1

this may be a very novice question, but I have searched and either I have a large gap in my understanding or am doing something incorrectly that I cannot figure out.

In my context file here is an excerpt

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${datasource.driverClassName}" />
    <property name="url" value="${datasource.url}" />
    <property name="username" value="${datasource.username}" />
    <property name="password" value="${datasource.password}" />
</bean>

<bean id="myBeanOne" class="a.b.c.myBeanOne">
         <property name="dataSource" ref="dataSource" />
</bean>

Now in myBeanOne I have:

private DataSource dataSource;

private JdbcTemplate jdbcTemplate;

@Autowired
public void setDataSource (DataSource dataSource) {
    this.jdbcTemplate = new JdbcTemplate(dataSource);
}

public void myMethod() {
    String sql = "'My generic SQL update query'";
    try {
        this.jdbcTemplate.update(sql);
    } catch (org.springframework.dao.EmptyResultDataAccessException ex) {
    }
    System.exit(0);
}

when I try to execute this on the line where setDataSource is invoked I get this error:

ERROR org.springframework.integration.handler.LoggingHandler 
    org.springframework.integration.MessageHandlingException: 
       java.lang.NullPointerException

on the line: this.jdbcTemplate.update(sql);

I have tried maybe ten different configurations to get this to work, but I cannot seem to do it. Any assistance is appreciated, thank you.

Edit: as per Luiggi's comment:

//in yet another classes run method
myBeanOne bOne = SomeOtherClass.create();   //just returns new myBeanOne
bOne.myMethod();

Neither SomeOtherClass or this class are classified as beans in the context or have any presence in the context.

I know that this is a very basic question but I am struggling with it.

Thank you for your patience.

Gray
  • 115,027
  • 24
  • 293
  • 354
Jay Mie
  • 65
  • 1
  • 2
  • 8
  • You missed the main problem: How are you calling `MyBeanOne#myMethod`? – Luiggi Mendoza Jul 23 '13 at 19:54
  • It is being invoked from another class (which is not in the context file). – Jay Mie Jul 23 '13 at 19:56
  • Check if you see any errors in stack trace, it happens if a database connection was not established.Other than that, I don't see issue with code. – Phani Jul 23 '13 at 20:00
  • @Phani the error is `NullPointerException` (read the question one more time). – Luiggi Mendoza Jul 23 '13 at 20:01
  • Add the code where you use this `MyBeanOne` instance, probably you're not using it right or initializing it by yourself, thus getting NPE when using `jdbcTemplate` variable in `myMethod`. – Luiggi Mendoza Jul 23 '13 at 20:02
  • @LuiggiMendoza So what, if you datasource is not initialized then it will throw the exception and will not autowire the object which is going to be null. – Phani Jul 23 '13 at 20:04
  • @Phani it is initialized, check the configuration. The problem seems to be how this `MyBeanOne` instance is used. – Luiggi Mendoza Jul 23 '13 at 20:05
  • @LuiggiMendoza So, if autowiring is failed and throwed the exception, it would still let him call because the calling code is in some other class. – Phani Jul 23 '13 at 20:09
  • @Phani if autowiring failed then the exception would be a different one than `NullPointerException`, the whole artifact won't be generated to begin with. – Luiggi Mendoza Jul 23 '13 at 20:10
  • @LuiggiMendoza Ah..!! Probably I missed that. Thanks. – Phani Jul 23 '13 at 20:13
  • Now, how `SomeOtherClass.create()` creates the `MyBeanOne` object, it uses the Spring factory or it returns a naive `new MyBeanOne()`? – Luiggi Mendoza Jul 23 '13 at 20:15
  • Thank you for the discussion...I added in some of the relevant code (which is likely where the problem stems from). Any suggestions on what to do ? I have been parsing spring documentation etc. but with no luck – Jay Mie Jul 23 '13 at 20:16
  • @Luiggi it returns a naive new MyBeanOne(); which I guess would be a problem judging by your question? – Jay Mie Jul 23 '13 at 20:17

2 Answers2

5

As noted in comments, the problem is that you're manually creating the bean instead of letting Spring container create it. Basically, you're doing this:

new MyBeanOne()

So Spring container can't inject any of the fields you have configured thus being null e.g. jdbcTemplate field. There are some solutions to this:

  1. Convert your SomeOtherClass into a bean managed by Spring container and let it inject the MyBeanOne instance (probably using @Autowired annotation).

  2. If latter approach can't be done since you need to manually create the bean, you can create the bean manually as shown here: How to create spring beans dynamically?

    But this implementation makes you hardcode somewhere the spring config file name and use it in your code. So, a better approach would be option 3.

  3. Look at this solution: Creating New Spring Beans on Demand, where you create a client abstract class with a method that Spring will implement to retrieve a new instance of your Spring managed bean.


I found another way to handle this by using @Configurable annotation. By decorating your bean with this annotation, you can create a new instance of the bean on demand and Spring will manage the injection of Spring managed beans for you. But to achieve this, Spring needs to use aspects behind the scenes and you should activate usage of aspects for your project. The explanation is quite long, so I provide links that explain in depth this solution:

Note that in order to enable this feature, you have to add a java agent when starting the JVM that will weave the class at runtime using aspects.

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
0

NullPointerException on the line: this.jdbcTemplate.update(sql);

If the NPE is actually on that line, then this.jdbcTemplate is obviously null. If this is true then either:

  • The setDataSource(...) method is not being called in Spring, possibly because the @Autowired is not right somehow. It would be easy to add a System.out.println(...) or put a debugging breakpoint in setDataSource to see if it is being called.

  • If it is being called then maybe there are more than one instance of a.b.c.myBeanOne? Are you for sure getting the instance being called from another class from the Spring context? Put a breakpoint in setDataSource and notice the this object reference id. Then put a breakpoint on the this.jdbcTemplate.update(...) line and make sure that the this reference-id is the same.

Gray
  • 115,027
  • 24
  • 293
  • 354