-
1. Re: Weld\CDI, JSF 2, Liferay 6 portlet using portletfaces bridge
mstruk Apr 2, 2012 3:13 PM (in response to turner2448)"Not in a Servlet environment" sounds like an old - pre-JBoss-AS7 version of Weld (1.1.2.AS7).
The problem with that one was that it presupposed that facesContext.getExternalContext().getContext() would always return an instance of ServletContext which may not be the case when you use a portlet bridge (see WELD-150).
The above patch doesn't work with WELD-1.0.1.SP3 for example.
-
2. Re: Weld\CDI, JSF 2, Liferay 6 portlet using portletfaces bridge
turner2448 Apr 2, 2012 3:34 PM (in response to mstruk)Hi Marko
This is using the latest Weld build, 1.1.6 final which has the cross context filter in the weld-servlet jar.
It seems like you're saying that it should work in a portlet environment with the cross context filter included. Do you know if people are using it successfully?
Cheers
Tony
-
3. Re: Weld\CDI, JSF 2, Liferay 6 portlet using portletfaces bridge
mstruk Apr 3, 2012 7:14 AM (in response to turner2448)Can you post a full stacktrace, so we can see where the "Not in a Servlet environment" message originates?
The patch only works as long as there are not some other issues present - like in your case - expectations about environment.
Stack trace will make it clear where the issue originates, and if it's Weld issue or something else.
-
4. Re: Weld\CDI, JSF 2, Liferay 6 portlet using portletfaces bridge
turner2448 Apr 3, 2012 8:49 AM (in response to mstruk)Hi Marko
Here's the exception thrown by Tomcat 7.
12:45:51,144 ERROR [render_portlet_jsp:154] java.lang.IllegalStateException: Not in a servlet environment!
at org.jboss.weld.environment.servlet.jsf.WeldApplication.beanManager(WeldApplication.java:103)
at org.jboss.weld.environment.servlet.jsf.WeldApplication.init(WeldApplication.java:77)
at org.jboss.weld.environment.servlet.jsf.WeldApplication.delegate(WeldApplication.java:85)
at org.jboss.weld.environment.servlet.jsf.ForwardingApplication.getViewHandler(ForwardingApplication.java:277)
at com.sun.faces.context.FacesContextImpl.isPostback(FacesContextImpl.java:210)
at org.portletfaces.bridge.BridgeImpl.doFacesRequest(BridgeImpl.java:360)
at org.portletfaces.bridge.GenericFacesPortlet.doView(GenericFacesPortlet.java:181)
at javax.portlet.GenericPortlet.doDispatch(GenericPortlet.java:328)
at javax.portlet.GenericPortlet.render(GenericPortlet.java:233)
at com.liferay.portlet.FilterChainImpl.doFilter(FilterChainImpl.java:100)
at com.liferay.portal.kernel.portlet.PortletFilterUtil.doFilter(PortletFilterUtil.java:64)
at com.liferay.portal.kernel.servlet.PortletServlet.service(PortletServlet.java:93)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:72)
at org.jboss.weld.servlet.WeldCrossContextFilter.doFilter(WeldCrossContextFilter.java:62)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:203)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:105)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilter.doFilter(InvokerFilter.java:70)web.xml is here (I've tried changing the servlet container from version 2.5 to version 3.0 but to no affect):
<?
?>
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
</
</
>
Cheers
Tony
-
5. Re: Weld\CDI, JSF 2, Liferay 6 portlet using portletfaces bridge
mstruk Apr 3, 2012 8:46 PM (in response to turner2448)This looks like a Weld issue indeed.
Can you try build Weld from sources:
git clone https://github.com/weld/core.git weld-core
cd weld-core
(you can use master or checkout tag 1.1.6.Final if you want)
Edit the following file: environments/servlet/core/src/main/java/org/jboss/weld/environment/servlet/jsf/WeldApplication.java
Overwrite beanManager() method with the following implementation:
private BeanManager beanManager() {
FacesContext facesContext;
if (beanManager == null && (facesContext = FacesContext.getCurrentInstance()) != null) {
ServletContext ctx = null;
Object obj = facesContext.getExternalContext().getContext();
if (!(obj instanceof ServletContext)) {
Class clazz = obj.getClass();
try {
Method m = clazz.getMethod("getServletContext");
ctx = (ServletContext) m.invoke(obj);
} catch (Exception e) {
throw new IllegalStateException("Not in a servlet environment!");
}
}
ctx = (ServletContext) obj;
if (ctx.getAttribute(BEAN_MANAGER_ATTRIBUTE_NAME) == null) {
return null;
}
this.beanManager = (BeanManager) ctx.getAttribute(BEAN_MANAGER_ATTRIBUTE_NAME);
}
return beanManager;
}
Build Weld:
mvn clean install -DskipTests
And try with this version (you should use environments/servlet/core/target/weld-servlet-core-*.jar).
-
6. Re: Weld\CDI, JSF 2, Liferay 6 portlet using portletfaces bridge
turner2448 Apr 4, 2012 11:35 AM (in response to mstruk)Hi Marko
I've built the jar file (weld-servlet-core-1.2.0-SNAPSHOT) as per your instructions and have deployed this to the lib directory of the portlet.
The portlet doesn't deploy to the portal because it is mssing org.jboss.weld.servlet.api.helpers.ForwardingServletListener. This class is in the original weld-servlet.jar that I have now replaced with the rebuilt JAR.
I'm assuming that you meant to replace one for the other (otherwise we would get classloading problems when loading the modified WeldApplication class).
It just seems that the original jar file contains many more classes than the new jar, i.e. the new jar is a subset of the old one.
Cheers
Tony
-
7. Re: Weld\CDI, JSF 2, Liferay 6 portlet using portletfaces bridge
mstruk Apr 4, 2012 4:33 PM (in response to turner2448)Then try to patch 1.1.6.Final version since this is the one you use, so you won't have jar content mismatches.
-
8. Re: Weld\CDI, JSF 2, Liferay 6 portlet using portletfaces bridge
turner2448 Apr 5, 2012 5:07 AM (in response to mstruk)Hi Marko
Thanks for your help with this.
I've patched the jar and deployed as suggested. Looking at the code I don't think that casting a portletcontext to a servletcontext will work within a portlet environment. Aside from the fact that you get a class cast exception, even if it were successful you would likely run into all sorts of problems later on.
The Weld package would need to be portlet aware throughout in order for this to be a viable solution I guess.
I'll post back if anything comes up.
Cheers
Tony
-
9. Re: Weld\CDI, JSF 2, Liferay 6 portlet using portletfaces bridge
mstruk Apr 5, 2012 8:24 AM (in response to turner2448)JSF API is loose at the point of external contexts precisely in order to allow different environments.
Method facesContext.getExternalContext().getContext() really returns a java.lang.Object type. And it can be anything.
I guess that for all the different portlet bridges this should return a javax.portlet.PortletContext on which Weld can then call getAttribute() which should be delegated to the underlying ServletContext.
The way it's written did work for me a while back with portletfaces bridge and Liferay 6, so I suppose it would work for you as well. I'm primarily interested if this is the only issue with Weld or is there more once you get beyond this one.
A more proper way would then be something like:
private BeanManager beanManager() {
FacesContext facesContext;
if (beanManager == null && (facesContext = FacesContext.getCurrentInstance()) != null) {
Object obj = facesContext.getExternalContext().getContext();
if (obj instanceof ServletContext) {
ServletContext ctx = (ServletContext) obj;
if (ctx.getAttribute(BEAN_MANAGER_ATTRIBUTE_NAME) == null) {
return null;
}
this.beanManager = (BeanManager) ctx.getAttribute(BEAN_MANAGER_ATTRIBUTE_NAME);
} else if (obj instanceof javax.portlet.PortletContext) {
javax.portlet.PortletContext ctx = (javax.portlet.PortletContext) obj;
if (ctx.getAttribute(BEAN_MANAGER_ATTRIBUTE_NAME) == null) {
return null;
}
this.beanManager = (BeanManager) ctx.getAttribute(BEAN_MANAGER_ATTRIBUTE_NAME);
} else {
throw new IllegalStateException("Not in a servlet or portlet environment!");
}
}
return beanManager;
}
I didn't test this, but it might work.
Please, give it a try and report back the outcome.
-
10. Re: Weld\CDI, JSF 2, Liferay 6 portlet using portletfaces bridge
ngriffin7a May 9, 2012 4:09 PM (in response to mstruk)Latest results of my testing of Weld 1.1.7 with Liferay Portal can be found here: