Access Servlet Context Parameters with CDI Extension

I am trying to write a CDI extension that needs to access the context parameters defined in web.xml via <context-param> . I think there are two ways to do this:

  • Somehow get a ServletContext and call getInitParameter()
  • Manually disassemble web.xml

Unfortunately, I need a ServletContext for both solutions, and getting it seems impossible. The problem here is that some CDI launch containers before creating the ServletContext . And even if ServletContext will be available before starting CDI, it seems that there is no access to it from the CDI extension. I experimented with a ServletContextListener that stores a ServletContext in a static ThreadLocal . This seems to work fine, but it will create a memory leak as I cannot reliably clear ThreadLocal .

Two more comments before you answer:

  • Using any other approach to reading configuration parameters (for example, using JNDI) is not an option for me, as I am trying to write a CDI extension for integration with a third-party structure.
  • I am aware that there will probably be no help for this problem, which is 100% transferred between environments / containers. But I would be glad if I found a solution that works in most cases.

Thanks!:)

+4
source share
3 answers

I tried to do something similar by sharing the context with CDI beans in general on JBoss 7.1. Although this did not work for me, I'm not sure if it caused problems with the current state of JBoss7.1, maybe this will work for you?

What I did was something at startup that has access to the ServletContext (in my case, the JAX-RS Application , but probably a listener or servlet for you) access the bean area with the applications and set the ServletContext in it.

To connect to the CDI world, I used the recipe from the following URI to instantiate the bean: http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html/extend.html#d0e4978

The corresponding code looks something like this:

 @SuppressWarnings("unchecked") public <T> T getBean(Class<T> instanceClass) throws NamingException { BeanManager beanManager = (BeanManager) InitialContext.doLookup("java:comp/BeanManager"); AnnotatedType<Object> annotatedType = (AnnotatedType<Object>) beanManager.createAnnotatedType(instanceClass); InjectionTarget<Object> injectionTarget = beanManager.createInjectionTarget(annotatedType); CreationalContext<Object> context = beanManager.createCreationalContext(null); Object instance = injectionTarget.produce(context); injectionTarget.inject(instance, context); injectionTarget.postConstruct(instance); return (T) instance; } 

which can then be set to a bean, which looks like this:

 package some.package; import javax.enterprise.context.ApplicationScoped; import javax.servlet.ServletContext; /** An application context, initialised on application startup. */ @ApplicationScoped public class AppContext { private ServletContext servletContext; /** Return the servlet context for the current application. */ public ServletContext getServletContext() { return servletContext; } public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; } } 

using a fragment like:

 getBean(AppContext.class).setServletContext(servletContext); 

in your starter code. Then you can simply @Inject use the context in any CDI construct in which you want to use it ... provided that it starts after your init servlet or something else.

For instance:

 @Inject private AppContext appContext; 

I will be wondering if this works in other situations ...

+4
source

Not sure which container you are using, but it seems like in JBoss you can just insert ServletContext using annotation. Doesn't this work for you, or am I misunderstanding the nature of your CDI extension?

EDIT: ah. I never used a CDI implementation, but it would be possible to create a ServletContextListener that generated a CDI event with ServletContext as one of the properties of the event. Then you can just listen to the event in your extension and retrieve the ServletContext .

0
source

As you noticed yourself, and Femi commented on whether ServletContext is unavailable, you can not get anything from it (for example, init parameters). Reading the web.xml file is possible, but of course it is crazy and will not be portable, but you can always try to do this in your specific deployment, you can get an example of reading smth from WEB-INF here

0
source

Source: https://habr.com/ru/post/1369107/


All Articles