Ok, I had a bounty about this same subject with only a partial answer so I'm going to open this one and simplify the subject since I guess the original one was way too bloated.
I'm facing a situation where I basically have a filter that gets a Spring service factory object from the servlet context, This factory allocates an instance of a bean when the filter calls it's getService method, but I need access the session or the actual httpServletRequest object of the request since I need the userID from the request. I think, from what I have read, that I shouldn't pass it down to the bean not just because it is not thread safe but because it will break the abstraction of the remote services bridge (CP2JavaWS) that owns the filter.
How can I get this bean to access the session or the httpServletRequest??
I try to use FacesContext but it didn't worked since I think the bean wasn't instantiated by a jsp call but from a filter.
Now Some code.
this is my web.xml
<display-name>CP2JavaWSTest</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/err.jsp</location>
</error-page>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.cp2javaws.listeners.SpringContextWrapperListener</listener-class>
</listener>
<listener>
<listener-class>com.bucle.listeners.BCLUserDatabaseContextListener</listener-class>
</listener>
<filter>
<filter-name>BCLAuthenticationFilter</filter-name>
<filter-class>com.bucle.filters.BCLAuthenticationFilter</filter-class>
</filter>
<filter>
<filter-name>BCLAuthorizationFilter</filter-name>
<filter-class>com.bucle.filters.BCLAuthorizationFilter</filter-class>
</filter>
<filter>
<filter-name>CPJSonFilter</filter-name>
<filter-class>com.cp2javaws.filters.CPJSonFilter</filter-class>
</filter>
the application context:
<bean id="service1" class="com.bucle.database.BCLDb4oManager" scope="request"/>
<bean id="service2" class="com.bucle.services.appe.BCLUserCFVC"/>
<bean id="service3" class="com.bucle.services.appe.BCLUserCustomizedFutureValueCalculator"/>
the CPWJavaWS filter
public class CPJSonFilter implements Filter {
//.. properties
public void init(FilterConfig filterConfig)
throws ServletException {
//.. init code
}
public void destroy() {
//..
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpSession session = ((HttpServletRequest)request).getSession(true);
//..Class and method decoding and mapping from JSON
Class type = null;
String value = request.getParameter(CP2JavaWSRequestParameterType+paramOrderString);
if(paramName.indexOf(CP2JavaWSRequestGenericParamSuffix)>0 || request.getParameter(CP2JavaWSRequestParameterType+paramOrderString).equals("id")) {//SAMIR
type = Object.class;
} else {
if(paramName.indexOf(CP2JavaWSRequestNullParamSuffix)>0) {
String CPClassName = paramName.substring(paramName.indexOf(CP2JavaWSRequestNullParamSuffix)+CP2JavaWSRequestNullParamSuffix.length());
try {
type = getJavaClassForCPClass(CPClassName);
} catch (CP2JavaWSException e) {
throw new ServletException("Cannot find corresponding Java class for null argument at index "+paramOrderString+" (passed CP class name is"+CPClassName+")");
}
} else if(List.class.isAssignableFrom(convertedObject.getClass())) {
type = List.class;
} else if(Map.class.isAssignableFrom(convertedObject.getClass())) {
type = Map.class;
} else {
type = convertedObject.getClass();
}
}
typesOrderedMap.put(new Integer(paramOrderString), type);
}
}
// invoke the service method using the provided service factory class
Object result = null;
try {
Class serviceInterfaceClass = Class.forName(serviceInterfaceName);
ServiceFactory serviceFactory = (ServiceFactory) filterConfig.getServletContext().getAttribute(ServiceFactory.CP2JAVAWS_SERVICES_FACTORY);
Object service = serviceFactory.getService(serviceInterfaceClass);
Method method = service.getClass().getDeclaredMethod(serviceMethodName, (Class[]) typesOrderedMap.values().toArray(new Class[typesOrderedMap.size()]));
result = method.invoke(service, argumentsOrderedMap.values().toArray());
} catch(Exception e) {
throw new ServletException("Error invoking the service method :"+serviceMethodName+" on service "+serviceInterfaceName,e);
}
//...Convert result to JSON
response.setContentType("application/json");
PrintWriter writer = response.getWriter();
StringBuffer stb = new StringBuffer();
//... append result and some other stuff to the string buffer stb
response.setContentLength(stb.length());
((HttpServletResponse)response).setStatus(HttpServletResponse.SC_OK);
writer.write(stb.toString());
writer.flush();
}
public static Class getJavaClassForCPClass(String CPClassName) throws CP2JavaWSException {
//... returns the matching Class.class according to a default map like: CPArray -> List.class
}
}
this is the Spring context listener:
public class SpringContextWrapperListener implements ServletContextListener {
private ServletContext context = null;
public void contextDestroyed(ServletContextEvent event) {
this.context = null;
//log.info("Spring Context Destruido");
}
public void contextInitialized(ServletContextEvent event) {
this.context = event.getServletContext();
ApplicationContext springContext = (ApplicationContext) WebApplicationContextUtils.getRequiredWebApplicationContext(this.context);
SpringContextWrapper aSpringContextWrapper = new SpringContextWrapper(springContext);
this.context.setAttribute(ServiceFactory.CP2JAVAWS_SERVICES_FACTORY, aSpringContextWrapper);
}
}
and the factory:
public class SpringContextWrapper implements ServiceFactory {
private ApplicationContext springContext;
public SpringContextWrapper(ApplicationContext springContext) {
this.springContext = springContext;
}
public Object getService(Class serviceInterfaceClass) throws CP2JavaWSException {
Map services = this.springContext.getBeansOfType(serviceInterfaceClass);
Iterator it = services.values().iterator();
if(it.hasNext()) {
return it.next();
}
throw new CP2JavaWSException("can't find service for interface "+serviceInterfaceClass.getName());
}
public Object getService(String serviceName) throws CP2JavaWSException {
Object service = this.springContext.getBean(serviceName);
if(service==null) {
throw new CP2JavaWSException("can't find service for name "+serviceName);
}
return service;
}}
I'm not 100% sure I understand the question, but I think you can use the
RequestContextHolder
for what you're trying to do.However, seeing some code would help. I suspect that you might achieve what you want with the correct
scope
of your bean.