Forums de discussion

Using CDI and IPC results in ClassCastException of class EventRequestImpl

thumbnail
Bernd Ruecker, modifié il y a 10 années.

Using CDI and IPC results in ClassCastException of class EventRequestImpl

New Member Publications: 22 Date d'inscription: 13/08/13 Publications récentes
Hey guys.

I run Liferay 6.1 on JBoss EAP 6.1 with liferay-faces-bridge 3.1.2-ga3 and it worked fine so far. But now I reached a problem which smells like a bug and I don't know how to proceed best.

I send an event for IPC via this code in one portlet:

@Named("tasklist")
public class TasklistBean {
public void someMethod() {
// ...
QName qName = new QName("http://camunda.org/events", "ipc.taskSelected");
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
ActionResponse actionResponse = (ActionResponse) externalContext.getResponse();
actionResponse.setEvent(qName, task.getId());


This is now sent to a portlet in a different war where it should get picked up by a BridgeEventHandler. But it cannot be sent since in the meanwhile WELD does a

HttpServletRequest request = (HttpServletRequest)facesContext.getExternalContext().getRequest();

But the request is a "com.liferay.portlet.EventRequestImpl" which leads to the exception attached (the line above is the root case in weld). Any ideas or thoughts?

Thanks
Bernd

Pièces jointes:

thumbnail
Neil Griffin, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

Liferay Legend Publications: 2655 Date d'inscription: 27/07/05 Publications récentes
Do you have the following in your WEB-INF/portlet.xml descriptor?

<filter>
	<filter-name>CDIPortletFilter</filter-name>
	<filter-class>com.liferay.cdi.portlet.bridge.CDIPortletFilter</filter-class>
	<lifecycle>ACTION_PHASE</lifecycle>
	<lifecycle>EVENT_PHASE</lifecycle>
	<lifecycle>RENDER_PHASE</lifecycle>
	<lifecycle>RESOURCE_PHASE</lifecycle>
</filter>


In particular, did you specify EVENT_PHASE?
thumbnail
Bernd Ruecker, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

New Member Publications: 22 Date d'inscription: 13/08/13 Publications récentes
Wow - you are fast! Thanks!

I indeed did not have the EVENT_PHASE here as I copied the portlet.xml from the cdi example. When I add it the exception changes - now somehow the filter does not work correctly any more I guess. Anything else I have to configure correctly?

TaskFormPortlet Servlet threw exception: java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_21]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_21]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_21]
at java.lang.reflect.Method.invoke(Method.java:601) [rt.jar:1.7.0_21]
at com.liferay.portal.kernel.bean.ClassLoaderBeanHandler.invoke(ClassLoaderBeanHandler.java:67) [portal-service.jar:]
at com.sun.proxy.$Proxy530.doFilter(Unknown Source)
at com.liferay.portlet.FilterChainImpl.doFilter(FilterChainImpl.java:80)
at com.liferay.portal.kernel.portlet.PortletFilterUtil.doFilter(PortletFilterUtil.java:58) [portal-service.jar:]
at com.liferay.portal.kernel.servlet.PortletServlet.service(PortletServlet.java:111) [portal-service.jar:]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.2.Final-redhat-1.jar:1.0.2.Final-redhat-1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:295) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1]
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:72) [portal-service.jar:]
at org.jboss.weld.servlet.WeldCrossContextFilter.doFilter(WeldCrossContextFilter.java:62) [weld-core-1.1.13.Final-redhat-1.jar:1.1.13.Final-redhat-1]
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.processDoFilter(InvokerFilterChain.java:206) [portal-service.jar:]
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:108) [portal-service.jar:]
at com.liferay.cdi.portlet.bridge.CDICrossContextFilter.doFilter(CDICrossContextFilter.java:47) [cdi-portlet-bridge-shared-6.2.0.1.jar:]
...
thumbnail
Bernd Ruecker, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

New Member Publications: 22 Date d'inscription: 13/08/13 Publications récentes
I debugged further into it

and in the FilterChainImpl when calling the ClassLoaderBeanHandler it comes to this method:

return method.invoke(_bean, arguments);

and here indeed the bean is from another classloader than the reflection method.

_bean.getClass().getName()
(java.lang.String) com.liferay.cdi.portlet.bridge.CDIPortletFilter
_bean.getClass().getClassLoader()
(org.jboss.modules.ModuleClassLoader) ModuleClassLoader for Module "deployment.camunda-bpm-liferay-process-application.war:main" from Service Module Loader

method.getDeclaringClass().getName()
(java.lang.String) javax.portlet.filter.EventFilter
method.getDeclaringClass().getClassLoader()
(org.jboss.modules.ModuleClassLoader) ModuleClassLoader for Module "com.liferay.portal:main" from local module loader @96be00 (finder: local module finder @9405ca (roots: D:\camundaBPM\playground\liferay\jboss-eap-6.1-liferay-6.1\modules,D:\camundaBPM\playground\liferay\jboss-eap-6.1-liferay-6.1\modules\system\layers\base))


