0

We have a Spring bean implemented as a singleton (default). This bean is used as part of an web-service, and at times when multiple simultaneous requests are triggered, the responseholder (singleton bean) throws a NullPointerException when trying to retrieve. This usually happens when the response is build, and then a new request is triggered before sending the original response back.

Can this be due to the Singletion implementation of the bean? If yes, is there wouldn't changing to prototype solve my problem. What about initiating it with the new operator always? Will there be any performance impacts on doing so? Or is there a better way.

Any help would be greatly appreciated.

Edit:

Code details

public class BuildToolRequestProcessor {

private BuildToolResponse buildToolResponse;
.....


//And it has been referenced in the code in different methods, setting the response details..

public String process(BuildToolRequestXml buildToolRequestXml) throws Exception {

buildToolResponse.setLocation(location);
...


public String handleDetails(BuildToolRequestXml buildToolRequestXml) throws Exception {


buildToolResponse.setSchedule(schedule);
...

// And in another method, when I try to retrieve the Location, it throws a Null Pointer Exception..

buildToolResponse.getLocation().getPinCode()


//Bean configuration

<bean id="buildToolResponse"
      class="com.raj.buildTool.processor.BuildToolResponse"/>

Additional Notes: I tried introducing a delay before bulding the response of the first request, shooting another request. The second request resets the Location to NULL, and hence NPE is thrown while trying to retrieve the Location. Could this be because of the singleton? Also I haven't used initialized the buildToolResponse again with the new operator, but the class BuildToolResponse extends from BuildToolResponseBuilder, which I am initializing using 'new' to build the response.

Chillax
  • 4,418
  • 21
  • 56
  • 91

1 Answers1

1

Can this be due to the Singletion implementation of the bean? If yes, is there wouldn't changing to prototype solve my problem.

If you have a singleton bean, make sure that this bean does not maintain any state. This means, it should not have any field that is reinitialized based on some methods, except for the injection of another beans or resources that is done by Spring. This may cause concurrency issues, specially when the bean is used in several threads (in this case, to attend multiple requests done to your web service).

This is an example of a bad design for a Spring bean that will be used on multiple threads:

@Component
public class SingletonByDefaultBean {
    private StringBuilder responseBuilder;

    @Autowired
    private FooService fooService;

    public String methodUsedInSeveralThreads() {
        //here you will have a concurrency issue
        responseBuilder = new StringBuilder();
        //write contents into the response
        //...
        //return the response
        return responseBuilder.toString();
    }
}

To solve this, you have two approaches:

  1. Remove any state of the bean and move the attributes into method local variables:

    @Component
    public class SingletonByDefaultBean {
        //private StringBuilder responseBuilder;
    
        @Autowired
        private FooService fooService;
    
        public String methodUsedInSeveralThreads() {
            StringBuilder responseBuilder = new StringBuilder();
            //write contents into the response
            //...
            //return the response
            return responseBuilder.toString();
        }
    }
    
  2. Change the scope of the bean to prototype

    @Component
    @Scope("prototype")
    public class SingletonByDefaultBean {
        private StringBuilder responseBuilder;
    
        @Autowired
        private FooService fooService;
    
        public String methodUsedInSeveralThreads() {
            responseBuilder = new StringBuilder();
            //write contents into the response
            //...
            //return the response
            return responseBuilder.toString();
        }
    }
    

What about initiating it with the new operator always?

Refer to this answer to know how you can create instances your classes manually and make them been managed by Spring. It is not that easy and I would recommend using these approaches only if you really understand what you're doing.

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • Thanks. The first option you provided by using the new operator, will it be having performance impacts? – Chillax Apr 28 '14 at 15:22
  • @Chillax that will depend on what the bean does after being created. If you execute a heavy long running task after the bean creation, then yes, it will have impact in performance... That question cannot be answered easily without seeing the design of your bean. – Luiggi Mendoza Apr 28 '14 at 15:25
  • Have added the implementation details. If you could have a look please? – Chillax Apr 29 '14 at 11:40
  • @Chillax looks like there won't be any performance impacts. But it's up to you to test it and demonstrate it. – Luiggi Mendoza Apr 29 '14 at 14:23
  • Thanks. but since I'm not using new for initializing the response, it is not re initialized yea? Then why would this occur, any idea? – Chillax Apr 29 '14 at 14:27
  • @Chillax if you change it to prototype, Spring will create the bean for you. Note that my post using `new` is another option, not among the 2 first options of my original answer. – Luiggi Mendoza Apr 29 '14 at 14:27
  • But here I believe my bean i.e buildToolResponse is stateless? Or is it? Why would it have a concurrency issue? Sorry for bothering you with lots of questions! – Chillax Apr 29 '14 at 15:40
  • @Chillax keep it simple: if your bean is singleton scoped (default), it should be stateless to avoid concurrency issues. If you want to maintain state in a Spring bean, make it prototype scoped. – Luiggi Mendoza Apr 29 '14 at 15:42
  • I do not want to maintain state. How has my bean become stateful here? – Chillax Apr 29 '14 at 15:53
  • @Chillax do you understand what it means for a class to maintain state? – Luiggi Mendoza Apr 29 '14 at 15:55
  • Oops. Since I change the instance variables using the setters, this changes the state, yea? – Chillax Apr 29 '14 at 16:04
  • @Chillax in fact, the bean that maintains state is `BuildToolResponse`. If a bean needs to have another stateful bean (this means, a bean that maintains state) as an attribute then the current bean will also become stateful. – Luiggi Mendoza Apr 29 '14 at 16:06