javaspringspring-mvcjersey

spring property initialization issue


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>

Solution

  • 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.