I have create a service bean and declare variable . Pseudocode : //one class
@Service
@Transactional(propagation=Propagation.REQUIRES_NEW)
public class CustomerService {
public Map<Long,Boolean> someMap= new HashMap<>();
}
//caller class
@Component
@Path("/maincontroller")
class MainCaller{
@Autowired
CustomerService customerService;
@POST
@Path("/process")
public Response processCustomer() {
try{
//some processing
}finally{
synchronized (customerService.someMap) { //liee 64
//do some work on map
}
}
}
I am getting null pointer exception @liee a i dont understand this. As far i know spring creates bean after initializing all its properties. and as i declared someMap with new variable it should not be null. then why it is giving null pointer exception. ERROR :
com.sun.jersey.spi.container.ContainerResponse mapMappableContainerException SEVERE: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container java.lang.NullPointerException at org.hungama.controller.MainCaller.processCustomer(MainCaller.java:64)
//Web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/rest-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>
com.sun.jersey.spi.spring.container.servlet.SpringServlet
</servlet-class>
<init-param>
<param-name>
com.sun.jersey.config.property.packages
</param-name>
<param-value>org.test.controller</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
//SPRING-CONTEXT
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<import resource="rest-datasource.xml" />
<context:component-scan base-package="org.test" />
<mvc:annotation-driven />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/retailser_detaults.properties</value>
<value>classpath:/log4j.properties</value>
</list>
</property>
</bean>
</beans>
//pom.xml
<!-- Jersey -->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.8</version>
</dependency>
just to clarify:
reason:
1. you are using @Transactional, so you need to understand it works with AOP, see here Spring transaction management.
2. You annotated you service class, which implements no interface, which means spring will use CGLIB to implement transaction management. (If you have an interface, it will use proxy pattern to implement transaction management).
3. CGLIB modifies your byte code of this class, which causes the NPE
Solution: use getter/setter pattern to void direct access of public field.
Misc: IMO it is not a good practice to use public field. Static cache using map could cause potential memory leak.