Spring methods being called twice - spring

I have a Spring, PrimeFaces JSF application configured to load an application through a class that implements WebApplicationInitializer rather than web.xml (I do still have a bare web.xml) though. The problem is on application start and basically throughout the whole application, methods are being called twice! Best explanation I found is possible double loading of one of the listeners. I don't see I'm doing that. Attached is my WebApplicationInitializer class below. I'm not sure what to else to provide to resolve my issue. Even managed bean methods are being called twice.
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
final CharacterEncodingFilter cf = new CharacterEncodingFilter();
cf.setEncoding("UTF-8");
cf.setForceEncoding(true);
servletContext.addListener(new RequestContextListener());
servletContext
.addFilter(
"ShiroFilter",
org.apache.shiro.web.servlet.IniShiroFilter.class)
.addMappingForUrlPatterns(null, false, "/*");
final WebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
final ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("*.do");
}
private AnnotationConfigWebApplicationContext getContext() {
final AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
return context;
}
}
My web.xml has the standard definitions for faces and the following mapping:
.....
<context-param>
<param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</param-name>
<param-value>true</param-value>
</context-param>
.....
<!-- JSF Mapping -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
When the application starts up, I see output from Spring that is also duplicated!
2013-12-12T11:29:56.430-0500|INFO: [org.springframework.web.context.support.AnnotationConfigWebApplicationContext] - Refreshing Root WebApplicationContext: startup date [Thu Dec 12 11:29:56 EST 2013]; root of context hierarchy
2013-12-12T11:29:56.430-0500|INFO: [org.springframework.web.context.support.AnnotationConfigWebApplicationContext] - Refreshing Root WebApplicationContext: startup date [Thu Dec 12 11:29:56 EST 2013]; root of context hierarchy
2013-12-12T11:29:56.978-0500|INFO: [org.springframework.context.annotation.ClassPathBeanDefinitionScanner] - JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning
2013-12-12T11:29:56.978-0500|INFO: [org.springframework.context.annotation.ClassPathBeanDefinitionScanner] - JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning
How do I stop the duplicate calls? Thanks.
EDIT
I'm using Log4j. Here's my configuration:
log4j.rootLogger=info, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%c] %x - %m%n
log4j.logger.org.hibernate=info, A1
log4j.logger.com.telus=info, A1
log4j.logger.org.springframework=info, A1
Using Spring 3.1.4.RELEASE. PrimeFaces 4.0. JSF 2.1.7. Deployed on Glassfish 3. Java 1.6.32.

Try adding the following to your log4j.properties
log4j.additivity.org.hibernate=false
log4j.additivity.com.telus=false
log4j.additivity.org.springframework=false
That should ensure that log messages aren't duplicated by the parent root logger.

Related

Migrate Spring Web Application (web.xml) to Spring Boot Executable Jar