Any ideas or hints?
thumbnail
Bernd Ruecker, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

New Member Publications: 22 Date d'inscription: 13/08/13 Publications récentes
I think the problem is that:

- portlet-api is deployed as JBoss Module
- cdi-portlet-bridge-shared-6.2.0.1.jar is part of the WAR deployments

So we have two classloaders. But actually it seems hard to re package the stuff easily as it has a lot of intervened dependencies. Or do I miss some easy solution?

Thanks
Bernd
thumbnail
Bernd Ruecker, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

New Member Publications: 22 Date d'inscription: 13/08/13 Publications récentes
Is it maybe possible to break up the cdi-portlet-bridge-shared-6.2.0.1.jar into one JAr in the JBoss modules and one jar necessery within the deployment (e.g. for CDI beans)? Or maybe this is not even the root cause?
thumbnail
Bernd Ruecker, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

New Member Publications: 22 Date d'inscription: 13/08/13 Publications récentes
Any idea to this? It is actually a show stopper for the solution we target in a POC with camunda BPM and Lifreay Enterprise Edition. Maybe there is a possibility to get some help in terms of pre-sales? Let me know if this is the case (bernd.ruecker@camunda.com).

For the moment I think I will replace IPC with some dirty hacked own mechanism - but that's really ugly. I would need some answer for the customer next week - so to get some quick feedback would be wonderful! Then I can at least tell them "does not work YET, but ..."

Thanks a lot
Cheers
Bernd
thumbnail
Neil Griffin, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

Liferay Legend Publications: 2655 Date d'inscription: 27/07/05 Publications récentes
Hi Bernd,

Thanks so much for diving into the debugger and reporting back about the classloader problem.

I would recommend that you try these steps:

1. MOVE the cdi-portlet-bridge-shared-6.2.0.1.jar dependency from your portlet WEB-INF/lib folder to $LIFERAY_HOME/jboss-7.1.1/modules/com/liferay/portal/main

2. EDIT the $LIFERAY_HOME/jboss-7.1.1/modules/com/liferay/portal/main/module.xml descriptor, and ADD the following line to the <resources>...</resources> section:

<resource-root path="cdi-portlet-bridge-shared-6.2.0.1.jar" />


3. Restart Liferay+JBoss

Kind Regards,

Neil
thumbnail
Bernd Ruecker, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

New Member Publications: 22 Date d'inscription: 13/08/13 Publications récentes
Hi Neil.

That was the first thing I tried yesterday :-) But the problem is that then you need CDI on the dependencies as well. So I added this - but then it wants to startup some listener when booting JBoss which does not work (as some classes has to be in the classpath of the WAR for WELD I guess). So I think that we somehow have to divide the cdi-portlet-bridge-shared-6.2.0.1.jar somehow into two jars (for modules / WAR). WDYT?

Any way to make sure that this is really the problem? Actually I never had the "java.lang.IllegalArgumentException: object is not an instance of declaring class" before - so I have no experience with that one (I am more "used to" ClassCast X to X ;-)).

Cheers
Bernd
thumbnail
Bernd Ruecker, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

New Member Publications: 22 Date d'inscription: 13/08/13 Publications récentes
Hi Neil.

We today double checked and we get the "java.lang.IllegalArgumentException: object is not an instance of declaring class" even if we send IPC events between portlets within the same WAR. So there seems to be something really wrong with IPC and CDI. I think it should be easy to build an isoltaed test case based on the cdi example showing this. Not sure if I will have time this week to do this.

Thanks & Cheers
Bernd
thumbnail
Bernd Ruecker, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

New Member Publications: 22 Date d'inscription: 13/08/13 Publications récentes
OK - another idea - as we had a similiar issue on the camunda BPM platform itself. We got the same exception ("java.lang.IllegalArgumentException: object is not an instance of declaring class") when using reflection on a proxy instead of the "real" object (which can happen quickly in the CDI context). So I wonder if this is maybe an idea?
thumbnail
Ahmed Hasan, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

Expert Publications: 306 Date d'inscription: 13/04/07 Publications récentes
Hi Bernd,

I have covered IPC in great length in my free eBook on Liferay. You can refer to that and see if that is going to be of some use to you.

Yours truly,
Ahamed Hasan
Author of the most comprehensive guide, Liferay Portlet Cookbook.
thumbnail
Bernd Ruecker, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

New Member Publications: 22 Date d'inscription: 13/08/13 Publications récentes
Hi Ahamed.

If you have an idea to the above issue I would be happy! I think it is defintely a bug in IPC together with the Liferay Faces CDI bridge - not sure if a book is of help here ;-) But thanks for the hint!

Cheers
Bernd
thumbnail
Michael Scholz, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

Junior Member Publications: 47 Date d'inscription: 03/09/13 Publications récentes
Hi together,

