Singleton implementation of a Spring bean - java

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.

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:
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();
}
}
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.

Related

Difference between creating new instance and using scope prototype annotation in Spring

My application is listening to an exchange (using rabbitMQ), expecting to receive some API data and then should redirect it to the relevant place.
I'm using rxJava to subscribe on these changes, when the purpose is to open a new thread and send the request by creating RestClient each time -> it will receive the data, parse it, send it and then send the response back to queue.
My problem is that I want each time to create a new instance of my RestClient. Thought of using Springs Scope annotation : #Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) but can't seem to understand how to use it and what will be the difference if I use new RestClient each time.
Can you please explain the advantage of using getBean over using new?
Here is the code:
class MyManager {
#Autowired
private WebApplicationContext context;
....
...
...
#PostConstruct
myListener.subscribeOn(Schedulers.computation()).subscribe(this::handleApiRequest);
private void handleApiRequest(ApiData apiData){
// Option 1:
RestClient client = new RestClient();
client.handleApiRequest(apiData);
//Option 2:
// use somehow the prototype?
RestClient x = (RestClient)context.getBean("restTest")..
}
}
#Service
//#Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //NEEDED??
class RestClient {
private String server;
private RestTemplate rest;
private HttpHeaders headers;
ResponseEntity<String> responseEntity;
#PostConstruct
private void updateHeaders() {
headers.add(Utils.CONTENT_TYPE, Utils.APPLICATION_JSON);
headers.add(Utils.ACCEPT, Utils.PREFIX_ALL);
}
public void handleApiRequest(ApiData apiRequest) {
sendRequest(apiRequest); //implemented
sendResponse(); //implemented
}
}
#Bean(name = "restTest")
#Scope("prototype")
public RestClient getRestTemplate() {
return new RestClient();
}
First of all, resttemplate is thread-safe. Don't instantiate it per request or using new keyword (Constructor), that is a bad design. Because you commented out #Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) here; and by default, spring will create a singleton bean of RestClient and you will get the same instance of RestClient wherever you autowire; so you are doing it right.
#Service
//#Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //NEEDED??
class RestClient {
I have a question here though, in RestClient, where are you instantiating private RestTemplate rest; I am not seeing that in the code that you posted
And if you are moving to singleton scope from prototype scope as suggested, you can use #Autowired RestClient restClient;
instead of
#Autowired private WebApplicationContext context;
RestClient x = (RestClient)context.getBean("restTest")
Less boilerplate.
When you use context.getBean the returned instance is a Spring bean, spring handles dependency injection, configuration, lifecycle callbacks... . When you just create it using new none of that happens. In the example you gave the #PostConstruct method is going to be called only if you use context.getBean.
When you use any bean returned by context.getBean(), then lifecycle of that bean will be handled by Spring.
But if you initialise bean with new instance, you are responsible for object creation and it's life cycle. (And hence #PostConstruct and other spring annotations inside that class will be meaningless.) And any dependencies inside that bean will not be injected.

Spring 4 #Service with #RequestScope

In order to optimize sql request, I've made a service that aggregate other services consumptions to avoid unecessary calls.
(Some pages of my webapp are called millions times by day, so I want to reuse the results of database queries as many times as possible on each request)
The solution I create is this one :
My service has #RequestScope instead of default scope (Singleton)
In MyService
#Service
#RequestScope
public MyService {
private int param;
#Autowired
private OtherService otherService;
#Autowired
private OtherService2 otherService2;
private List<Elements> elements;
private List<OtherElements> otherElements;
public void init(int param) {
this.param = param;
}
public List<Elements> getElements() {
if(this.elements == null) {
//Init elements
this.elements = otherService.getElements(param);
}
return this.elements;
}
public List<OtherElements> getOtherElements() {
if(this.otherElements == null) {
//Init otherElements
this.otherElements = otherService2.getOtherElements(param);
}
return this.otherElements;
}
public String getMainTextPres() {
//Need to use lElements;
List<Elements> elts = this.getElements();
....
return myString;
}
public String getSecondTextPres() {
//Need to use lElements;
List<Elements> elts = this.getElements();
//Also Need to use lElements;
List<OtherElements> otherElts = this.getOtherElements();
....
return myString;
}
}
In my controller :
public class myController {
#Autowired MyService myService;
#RequestMapping...
public ModelAndView myFunction(int param) {
myService.init(param);
String mainTextPres = myService.getMainTextPres();
String secondTextPres = myService.getSecondTextPres();
}
#OtherRequestMapping...
public ModelAndView myFunction(int param) {
myService.init(param);
String secondTextPres = myService.getSecondTextPres();
}
}
Of course, I've simplified my example, because myService use lots of other elements, and i protect the initialization of his members attributes
This method has the advantage of doing lazy loading of the attributes only when I need them.
If somewhere in my project (in same or other controller) I only need the SecondTextPres, then calling "getSecondTextPres" will initialize both lists which is not the case in my example beacuse the first list has been initialized when "getMainTextPres" was called.
My question are :
What do you think of this way of doing things ?
May I have performance issues because I instantiate my service on each request ?
Thanks a lot !
Julien
I think that your idea is not going to fly. I you call the same or different controller this is will be different request - in that case new bean will be created (elements and other elements are empty again).
Have you been thinking about caching? Spring has nice support where you can define cache expiration, etc
It's not quite clear to me what exactly you want to optimise instantiating Service in request scope? If you are bothered about memory foot print, you could easily measure it by JMX or VisualVM.
On the other hand, you could make all Service calls pure, i.e. depending on function parameters and (ofc) database state only and instantiate the Service with default scope as Singleton.
This decision will save you reasonable amount of resources as you will not instantiate possible large object graph on each call and will not require GC to clean the thing after Request is done.
The rule of thumb is to think why exactly you need the specific Class instantiated on every call and if it doesn't keep any state specific to call, make it Singleton.
Speaking about lazy loading, it always helps to think about worst case repeated like 100 times. Will it really save you something comparing to be loaded once and for the whole Container lifetime.

JSF managed property injection null inside REST resource

I have a REST resource class (so the one listening for incoming REST connections from the web) which needs to access a managed bean library controller.
Upon invocation however I get a null pointer exception.
#ApplicationPath("webresources")
#Path("/record")
#Stateless
public class RecordResource
{
#ManagedProperty(value = "#{libraryController}") // this references the #ManagedBean named libraryController
private LibraryController libraryController;
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadWeb(InputStream inputStream)
{
//Null exception below !
getLibraryController().function();
}
public LibraryController getLibraryController()
{
return libraryController;
}
public void setLibraryController(LibraryController libraryController)
{
this.libraryController = libraryController;
}
}
The getters/setters are ok so I don't know why the proper constructor for LibraryController is not called.
The injection fails because the client class is not a #ManagedBean, therefore the container has no notion of the JSF context inside RecordResource.
See this question for further clarification.
As a workaround, consider to use an #EJB controller and inject it by means of #EJB annotation. Otherwise please explain what's the business logic behind this design.

Invoke controller method from java class

I just want to know whether controller class method is accessible from another java class.
following is my controller and its method.
#Controller
public class TestResultUploadController {
#RequestMapping(method = RequestMethod.POST,value="/uploadTestResult")
public #ResponseBody
String uploadTestResult(String testResultBarcode,int deviceLoc) {
//some code goes here
return something;
}
I just want to call this controller method from another java class.
How can I make it work?
please suggest..
Short answer: yes, it is possible. In your other class/thread, you can do
// this will create a new instance of that controller where no fields are wired/injected
TestResultUploadController controller = new TestResultUploadController();
controller.uploadTestResult("someString", 1234);
However, keep in mind that your setup is highly unusual and all your autowired fields wouldn't be wired correctly. If you obtain your controller from the context, you'd be able to have your fields wired/injected properly:
// obtain controller bean from context, should have fields wired properly
TestResultUploadController controller = ctx.getBean(TestResultUploadController.class);
controller.uploadTestResult("someString", 1234);
or you can, in your other class, have:
#Autowired private TestResultUploadController controller;
....
public void doStuff(){
controller.uploadTestResult("someString", 1234);
}
Again, this is highly unusual, but highly possible. However, just cause something is possible to be done, doesn't mean you should do it. I would recommend the more common Spring/MVC approach in which you outsource the business logic to Services. Basically, to have something like this:
#Controller
public class TestResultUploadController {
#Autowired private UploadTestResultService uploadTestResultService;
#RequestMapping(method = RequestMethod.POST,value="/uploadTestResult")
public #ResponseBody String uploadTestResult(String testResultBarcode,int deviceLoc) {
return uploadTestResultService.uploadTestResult(testResultBarcode, deviceLoc);
}
}
And in your thread:
//somehow get the service
UploadTestResultService uploadTestResultService = //somehowGetTheService (whether from context or in some other way)
uploadTestResultService.uploadTestResult(testResultBarcode, deviceLoc);
That way, you'd be able to mock the UploadTestResultService in your tests of the controller, and you'd also be able to test the uploadTestResult method of that service on its own without it being in a controller.
EDIT:
How to obtain the Spring context is outside of the scope of this question. I assume you know basic Spring and also basic java.

Performance problems when using lots of AOP request scoped beans

I'm working on a semi-large application using Spring 3 and am running into performance problems when throwing hundreds of users at it at once. I'm using several request scoped beans using Spring's AOP proxy and I can see that every time I call any method on one of these beans, the CGLIB interceptor is invoked, which then calls AbstractBeanFactory.getBean(), which calls add() on a Synchronized Set of existing Spring beans. Since this add() is synchronized, it effectively locks up the server when there are thousands of calls to it all waiting to add to the same list.
Is there a way to get around this using request scoped beans? I read in the Spring documentation that CGLIB isn't used if the bean implements any interface (http://static.springsource.org/spring/docs/2.0.0/reference/aop.html#d0e9015) but my request scoped beans all implement one (the same one in fact) and it's still happening. And I definitely need the beans to be request scoped because some of their fields are calculated in one part of the app for a particular request and then I use SpEL to get their value in a different part of the app during the same request. I think if I made the beans prototype scoped, I'd have a fresh object when I used SpEL to get them the second time.
Here is a code sample that illustrates my problem. See the last two lines for comments describing where exactly I'm having issues.
<!-- Spring config -->
<bean name="someBean" class="some.custom.class.SomeClass" scope="request">
<property name="property1" value="value1"/>
<property name="property2" value="value2"/>
<aop:scoped-proxy/>
</bean>
<bean name="executingClass" class="some.other.custom.class.ExecutingClass" scope="singleton">
<property name="myBean" ref="someBean" />
</bean>
public Interface SomeInterface {
public String getProperty1();
public void setProperty1(String property);
public String getProperty2();
public void setProperty2(String property);
}
public class SomeClass implements SomeInterface {
private String property1;
private String property2;
public String getProperty1() { return propery1; }
public void setProperty1(String property) { property1=property;}
public String getProperty2() { return propery2; }
public void setProperty2(String property) { property2=property;}
}
public class ExecutingClass {
private SomeInterface myBean;
public void execute() {
String property = myBean.getProperty1(); // CGLIB interceptor is invoked here, registering myBean as a bean
String otherProperty = myBean.getProperty2(); // CGLIB interceptor is invoked here too! Seems like this is unnecessary. And it's killing my app.
}
}
My ideas are one of the following:
Can I make a Spring Bean request scoped without proxying every method call made on the bean? And without marking every method as "final"?
or...
Can I override Spring's bean factory to implement a Bean cache that will check if a bean is cached before calling AbstractBeanFactory.getBean()? And if so, where do I configure Spring to use my custom bean factory?
As it turns out, Spring actually does cache the request scoped beans, in the request attributes. If you're curious, take a look at AbstractRequestAttributesScope, which RequestScope extends:
public Object get(String name, ObjectFactory objectFactory) {
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
Object scopedObject = attributes.getAttribute(name, getScope());
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
attributes.setAttribute(name, scopedObject, getScope());
}
return scopedObject;
}
So while AbstractBeanFactory.getBean() does get called on every bean method call because of the aop proxy, it only causes Spring to add to that synchronized set if the bean wasn't already found in the request attributes.
Avoiding the proxying of every method call on my request scoped beans would still reduce complexity but with this caching in place, the performance impact would be minimal. I think the slow performance is something I'm going to have to live with if I want a ton of request scoped beans and still serve a ton of requests at a time.
Interesting question.
It turns out that Spring's scoped proxy doesn't cache resolved objects, so that every access to the scoped proxy causes getBean() to be called.
As a workaround, you can create a poor man's caching scoped proxy, something like this (untested, target bean should be request-scoped, but without <aop:scoped-proxy />):
public class MyScopedProxy implements SomeInterface, BeanFactoryAware {
private BeanFactory factory;
private Scope scope;
private String targetBeanName;
private ThreadLocal<SomeInterface> cache = new ThreadLocal<SomeInterface>();
private SomeInterface resolve() {
SomeInterface v = cache.get();
if (v == null) {
v = (SomeInterface) factory.getBean(targetBeanName);
cache.set(v);
scope.registerDestructionCallback(targetBeanName, new Runnable() {
public void run() {
cache.remove();
}
});
}
return v;
}
public void setBeanFactory(BeanFactory factory) {
this.factory = factory;
this.scope = ((ConfigurableBeanFactory) factory).getRegisteredScope("request");
}
public String getProperty() {
return resolve().getProperty();
}
...
}
Regarding the proxying mechanisms: unlike other AOP proxies, scoped proxies are CGLIB by default, you can override it by setting <aop:scoped-proxy proxy-target-class = "false" />, but it wouldn't help in this case.
One option is to replace injecting a scoped proxy with a lookup-method:
public abstract class ExecutingClass {
protected abstract SomeInterface makeMyBean();
public void execute() {
SomeInterface myBean = makeMyBean();
String property = myBean.getProperty1();
String otherProperty = myBean.getProperty2();
}
}
That will ensure Spring is asked for the bean only once per request, eliminate any overhead due to the scoped proxy, and shorten stack traces. It is less flexible (in that you can not arbitrarily share references to the request scoped bean and have the scoped proxy use the right bean) but you might not need the flexibility.

Categories

Resources