Posted by: Joshua on: November 14, 2007
Generally you won’t find any problem setting up Wicket on Websphere 5 using WicketFilter. But there are some situation where you just can’t use WicketFilter. One case of that is if you integrate Wicket with Spring, then you’re in trouble. Why?
Is that it?
No. You’re still on another problem.Filter is loaded first before servlet. So you would end up in an exception saying that Wicket can not find your spring context. Thank’s God Wicket also provides a WicketServlet (though this has been deprecated and not recommended to use anymore) for situation like this. And you would not lose all the functionality in WicketFilter because basically WicketServlet will instantiate WicketFilter and call it once it is loaded.
To wrap it up, this is the web.xml configuration you would likely use for such situation:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <display-name>wicket</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext*.xml</param-value> </context-param> <servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet> <servlet-name>wicket.wicket</servlet-name> <servlet-class>org.apache.wicket.protocol.http.WicketServlet</servlet-class> <init-param> <param-name>configuration</param-name> <param-value>development</param-value> </init-param> <init-param> <param-name>applicationClassName</param-name> <param-value>com.taxandtech.lab.wicket.web.WicketApplication</param-value> </init-param> <init-param> <param-name>applicationFactoryClassName</param-name> <param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>wicket.wicket</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping> </web-app>
Then you call your Spring beans from WicketApplication class as such:
public class WicketApplication extends WebApplication
{
private DepartmentService departmentService;
public DepartmentService getDepartmentService() {
return departmentService;
}
public void setDepartmentService(DepartmentService departmentService) {
this.departmentService = departmentService;
}
}
And this is an example how your applicationContext configuration would look like:
<beans>
<bean id="departmentDao" class="com.taxandtech.lab.wicket.dao.DepartmentDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="departmentService" class="com.taxandtech.lab.wicket.service.DepartmentServiceImpl">
<property name="departmentDao" ref="departmentDao" />
</bean>
<bean id="wicketApplication" class="com.taxandtech.lab.wicket.web.WicketApplication">
<property name="departmentService" ref="departmentService"/>
</bean>
</beans>
And that’s about it.You would normally can your spring bean from your wicket page as such:
public class DepartmentInput extends WebPage{
private Department department;
public DepartmentInput() {
add(feedback);
add( new DepartmentInputForm("departmentInputForm", new CompoundPropertyModel( new Department() )));
add( new Label("departmentName", new PropertyModel(department, "name" ) ));
}
public class DepartmentInputForm extends Form{
public DepartmentInputForm(String id, final CompoundPropertyModel model) {
super(id, model);
department = (Department)model.getObject();
add(new TextField( "name" ) );
add(new Button("save"){
public void onSubmit(){
getDepartmentService().save(department);
}
});
}
}
protected DepartmentService getDepartmentService(){
return ((WicketApplication)getApplication()).getDepartmentService();
}
}
Watch closely on line 19-23 on how the button calls the service and on line 27-29 how the service is called from WicketApplication that we have set up before.
Hi Joshua,
You saved my bacon! We are going to use Wicket 1.3 for our next big WAS 6.1 project based on my recommendation. However, my proof of concept suddenly stopped working after I integrated Spring/Hibernate following the Wicket in Action book. So I went back to WicketServlet based on your advice, and it works! I have a question for you: I am creating a Hibernate session per each request using the Spring OpenSessionInViewFilter filter — will this filter still work properly with Websphere?
Thanks,
Steve
I have a wicket/spring application that works on Tomcat. I am trying to port it to WebSphere 5.1. After seeing this post, I replaced the listener with the ContextLoaderServlet. That allowed me to get a little further. However, now I am getting the following error when the WAS server starts:
[10/21/08 10:57:32:656 CDT] 35e7f85e WebGroup E SRVE0020E: [Servlet Error]-[ContextLoaderServlet]: Failed to load servlet: java.lang.ClassCastException: org.springframework.web.context.ContextLoaderServlet
at com.ibm.ws.webcontainer.webapp.WebAppServletManager.loadServlet(WebAppServletManager.java:188)
at com.ibm.ws.webcontainer.webapp.WebAppServletManager.loadAutoLoadServlets(WebAppServletManager.java:542)
at com.ibm.ws.webcontainer.webapp.WebApp.loadServletManager(WebApp.java:1279)
at com.ibm.ws.webcontainer.webapp.WebApp.init(WebApp.java:283)
at com.ibm.ws.webcontainer.srt.WebGroup.loadWebApp(WebGroup.java:392)
at com.ibm.ws.webcontainer.srt.WebGroup.init(WebGroup.java:211)
at com.ibm.ws.webcontainer.WebContainer.addWebApplication(WebContainer.java:1005)
at com.ibm.ws.runtime.component.WebContainerImpl.install(WebContainerImpl.java:136)
at com.ibm.ws.runtime.component.WebContainerImpl.start(WebContainerImpl.java:356)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:505)
at com.ibm.ws.runtime.component.DeployedApplicationImpl.fireDeployedObjectStart(DeployedApplicationImpl.java:808)
at com.ibm.ws.runtime.component.DeployedModuleImpl.start(DeployedModuleImpl.java:354)
at com.ibm.ws.runtime.component.DeployedApplicationImpl.start(DeployedApplicationImpl.java:578)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.startApplication(ApplicationMgrImpl.java:299)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:256)
at com.ibm.ws.runtime.component.ContainerImpl.startComponents(ContainerImpl.java:536)
at com.ibm.ws.runtime.component.ContainerImpl.start(ContainerImpl.java:413)
at com.ibm.ws.runtime.component.ApplicationServerImpl.start(ApplicationServerImpl.java:152)
at com.ibm.ws.runtime.component.ContainerImpl.startComponents(ContainerImpl.java:536)
at com.ibm.ws.runtime.component.ContainerImpl.start(ContainerImpl.java:413)
at com.ibm.ws.runtime.component.ServerImpl.start(ServerImpl.java:243)
at com.ibm.ws.runtime.WsServer.start(WsServer.java:128)
at com.ibm.ws.runtime.WsServer.main(WsServer.java:225)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:85)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:58)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:60)
at java.lang.reflect.Method.invoke(Method.java:391)
at com.ibm.ws.bootstrap.WSLauncher.main(WSLauncher.java:189)
at com.ibm.etools.websphere.tools.runner.api.ServerRunnerV5$1.run(ServerRunnerV5.java:97)
[10/21/08 10:57:32:656 CDT] 35e7f85e TraceNLS u No message text associated with key Servlet.[ContextLoaderServlet]:.not.a.servlet.class in bundle com.ibm.ejs.resources.seriousMessages
[10/21/08 10:57:32:656 CDT] 35e7f85e WebAppServlet E Servlet [ContextLoaderServlet]: not a servlet class
Any thoughts on what could be causing this error … Thanks!
The spring.jar file is in the installedApps application directory under …/WEB-INF/lib. I was able to get around the problem I posted above. The problem was that javax.servlet.Servlet was found in another jar file that was deployed with the application. This didn’t cause a problem for Tomcat but WebSphere didn’t like it.
I have worked through a number of other problems but it’s still not working yet. One problem I had is that we are using version 1.3.4 of wicket which was compiled with JDK 5. I had to use a tool called retroweaver to make it byte-code compatible with JDK 1.4 on WAS.
At this point, I have been able to get the application installed and started on the WebSphere console. When I enter the URL on a browser to start the wicket application I get the error:
“org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘viewController’: Scope ’session’ is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request? If you are actually operating within a web request and still receive this message,your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.”
This is the web.xml I am using:
PepBoys Mobile Application
contextConfigLocation
/WEB-INF/endpointAppContext.xml
org.springframework.web.context.request.RequestContextListener
context
org.springframework.web.context.ContextLoaderServlet
0
wicket.wicket
org.apache.wicket.protocol.http.WicketServlet
configuration
development
applicationClassName
com.starmountsystems.wicket.app.WicketApplication
applicationFactoryClassName
org.apache.wicket.spring.SpringWebApplicationFactory
1
wicket.wicket
/app/*
This same web.xml works fine on Tomcat.
Thanks for your help.
I got past the last hurdle only to hit another. This is what I discovered. The error above resulted from a setting in our Spring applicationContext.xml. We were setting the scope to “session”, overriding the default of “singleton”. This is what the applicationContext.xml looked like:
After changing the scope to “singleton” the problem was resolved. However, we really need that bean to be associated with the session so we are stuck again.
Looks like, the filter issue with websphere can be fixed with this property
com.ibm.ws.webcontainer.invokefilterscompatibility=true
http://www-01.ibm.com/support/docview.wss?uid=swg24014758
http://www.nabble.com/URL-mounting-on-Websphere-causes-Error-404-td22455795.html
November 14, 2007 at 8:25 am
The wicket servlet is only deprecated for the way most people used it: configuring it on the context root with the /* catch all. If you map it to /app/* you won’t have any problems.
Because of the problems with WebSphere and other servers, the servlet is still a viable alternative and won’t be going away anytime soon.