Okay I've done a lot of googling and I can't seem to find a clear answer. Let's keep it as simple as possible. I have a web.xml file
<listener>
<listener-class>A</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:springcontexts/*.xml</param-value>
</context-param>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<servlet>
<servlet-name>spring-ws</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:wsspringcontexts/*.xml</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring_mvc_contexts/*.xml</param-value>
</init-param>
</servlet>
I think I know how to migrate this to Spring Boot ...
#SpringBootApplication(exclude = DispatcherServletAutoConfiguration.class)
#ImportResource("classpath*:springcontexts/*.xml")
public class Application
{
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
}
Somewhere in a sub-package...
#Configuration
#EnableWebMvc
public class SpringMVCConfiguration
{
#Bean
public ServletRegistrationBean mvc()
{
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.setConfigLocation("classpath*:spring_mvc_contexts/*.xml");
// the dispatcher servlet should automatically add the root context
// as a parent to the dispatcher servlet's applicationContext
DispatcherServlet dispatcherServlet = new DispatcherServlet(applicationContext);
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/spring/*");
servletRegistrationBean.setName("DispatcherServlet");
return servletRegistrationBean;
}
}
...and we do the above again for the other Servlet
My first problem is how to add the listener "A" to Spring Boot and ensure it runs before the root application is refreshed? Some beans that get configured require some static fields to be setup (legacy code), and this setup is done in listener "A". This works fine when deployed as a standard war using the above web.xml
In addition does the above Spring Boot setup look correct?
Why not put your legacy initialisation in a postConstruct method on a bean ?
Failing that you can add a listener that implements
ApplicationListener<ContextRefreshedEvent>
and overrides
public void onApplicationEvent(final ContextRefreshedEvent event)
Does your Spring Boot setup look OK ? Difficult to tell, though I'd let Spring Boot autoconfigure things like the dispatcher servlet for you and get rid of any XML config if at all possible.

sockjs info 404 error

i use tomcat 7.0.77, spring, now sockjs can not open info.
web.xml
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/cmd/*</url-pattern>
<url-pattern>/webSocketServer</url-pattern>
<url-pattern>/sockjs/webSocketServer/*</url-pattern>
<url-pattern>/sockjs/webSocketServer/info</url-pattern>
<url-pattern>/webSocketServerLogout</url-pattern>
<url-pattern>/webSocketServerSpAlarm</url-pattern>
java
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor());
registry.addHandler(systemWebSocketHandler(), "/sockjsWebSocketServer").addInterceptors(new WebSocketHandshakeInterceptor())
.withSockJS();
catalina.out
INFO: Mapped URL path [/sockjs/webSocketServer/**] onto handler of type [class org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler]
Jul 17, 2017 1:01:46 PM org.springframework.web.servlet.handler.SimpleUrlHandlerMapping registerHandler
html
websocket = new SockJS("http://"+local+"/sockjs/webSocketServer");
firstly can not open /sockjs/webSocketServer/info when i add /sockjs/webSocketServer/info into web.xml like above, report
http://172.24.170.178/sockjs/webSocketServer/093/vl3vnd0p/websocket 404 error
thanks
add servlet-mapping /sockjs/* to web.xml
and change html to
websocket = new SockJS("http://"+local+"/sockjs/sockjsWebSocketServer");
ok now.
because for sockjs, in webConfig java map url can not directly put it to web.xml.
need add a prefix sockjs(example).

Spring 3, AbstractAnnotationConfigDispatcherServletInitializer, multiple servlets

With Servlet 2.5 it was possible to use multiple servlets configured in the web.xml file by simple duplicating and editing the following xml tags.
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Is it somehow possible to create multiple servlets using Spring's AbstractAnnotationConfigDispatcherServletInitializer with Servlet 3?
I thought that returning 2 classes in getServletConfigClasses() method and 2 paths in getServletMappings() method would be enough, but that doesn't work as I expected it to.
So, is there a (simple) way to configure multiple servlets using Spring 3 and Servlet 3?
Thank you for your answers!
You can do something like:
public class MyWebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher", new DispatcherServlet(appContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
ServletRegistration.Dynamic anotherServlet =
container.addServlet("anotherServlet", "com.xxx.AnotherServlet");
anotherServlet.setLoadOnStartup(2);
anotherServlet.addMapping("/another/*");
ServletRegistration.Dynamic yetAnotherServlet =
container.addServlet("yetAnotherServlet", "com.xxx.YetAnotherServlet");
yetAnotherServlet.setLoadOnStartup(3);
yetAnotherServlet.addMapping("/yetanother/*");
}
}
Ofcourse, You could use any of the addServlet() methods as per your convenience.

Request not addressed by spring controller

I have configured in following way that spring MVC app using Spring 3.1.1.RELEASE
web.xml
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/context/*-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/cgi/*</url-pattern>
</servlet-mapping>
springmvc-servlet.xml
<context:component-scan base-package="com.pokuri.mvc.controllers"/>
UserController.java
package com.pokuri.mvc.controllers;
#Controller
#RequestMapping("/user")
public class UserController {
#RequestMapping(method=RequestMethod.GET)
#ResponseBody
public String defaultRequest(){
return "It's a default handler method";
}
}
index.jsp
<a class="action" href="cgi/user">Default Action</a>
Sever log on initializing springmvc app:
23:53:04,406 INFO [DispatcherServlet] FrameworkServlet 'springmvc': initialization started
23:53:04,468 INFO [XmlWebApplicationContext] Refreshing WebApplicationContext for namespace 'springmvc-servlet': startup date [Thu Jun 28 23:53:04 IST 2012]; root of context hierarchy
23:53:04,609 INFO [XmlBeanDefinitionReader] Loading XML bean definitions from ServletContext resource [/WEB-INF/context/services-context.xml]
23:53:04,890 INFO [DefaultListableBeanFactory] Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#6c4fe: defining beans [dummyService]; root of factory hierarchy
23:53:05,156 INFO [DispatcherServlet] FrameworkServlet 'springmvc': initialization completed in 750 ms
.....
.....
23:56:17,875 WARN [PageNotFound] No mapping found for HTTP request with URI [/springmvc/cgi/user] in DispatcherServlet with name 'springmvc'
When I click on that link in index.jsp, I am getting 404 error. I thing I might have done a silly mistake. But, not able to track it. Can someone help me in this?
It looks like your DispatcherServlet is looking for config files ending in -context.xml. But your Spring config file is called springmvc-servlet.xml.

Servlet Mapping Help - Possible to Avoid Referencing Context Name?

I am working on a Spring application using Tomcat 6 and Spring 2.5. I'm trying to get my URL mapping correct. What I would like to have work is the following:
http://localhost:8080/idptest -> doesn't work
But instead, I have to reference the context name in my URL in order to resolve the mapping:
http://localhost:8080/<context_name>/idptest -> works
How can I avoid the requirement of referencing the context name in my URL without using a rewrite/proxy engine e.g. Apache?
Here is the servlet definition and mapping from my web.xml:
<servlet>
<servlet-name>idptest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/conf/idptest.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>idptest</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Here's the outline of my controller (showing annotations for request mappings):
#Controller
#RequestMapping("/idptest")
public class MyController {
#RequestMapping(method=RequestMethod.GET)
public String setupForm(Model model){
MyObject someObject = new MyObject();
model.addAttribute("someObject", someObject);
return "myform";
}
#RequestMapping(method = RequestMethod.POST)
public String processSubmit(#ModelAttribute("someObject") MyObject someObject) throws Exception {
// POST logic...
}
}
Thanks!
That's going to depend on your servlet container, for Tomcat - you pretty much have to deploy your webapp as the ROOT webapp, that is, under $CATALINA_HOME/webapps/ROOT/
More info here
Just rename your war file to ROOT.war, then the application runs in root context (i.e. with empty context name)

Resources