I just had a look into class com.liferay.cdi.portlet.bridge.CDIPortletFilter and it actually DOES NOT IMPLEMENT javax.portlet.filter.EventFilter but instead javax.xml.stream.EventFilter.

This seems weird!

Maybe just a wrong import in CDIPortletFilter?!?

I will try to write an own implementation of it implementing the right interface and use it instead of the given one.

Regards,

Michael
thumbnail
Michael Scholz, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

Junior Member Publications: 47 Date d'inscription: 03/09/13 Publications récentes
Yey!

try this as implementation for CDIPortletFilter and the Exception no longer occurs!

package com.liferay.cdi.portlet.bridge;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.filter.ActionFilter;
import javax.portlet.filter.EventFilter;
import javax.portlet.filter.FilterChain;
import javax.portlet.filter.FilterConfig;
import javax.portlet.filter.RenderFilter;
import javax.portlet.filter.ResourceFilter;

public class CDIPortletFilter
    implements ActionFilter, EventFilter, RenderFilter, ResourceFilter {

    public void destroy() {
    }

    @Override
    public void doFilter(
            EventRequest eventRequest, EventResponse eventResponse,
            FilterChain filterChain)
        throws IOException, PortletException {
        
        CDIRequestFactory cdiRequestFactory = getCDIRequestFactory();

        eventRequest = cdiRequestFactory.getCDIEventRequest(eventRequest);

        CDIResponseFactory cdiResponseFactory = getCDIResponseFactory();

        eventResponse = cdiResponseFactory.getCDIEventResponse(
            eventResponse, eventRequest.getLocale());

        filterChain.doFilter(eventRequest, eventResponse);
    }

    public void doFilter(
            ActionRequest actionRequest, ActionResponse actionResponse,
            FilterChain filterChain)
        throws IOException, PortletException {

        CDIRequestFactory cdiRequestFactory = getCDIRequestFactory();

        actionRequest = cdiRequestFactory.getCDIActionRequest(actionRequest);

        CDIResponseFactory cdiResponseFactory = getCDIResponseFactory();

        actionResponse = cdiResponseFactory.getCDIActionResponse(
            actionResponse, actionRequest.getLocale());

        filterChain.doFilter(actionRequest, actionResponse);
    }

    public void doFilter(
            RenderRequest renderRequest, RenderResponse renderResponse,
            FilterChain filterChain)
        throws IOException, PortletException {

        CDIRequestFactory cdiRequestFactory = getCDIRequestFactory();

        renderRequest = cdiRequestFactory.getCDIRenderRequest(renderRequest);

        CDIResponseFactory cdiResponseFactory = getCDIResponseFactory();

        renderResponse = cdiResponseFactory.getCDIRenderResponse(
            renderResponse, renderRequest.getLocale());

        filterChain.doFilter(renderRequest, renderResponse);
    }

    public void doFilter(
            ResourceRequest resourceRequest, ResourceResponse resourceResponse,
            FilterChain filterChain)
        throws IOException, PortletException {

        CDIRequestFactory cdiRequestFactory = getCDIRequestFactory();

        resourceRequest = cdiRequestFactory.getCDIResourceRequest(
            resourceRequest);

        CDIResponseFactory cdiResponseFactory = getCDIResponseFactory();

        resourceResponse = cdiResponseFactory.getCDIResourceResponse(
            resourceResponse, resourceRequest.getLocale());

        filterChain.doFilter(resourceRequest, resourceResponse);
    }

    public void init(FilterConfig filterConfig) {
    }

    protected CDIRequestFactory getCDIRequestFactory() {
        if (_cdiRequestFactory == null) {
            _cdiRequestFactory =
                (CDIRequestFactory)CDIBeanManagerUtil.getManagedBeanReference(
                    CDIRequestFactory.class);
        }

        return _cdiRequestFactory;
    }

    protected CDIResponseFactory getCDIResponseFactory() {
        if (_cdiResponseFactory == null) {
            _cdiResponseFactory =
                (CDIResponseFactory)CDIBeanManagerUtil.getManagedBeanReference(
                    CDIResponseFactory.class);
        }

        return _cdiResponseFactory;
    }

    private CDIRequestFactory _cdiRequestFactory;
    private CDIResponseFactory _cdiResponseFactory;
}
thumbnail
Michael Scholz, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

Junior Member Publications: 47 Date d'inscription: 03/09/13 Publications récentes
I reported an issue: LPS-39592
thumbnail
Neil Griffin, modifié il y a 10 années.

RE: Using CDI and IPC results in ClassCastException of class EventRequestIm

Liferay Legend Publications: 2655 Date d'inscription: 27/07/05 Publications récentes
Michael,

Thanks so much for finding the EventFilter problem and for creating LPS-39592! emoticon

I have assigned the issue to myself and should be able to get it fixed in the next couple of weeks.

Kind Regards,

Neil