SpringMvc Instantiating Beans - Singleton - java

In the under mentioned code i created this because i was getting java.lang.NullPointerException see my error log under. When i implemented this it was fixed and it worked perfectly. However i was told by one of the members here that -
"you are creating new beans for every call to getOfficerRegistrationValidation. this includes recreating the database objects which are every expensive and can cost error if some object are supposed to be created only once (singleton). you should find a way to make OfficerRegistrationValidation reusable and threadsafe so that you can have only one of it and inject this to wherever you want using only IoC"
and i think hes right can someone tell me whats the best way to do this without having to instantiate all my beans again. I just want to instantiate only the certain beans and not run into this problem.
public final class BeanFactory() {
private static ClassPathXmlApplicationContext context;
private static ClassPathXmlApplicationContext getContext() {
if (context== null) {
context = new ClassPathXmlApplicationContext("applicationContext.xml");
}
return context;
}
public static OfficerRegistrationValidation getOfficerRegistrationValidation() {
return (OfficerRegistrationValidation) getContext().getBean("officerRegistrationValidation");
}
}
In the controller make a call like : `BeanFactory.getOfficerRegistrationValidation().validate(....)
Error Log:
java.lang.NullPointerException
at com.crimetrack.service.OfficerRegistrationValidation.validate(OfficerRegistrationValidation.java:51)
at org.springframework.validation.DataBinder.validate(DataBinder.java:725)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doBind(HandlerMethodInvoker.java:815)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:367)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Unknown Source)

I'm going to hazard a guess at what you are asking about (as your question doesn't provide your motivation for using a beanfactory and doesn't provide enough code to give a complete picture)...
Spring beans are by default instantiated as singletons. So you should be able to configure Spring to create your OfficerRegistrationValidation object using either XML or annotation (#Component) and then get it injected into your controller by using the #Inject annotation.
Annotations are the way to go - just make sure you have the following in your Spring config XML (applicationContext.xml):
<context:component-scan base-package="com.acme.project" />
<mvc:annotation-driven />
Then simply add the #Component annotation to the class declaration of your OfficerRegistrationValidation class:
#Component
public class OfficerRegistrationValidation {
// ...
}
and then in your controller, declare a field for your OfficerRegistrationValidation and annotate it thus:
#Controller
public class MyController {
#Inject
private OfficerRegistrationValidation officerRegistrationValidation;
// ...
}
Now you will have access to the OfficerRegistrationValidation singleton bean in your controller - only ~4 lines of code needed!

Related

Spring: How can I debug a BeanCreationNotAllowedException?

I am trying to add a new Spring bean to one of my projects. The bean is defined and created in another package like so:
#Configuration
public class UtilityBeans {
public static String MY_BEAN_NAME = "my.bean.name";
#Bean(name = MY_BEAN_NAME)
public MyUtilBeanClass getMyBeanClass() {
return new MyUtilBeanClass();
}
}
I use it in my other package like this:
#Configuration
#Import({
UtilityBeans.class
)}
...
#Resource(name = UtilityBeans.MY_BEAN_NAME)
private MyUtilBeanClass myUtilBeans;
During runtime I get:
ERROR
Caused by: org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'my.bean.name': Singleton bean creation not allowed while the singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
...
The logs do not give me any useful information as the stack trace is all in Spring library. How can I find out what failed? Is it incorrect usage of resource or is it that the bean creation itself is wrong?
I am using Spring-4 with JDK8.
The issue here was that the bean was being created in 2 different points in my spring configuration due to some refactoring and the fix was to remove duplicate code. I had the same bean creation code:
#Bean(name = MY_BEAN_NAME)
public MyUtilBeanClass getMyBeanClass() {
return new MyUtilBeanClass();
}
... in another class I had half way refactored.
In this case my mistake was that I did not grep across all the log files being generated. The exceptions were being split and then buried into 2 different logs, one for a server start up and one for application runtime. The above exception was being posted to the application log. The other logs contained the relevant exception which stated that duplicate bean creation failed and the fix was to remove duplicate code.

WebBeans context with scope type annotation #RequestScoped does not exist within current thread

I'm using OpenJPA at TomEE server.
I build my .war, deploy it on server but i get this execption when i open page with my application:
javax.servlet.ServletException: WebBeans context with scope type annotation #RequestScoped does not exist within current thread
javax.faces.webapp.FacesServlet.service(FacesServlet.java:229)
filters.NoCacheFilter.doFilter(NoCacheFilter.java:42)
org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:98)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:145)
javax.enterprise.context.ContextNotActiveException: WebBeans context with scope type annotation #RequestScoped does not exist within current thread
org.apache.webbeans.container.BeanManagerImpl.getContext(BeanManagerImpl.java:351)
org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.getContextualCreationalContext(NormalScopedBeanInterceptorHandler.java:169)
org.apache.webbeans.web.intercept.RequestScopedBeanInterceptorHandler.getContextualInstance(RequestScopedBeanInterceptorHandler.java:79)
org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.invoke(NormalScopedBeanInterceptorHandler.java:114)
org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.invoke(NormalScopedBeanInterceptorHandler.java:108)
org.apache.webbeans.conversation.ConversationImpl_$$_javassist_0.isTransient(ConversationImpl_$$_javassist_0.java)
org.apache.webbeans.jsf.WebBeansPhaseListener.beforePhase(WebBeansPhaseListener.java:106)
org.apache.myfaces.lifecycle.PhaseListenerManager.informPhaseListenersBefore(PhaseListenerManager.java:77)
org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:158)
org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:197)
filters.NoCacheFilter.doFilter(NoCacheFilter.java:42)
org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:98)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:145)
Ok, I find where is problem.
First of all, I had to read log of starting my TomEE server. I found there, that I have problem with one of my EJB class. I inject there resource with transaction manager:
#Resource
private UserTransaction userTransaction;
but I forgot to anotate my service EJB by:
#Stateless
#TransactionManagement(TransactionManagementType.BEAN)
public class TaskService {
...
}
This might also happen if "someone" uncritically deletes the login page for the application.

Finding template files in velocity

My webapp cannot find its template file. I have read the material in this article, but it doesn't seem to solve the problem. My velocity.properties file, which is installed into my WEB-INF directory, contains the lines
resource.loader=class
resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
and the Java servlet is
package test;
import java.io.*;
import javax.servlet.http.*;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.context.Context;
import org.apache.velocity.tools.view.VelocityViewServlet;
import org.apache.velocity.app.Velocity;
import org.apache.commons.lang.StringEscapeUtils;
public class Recipes extends VelocityViewServlet {
public Template handleRequest(HttpServletRequest request,
HttpServletResponse response,
Context context) {
Velocity.init();
Template template=null;
try {
context.put("recipeList","r1");
template = Velocity.getTemplate("Recipes.vm");
} catch (Exception e) {
System.err.println("Exception caught: " + e.getMessage());
}
return template;
}
}
When I navigate to that URL, it fails. I've tried placing the vm file in the WEB-INF directory, in the classes subdirectory, in the lib directory, and in a jar in the lib directory. After things fail, catalina.out contains
Jan 12, 2013 6:35:25 PM org.apache.velocity.runtime.log.CommonsLogLogChute log
SEVERE: ResourceManager : unable to find resource 'Recipes.vm' in any resource loader.
Exception caught: Unable to find resource 'Recipes.vm'
and in localhost.log
Jan 12, 2013 6:35:25 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet recipes threw exception
java.lang.NullPointerException
at org.apache.velocity.tools.view.VelocityView.performMerge(VelocityView.java:942)
at org.apache.velocity.tools.view.VelocityView.merge(VelocityView.java:902)
at org.apache.velocity.tools.view.VelocityViewServlet.mergeTemplate(VelocityViewServlet.java:318)
at org.apache.velocity.tools.view.VelocityViewServlet.doRequest(VelocityViewServlet.java:220)
at org.apache.velocity.tools.view.VelocityViewServlet.doGet(VelocityViewServlet.java:182)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:619)
Can someone explain to me what is going on? Thanks.
You should be using:
class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
The resource loader "type" precedes the property name defining the loader class.
See the Velocity Developer Guide to Resource Loaders. Note that the answer you link to points at the correct docs but doesn't (appear) to include the correct config
(All this said, are you sure that's how you're supposed to use the VelocityViewServlet? I thought you'd normally request the *.vm file, do something like a fillContext, and be done with it.)
You're calling Velocity.init() from within a VelocityViewServlet, which is most likely not what you want to do. That aside, from the docs:
initialize the Velocity runtime engine, using the default properties of the Velocity distribution
If you do the following, the configuration I show works:
String propFile = getServletContext().getRealPath("/WEB-INF/velocity.properties");
Velocity.init(propFile);
That said, I'm not convinced you're going about this the right way, but I could be mistaken--I've never used it in a standalone web app before, but this doesn't strike me as being correct.
If nothing else, I'd at least move some stuff into a base class, like:
public abstract class BaseVelocityServlet extends VelocityViewServlet {
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
Velocity.init(getServletContext().getRealPath("/WEB-INF/velocity.properties"));
}
#Override
protected Template getTemplate(HttpServletRequest request, HttpServletResponse response) {
return Velocity.getTemplate(getTemplateName());
}
public abstract String getTemplateName();
}
Then each URL's servlet can just fill the context and provide a template name:
public class Recipes extends BaseVelocityServlet {
#Override
protected void fillContext(Context context, HttpServletRequest request) {
context.put("recipeList", "r1");
}
#Override
public String getTemplateName() {
return "Recipes.vm";
}
}
Again, I'm not convinced this is right; I'm still under the impression that it should be finding the config file under WEB-INF by default, but for me, at least, it's not.

spring MVC3 errors Could not instantiate bean class [java.util.List]: Specified class is an interface Occasional

I am using spring MVC3, I found code like below:
#Controller
class IndexController
{
#ModelAttribute("allTags")
public List<ArticleTag> allTags()
{
return Collections.emptyList();
}
}
Sometimes errors with message
(Not always)
SEVERE: Servlet.service() for servlet [appServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [java.util.List]: Specified class is an interface] with root cause
org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [java.util.List]: Specified class is an interface
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:101)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:81)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:103)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:75)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:156)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:117)
at org.springframework.web.method.annotation.ModelFactory.invokeModelAttributeMethods(ModelFactory.java:123)
at org.springframework.web.method.annotation.ModelFactory.initModel(ModelFactory.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:614)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
Someone Says, List is a interface, plz use ArrayList or LinkedList instead
But, My Question is, Why the code above is not always eror?
When the error above occured, not matter how to refresh the page, error continues, nevery disappear!But, If you restart tomcat, you have a good opportunity to walk through this error!If no error like above occur,it never occurs util next tomcat restart!
Same as #ModelAttribute with type int or Integer, it will very likely error, but on some host, It never occurs
Change the code as below
public ArticleTag allTags()
For more information, please refer to below link
[http://forum.spring.io/forum/spring-projects/data/nosql/724397-mapping-exception-with-mongodb-aggregation-framework][1]
Also refer to Mongo Issue fixed
[https://jira.spring.io/browse/DATAMONGO-229]

java.lang.IllegalArgumentException: setAttribute: Non-serializable attribute

I have inherited some code and am getting an error when I try to run it. The error is below:
10:08:32,093 ERROR [MyServlet]:260 - Servlet.service() for servlet MyServlet threw exception
java.lang.IllegalArgumentException: setAttribute: Non-serializable attribute
at org.apache.catalina.session.StandardSession.setAttribute(StandardSession.java:1270)
at org.apache.catalina.session.StandardSession.setAttribute(StandardSession.java:1248)
at org.apache.catalina.session.StandardSessionFacade.setAttribute(StandardSessionFacade.java:130)
at uk.co.my.servlet.MyServlet.doPost(MyServlet.java:121)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at com.my.ddi.security.SecurityContextServletFilter.doFilter(SecurityContextServletFilter.java:55)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:835)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:640)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1286)
at java.lang.Thread.run(Unknown Source)
I imagine that the main problem is where it is hitting my code at uk.co.my.servlet.MyServlet.doPost(MyServlet.java:172). Line 121 of MyServlet is
session.setAttribute("LISTENER", myListener);
This myListener object is from the following class:
public class myListener {
static Log log = LogFactory.getLog(TerminationListener.class.getName());
private boolean shouldCancel = false;
How would I go about getting rid of this error? Would I need to use the transient keyword?
If you want an instance of myListener to be placed in a session, you need to make it serializable. That might involve making some fields transient, but then those fields won't be saved in the session. You'll also need to make the class implement Serializable.
I suggest you look at the documentation for Serializable, which goes into a fair amount of detail about serialization.

Categories