Trying to autowire Spring bean with property, but still getting NPE. Snippets:
INFO: Loading XML bean definitions from class path resource [autoWireByName.xml]
Exception in thread "main" today do push-ups for 30 mins
java.lang.NullPointerException
at com.springAutoWireByName.KabadiCoach.getFortune(KabadiCoach.java:23)
at com.springAutoWireByName.AutoWireByName.main(AutoWireByName.java:13)
KabadiCoach.java
package com.springAutoWireByName;
public class KabadiCoach {
private SadFortune sadFortune;
/*public KabadiCoach(){
System.out.println("inside default Constructor");
}*/
public String getDailyWorkout()
{
return "today do push-ups for 30 mins";
}
public void setSadFortune(SadFortune fortune) {
sadFortune = fortune;
}
public String getFortune() {
return sadFortune.getSadFortune();
}
}
SadFortune.java
package com.springAutoWireByName;
public class SadFortune {
public String getSadFortune()
{
System.out.println();
return "your day wont be good enough Sorry!!!";
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
<bean name="Fortune" class="com.springAutoWireByName.SadFortune">
</bean>
<bean id="myCoach" class="com.springAutoWireByName.KabadiCoach" autowire="byName" />
<!-- this is just a prototype to define actual just make use of this file-->
</beans>
main
package com.springAutoWireByName;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AutoWireByName {
public static void main(String[] args) {
ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("autoWireByName.xml");
KabadiCoach co = context.getBean("myCoach",KabadiCoach.class);
System.out.println(co.getDailyWorkout());
System.out.println(co.getFortune());
}
}
after running the above code I am getting the error message as listed and when I change the method to static
public static String getSadFortune()
{
System.out.println();
return "your day wont be good enough Sorry!!!";
}
In class 2 I got the desired output. Why?
Basically the SadFortune member is still null, which is why it works if the getSadFortune() method will be made static.
Until now you only tell Spring to instantiate a Fortune bean and a KabadiCoach, but you have to tell Spring that some members in the KabadiCoach need to be autowired too.
Try this in your Spring configuration file:
<bean id="fortune" class="com.springAutoWireByName.SadFortune"></bean>
<bean id="myCoach" class="com.springAutoWireByName.KabadiCoach" autowire="byName">
<property name="fortune" ref="fortune" />
</bean>
EDIT: Sorry, overread the autowire="byName" attribute. In this case you probably just have write the name in lower case.
<bean id="fortune" class="com.springAutoWireByName.SadFortune"/>
<bean id="myCoach" class="com.springAutoWireByName.KabadiCoach" autowire="byName"/>
Related
I am implementing Springcache with XML configuration and want to get rid of all the annotations. I just want to replace the annotations in the applicationContext.xml file. Here is my code -
//DummyBean.java
package com.spring.example;
interface DummyBean {
public String getCity();
}
//DummyBeanImpl.java
package com.spring.example;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
#EnableCaching
#CacheConfig(cacheNames={"myCache"})
public class DummyBeanImpl implements DummyBean {
private String city = "New York";
#Cacheable()
public String getCity() {
System.out.println("DummyBean.getCity() called!");
return city;
}
}
SpringAwareAnnotationXMLConfig.java
package com.spring.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
public class SpringAwareAnnotationXMLConfig {
public static void main(String[] args) throws Exception {
AbstractApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
DummyBean personService = (DummyBean) context.getBean("myBean");
System.out.println(personService.getCity());
System.out.println(personService.getCity());
System.out.println(personService.getCity());
((AbstractApplicationContext) context).close();
}
}
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd>
<context:annotation-config/>
<cache:annotation-driven cache-manager="cacheManager"/>
<context:component-scan base-package="com.spring"/>
<bean id="myBean" class="com.spring.example.DummyBeanImpl"/>
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="myCache"/>
</set>
</property>
</bean>
<cache:advice id="cacheAdvice" cache-manager="cacheManager">
<cache:caching cache="myCache">
<cache:cacheable method="getCity"/>
</cache:caching>
</cache:advice>
</beans>
As you can see if I keep the #EnableCaching, #CacheConfig, #Cacheable annotations in the Java code, then caching is working fine and I am getting the following output -
DummyBean.getCity() called!
New York
New York
New York
But if I remove the annotations, then I am getting the following output -
DummyBean.getCity() called!
New York
DummyBean.getCity() called!
New York
DummyBean.getCity() called!
New York
This means that the caching didn't work!
But my expectation is that in the applicationContext.xml file I have already enabled the cache by <cache:annotation-driven cache-manager="cacheManager"/>, I have already mentioned the cachename and I have already configured the cache with the method names where caching is to be implemented. So if I omit the annotations, I should get the desired output. But why I am not getting?
Thanks
Nirmalya
When using XML configured aspects you will also need to add an aop:config section to have the aspect applied.
<aop:config>
<aop:advisor advice-ref="cacheAdvice" pointcut="execution(* com.spring.example.DummyBean+.*(..))"/>
</aop:config>
Assuming DummyBean is an interface implemented by com.spring.example.DummyBeanImpl this should do the trick. This states that you want to apply the cacheAdvice (the aspect) to the bean matching the expression.
See also the reference guide
so I'm trying to run a sql query within this java app. I think I have the DAO set up correctly but it can't find the XML file which contains my queries. The code in question for my DAO implementation is:
private Properties queries;
public void setQueries(Properties queries) {
this.queries = queries;
}
public Boolean checkAssigned(String Id) {
String sql = queries.getProperty("CHECK_IF_ASSIGNED");
Map<String,Object> params = new HashMap<>();
List<String> assignedList;
params.put(":Id",Id);
LOG.info("Checking to see if already assigned \n" + "sql=" + sql
+ "\n" + "params=" + params);
assignedList = getNamedParameterJdbcTemplate().query(sql,params,
new assignedMapper());
if (assignedList == null || assignedList.size() == 0) {
ScreenVo.setSwitch(false);
}
else {
ScreenVo.setSwitch(true);
}
return ScreenVo.getSwitch();
}
My DAO is just:
public interface ScreenDao {
Boolean checkAssigned(String Id);
}
My queries.xml file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<util:properties id="queries">
<prop key="CHECK_IF_ASSIGNED">
<![CDATA[
--Long query
]]>
</prop>
</util:properties>
</beans>
The bean for the dao in the applicationContext.xml is:
<bean id="screenDaoImpl" class="com.corp.apps.actionator.dao.ScreenDaoImpl">
<property name="dataSource" ref="datasource"/>
<property name="queries" ref="queries"/>
</bean>
And my declaration of the queries file in the applicationContext is:
<import resource="classpath:queries.xml"/>
It's declared in my web.xml in a similar fashion.
I tried to include everything that could possibly be relevant. I've tried autowiring the bean in ScreenDaoImpl.java but that didn't work. I'm really not sure where to go from here, or what I might have done wrong.
EDIT:
The exception I'm getting is:
javax.faces.event.MethodExpressionActionListener.processAction java.lang.NullPointerException
And my screenDaoImpl is declared before use as:
private static ScreenDao screenDao = new ScreenDaoImpl();
Spring-Bean screenDaoImpl must be created through Spring context, in this case Spring can inject required properties (dataSource and queries) in created bean.
I don't know your architecture of application. But I can offer you a couple of ways.
1 - If you want use screenDaoImpl in spring-bean which declared in spring-xml then you can do it like this:
<bean id="screenServiceImpl" class="com.corp.apps.actionator.service.ScreenServiceImpl">
<property name="screenDao" ref="screenDaoImpl"/>
</bean>
The better way is make all your application in Spring. And create (and inject) beans by spring-context xml. Do not create bean-objects by new. Spring can not inject properties in these objects.
If it is difficult then try to find examples of applications on the Spring site. Maybe try spring-boot (without xml).
2 - If you want use screenDaoImpl in non-spring object you can get screenDaoImpl from spring-context by "bridge". Create class:
package com.corp.apps.actionator.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class AppSpringBridge implements ApplicationContextAware {
private static ApplicationContext context;
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
public static ApplicationContext getApplicationContext() {
return context;
}
}
Define bean in application-context.xml:
<bean id="springBridge" class="com.corp.apps.actionator.util.AppSpringBridge />
Spring create this bean, but method getApplicationContext() (and context property) of this bean is static. And we can use getApplicationContext() in any methods:
ScreenDao screenDao = (ScreenDao)AppSpringBridge.getApplicationContext().getBean("screenDaoImpl");
I fixed it, and for posterity's sake I'll post my solution here:
First I autowired my screenDao bean in the invoking class, and then I created a static method to set screenDao.
#Autowired
private static ScreenDao screenDao;
#PostConstruct
public static void setScreenDao(ScreenDao newScreenDao) {
screenDao = newScreenDao;
}
#PostConstruct
public ScreenDao getScreenDao() {
return screenDao;
}
I'm not really sure if getScreenDao does anything but I added it as well.
Then in my application context I created a bean I called initialize to invoke the static method.
<bean id="initialize" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="com.corp.apps.consolidator.backing.ScreenBean"/>
<property name="targetMethod" value="setScreenDao"/>
<property name="arguments">
<list>
<ref bean="screenDao"/>
</list>
</property>
</bean>
These two changes resolved my issue.
package com.mkyong.output;
IOutputGenerator.java
public interface IOutputGenerator
{
public void generateOutput();
}
package com.mkyong.output;
OutputHelper.java
#Component
public class OutputHelper {
#Autowired
IOutputGenerator outputGenerator;
public void generateOutput() {
outputGenerator.generateOutput();
}
/*//DI via setter method
public void setOutputGenerator(IOutputGenerator outputGenerator) {
this.outputGenerator = outputGenerator;
}*/
}
package com.mkyong.output.impl;
CsvOutputGenerator.java
#Component
public class CsvOutputGenerator implements IOutputGenerator {
public void generateOutput() {
System.out.println("This is Csv Output Generator");
}
}
SpringBeans.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com.mkyong" />
</beans>
i am getting this exception Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'OutputHelper' is defined
even though i have marked OutputHelper as component.
I have changed
OutputHelper output = (OutputHelper) context.getBean("OutputHelper");
to
OutputHelper output = (OutputHelper) context.getBean("outputHelper");
and it worked.
Hi i think you haven't added following in your Spring XML configuration
xmlns:mvc="http://www.springframework.org/schema/mvc"
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
<mvc:annotation-driven/>
you need to see top exception and read the whole line.
i guess there have a exception is nested exception just like #Autowired xxxxxx,meas autowired fail.
i have notice this:
#Autowired
IOutputGenerator outputGenerator;
and
#Component
public class CsvOutputGenerator implements IOutputGenerator
so, in the default, class name is used to #Autowired,you can rewrite to
#Autowired
IOutputGenerator csvOutputGenerator;
notice:
"csvOutputGenerator" first letter is lowercase
the easier option would be to enable annotations in beans already registered in the application context, means that you can just use #Autowired instead of getting manually all beans with context.getBean()
just add this line to your SpringBeans.xml
<context:annotation-config>
if you really want to understand what you are doing reading this could help.
I am learning JdbcTemplate with Spring and when i am running my java application i am getting null pointer on this line:
return jdbcTemplate.queryForMap(sql, id);
Please find the whole class below:
public class CustomerDaoImpl implements CustomerDAO{
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource ds) {
dataSource = ds;
}
public Map getCustomerById(String id) {
String sql = "SELECT * FROM CUSTOMER WHERE CUST_ID = ?";
return jdbcTemplate.queryForMap(sql, id);
}
Please find my SpringContext file below:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Scans within the base package of the application for #Components to
configure as beans -->
<context:property-placeholder location="classpath:db.properties" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<bean id="customerDAO" class="com.tuto.dao.impl.CustomerDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
Please find my Main method below:
public class JdbcTemplateApp {
public static void main(String[] args) {
// if you have time,
// it's better to create an unit test rather than testing like this :)
ApplicationContext context = new ClassPathXmlApplicationContext(
"integration.xml");
CustomerDAO customerDAO = (CustomerDAO) context.getBean("customerDAO");
Map customerA = customerDAO.getCustomerById("1");
System.out.println("Customer A : " + customerA);
}
}
Please find below my exception in eclipse console:
INFO: Loaded JDBC driver: oracle.jdbc.driver.OracleDriver
Exception in thread "main" java.lang.NullPointerException
at com.tuto.dao.impl.CustomerDaoImpl.getCustomerById(CustomerDaoImpl.java:23)
at com.tuto.main.JdbcTemplateApp.main(JdbcTemplateApp.java:23)
Any idea why it is null please?
Thanks in advance for any help
Change setDataSource to:
public void setDataSource(DataSource ds) {
jdbcTemplate = new JdbcTemplate(ds);
}
You can extend org.springframework.jdbc.core.support.JdbcDaoSupport in your DAOImpl Class and use inherited getJdbcTemplate() method to get the jdbcTemplate. in this case you can remove the variable jdbcTemplate from your class
You never initialize jdbcTemlpate instance variable. In this case it's initialized as null and you're getting NullPointerException (you can't call methods on null). You need to initialize jdbcTemplate by yourself.
To quote Java Language Specification:
Each class variable, instance variable, or array component is
initialized with a default value when it is created [...] For all
reference types the default value is null.
I am attempting a java application that has two beans it gets through Spring, one retrieved by name and one autowired. Here is that code:
package firstspring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class FirstSpring
{
private final static Logger logger = LoggerFactory.getLogger(FirstSpring.class);
#Autowired
private Car currentCar;
public void setCurrentCar(Car car) { this.currentCar = car; }
public Car getCurrentCar() { return currentCar; }
private static void say(String message) { System.out.println(message); }
public static void main(String[] args)
{
FirstSpring firstSpring = new FirstSpring();
firstSpring.go();
}
public void go()
{
logger.info("here we go");
ApplicationContext appContext = new ClassPathXmlApplicationContext("/appContext.xml");
Car firstCar = (Car)appContext.getBean("firstCar");
say ("firstCar was " + firstCar.getColor());
say ("currentCar is " + currentCar.getColor());
}
}
and its configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
<bean id="firstCar" class="firstspring.Car">
<property name="color" value="blue" />
<property name="doors" value="2" />
<property name="transmission" value="automatic" />
</bean>
<bean id="currentCar" class="firstspring.Car" >
<property name="color" value="red" />
<property name="doors" value="4" />
<property name="transmission" value="5-speed" />
</bean>
<bean id="firstSpring" class="firstspring.FirstSpring">
<property name="currentCar" ref="currentCar" />
</bean>
</beans>
And the Car class just to make it complete:
package firstspring;
public class Car
{
String color;
int doors;
String transmission;
public String getColor() { return color; }
public void setColor(String color) { this.color = color; }
public int getDoors() { return doors; }
public void setDoors(int doors) { this.doors = doors; }
public String getTransmission() { return transmission; }
public void setTransmission(String transmission) { this.transmission = transmission; }
}
I get a null pointer exception:
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#5e6458a6: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,firstCar,currentCar,firstSpring,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
Exception in thread "main" java.lang.NullPointerException
at firstspring.FirstSpring.go(FirstSpring.java:33)
at firstspring.FirstSpring.main(FirstSpring.java:23)
firstCar was blue
I've tried various other things -- putting 'byName' on the currentCar bean in the configuration, but I don't think that's necessary according to what documentation I've read. What am I missing here?
When you say new FirstSpring(), you're creating your own instance of that class which is outside of Spring's control, so Spring can't autowire it. Therefore when you get to currentCar.getColor(), currentCar is null. For this to work properly, you'd need to create your ApplicationContext in the main method, get the FirstSpring instance from Spring, and invoke go() on that instead of creating the object yourself.
In short, Spring cannot and will not manage (that is, autowire, initialize, destroy, etc.) any object that it didn't create itself.*
*Unless you're using AspectJ with bytecode weaving to accomplish this, but that's a rather advanced topic that you probably don't want to touch yet, unless you have other experience with AspectJ.