Update
I'm currently over at the ICEfaces forums to get my problem solved - sadly, none of the provided options led to a solution now, but they indeed gave me some more insight into the whole JSF topic (credits go to BalusC for that, as often :-)).
I will try to keep this thread up to date and post an answer if the problem is finally solved to help others which may encounter it.
My findings so far are:
- Disabling the Seam Multipart Filter is required because it prevents the fileEntry-component from working correctly
- I still have some nasty library issues in my application resulting in (silent) ClassLoading-issues: 2 icefaces-ace.jar-files were present, one in EAR/lib and one in EAR/WAR/WEB-INF/lib. Removing the one from WEB-INF results in the component doing nothing, removing the one from EAR/lib results in my app not longer deploying.
When moving all frontend jars (icefaces.jar, icefaces-ace.jar, icefaces-compat.jar) from EAR/lib to WEB-INF/lib, I receive various ClassNotFoundExceptions for the jar-part of my EAR: ValueChangeEvent, RowSelectorEvent etc. could not be found (that means, all those events coming from the view into the backend). Example:
12:12:42,145 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-16) MSC00001: Failed to start service jboss.deployment.subunit."myApp.ear"."myApp.jar".POST_MODULE: org.jboss.msc.service.StartException in service jboss.deployment.subunit."myApp.ear"."myApp.jar".POST_MODULE: Failed to process phase POST_MODULE of subdeployment "myApp.jar" of deployment "myApp.ear" at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:119) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final] at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811) [jboss-msc-1.0.2.GA.jar:1.0.2.GA] at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746) [jboss-msc-1.0.2.GA.jar:1.0.2.GA] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) [rt.jar:1.7.0_06] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) [rt.jar:1.7.0_06] at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_06] Caused by: java.lang.RuntimeException: Error getting reflective information for class my.company.myApp.myExampleBean with ClassLoader ModuleClassLoader for Module "deployment.myApp.ear.myApp.jar:main" from Service Module Loader at org.jboss.as.server.deployment.reflect.DeploymentReflectionIndex.getClassIndex(DeploymentReflectionIndex.java:70) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final] at org.jboss.as.ee.metadata.MethodAnnotationAggregator.runtimeAnnotationInformation(MethodAnnotationAggregator.java:58) at org.jboss.as.ee.component.deployers.InterceptorAnnotationProcessor.handleAnnotations(InterceptorAnnotationProcessor.java:85) at org.jboss.as.ee.component.deployers.InterceptorAnnotationProcessor.processComponentConfig(InterceptorAnnotationProcessor.java:70) at org.jboss.as.ee.component.deployers.InterceptorAnnotationProcessor.deploy(InterceptorAnnotationProcessor.java:55) at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:113) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final] ... 5 more Caused by: java.lang.NoClassDefFoundError: com/icesoft/faces/component/ext/RowSelectorEvent at java.lang.Class.getDeclaredMethods0(Native Method) [rt.jar:1.7.0_06] at java.lang.Class.privateGetDeclaredMethods(Class.java:2442) [rt.jar:1.7.0_06] at java.lang.Class.getDeclaredMethods(Class.java:1808) [rt.jar:1.7.0_06] at org.jboss.as.server.deployment.reflect.ClassReflectionIndex.<init>(ClassReflectionIndex.java:65) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final] at org.jboss.as.server.deployment.reflect.DeploymentReflectionIndex.getClassIndex(DeploymentReflectionIndex.java:66) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final] ... 10 more Caused by: java.lang.ClassNotFoundException: com.icesoft.faces.component.ext.RowSelectorEvent from [Module "deployment.myApp.ear.myApp.jar:main" from Service Module Loader] at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190) [jboss-modules.jar:1.1.1.GA] at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:468) [jboss-modules.jar:1.1.1.GA] at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:456) [jboss-modules.jar:1.1.1.GA] at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398) [jboss-modules.jar:1.1.1.GA] at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:120) [jboss-modules.jar:1.1.1.GA] ... 15 more The whole story
I'm working on an web application, using Seam 2.3 and ICEfaces 3.1.0. That means, JSF2 is being used.
My app is deployed on JBoss AS 7.1.0 as an EAR, containing a JAR for application logic and a WAR for all view related stuff.
I recently migrated from Seam 2.1.2 to Seam 2.3 and ICEfaces 1.8.2 to 3.1.0. That step was terrible, but now everything works fine, leaving aside some minor issues.
The only big issue is, when I'm using components to upload files, no matter if I use Seam components or ICEfaces components - in Seam, the uploaded file is always null and in ICEfaces, my fileEntryListener-Method never gets called.
With ICEfaces:
In ICEfaces versions prior to 2.X, there was the ice:inputFile-component which has been removed with 2.X and replaced with ace:fileEntry.
InputFile was working good, but FileEntry does not. My problem is exact the same as described in JSF : Issues with File Upload using Icefaces component - the fileEntryListener is never called. I tried the suggestions there (using enctype="multipart/form-data" on the surrounding form, using h:commandButton for form submission), but it didn't work. The only solution provided was switching to Richfaces, which is not an option for me.
With Seam:
Gladly, Seam has it's own build-in fileUpload-component, s:fileUpload.
It doesn't work either, but at least showed me a spot where to look further. When debugging the doDecode-Methods of this component, I found that my request is no MultipartRequest. Crazy thing! All the forms used for uploading files declare the enctype as multipart/form-data. I think, the same is happening when I'm trying to use the ICEfaces component - no multipart request and that leads to no listeners being called.
So: How do I get this to work? What's the point that no Request comes in as MultipartRequest? Do I miss something in web/components.xml?
web.xml:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xmlns/ javaee/web-app_3_0.xsd" version="3.0"> <listener> <listener-class>org.jboss.seam.servlet.SeamListener</listener-class> </listener> <filter> <filter-name>Seam Filter</filter-name> <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class> </filter> <filter-mapping> <filter-name>Seam Filter</filter-name> <url-pattern>*.seam</url-pattern> </filter-mapping> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/icefaces/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.seam</url-pattern> </servlet-mapping> <servlet> <servlet-name>Seam Resource Servlet</servlet-name> <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Seam Resource Servlet</servlet-name> <url-pattern>/seam/resource/*</url-pattern> </servlet-mapping> <servlet> <servlet-name>Resource Servlet</servlet-name> <servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Resource Servlet</servlet-name> <url-pattern>/xmlhttp/*</url-pattern> </servlet-mapping> <session-config> <session-timeout>60</session-timeout> </session-config> <context-param> <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>facelets.DEVELOPMENT</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>com.icesoft.faces.actionURLSuffix</param-name> <param-value>.seam</param-value> </context-param> <context-param> <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name> <param-value>-1</param-value> </context-param> <context-param> <param-name>com.icesoft.faces.synchronousUpdate</param-name> <param-value>false</param-value> </context-param> <context-param> <param-name>com.icesoft.faces.doJSFStateManagement</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>com.icesoft.faces.standardRequestScope</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>com.icesoft.faces.uploadDirectory</param-name> <param-value>upload</param-value> </context-param> <context-param> <param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name> <param-value>false</param-value> </context-param> components.xml (leaving out the Seam 2.3 namespace declarations
<core:init jndi-pattern="java:app/myApp/#{ejbName}" debug="false" distributable="false" /> <component class="org.jboss.seam.transaction.EjbSynchronizations" jndi-name="java:app/jboss-seam/EjbSynchronizations" /> <core:manager concurrent-request-timeout="500" conversation-timeout="90000000" conversation-id-parameter="cid" parent-conversation-id-parameter="pid" /> <web:hot-deploy-filter url-pattern="*.seam" /> <web:multipart-filter create-temp-files="true" max-request-size="1000000" url-pattern="/*"/> <persistence:managed-persistence-context name="entityManager" auto-create="true" persistence-unit-jndi-name="java:/myAppEntityManagerFactory" /> <security:identity authenticate-method="#{authenticator.authenticate}" /> <security:remember-me enabled="true" /> <security:rule-based-permission-resolver security-rules="#{securityRules}" /> <drools:rule-base name="securityRules"> <drools:rule-files> <value>/security.drl</value> </drools:rule-files> </drools:rule-base> <async:quartz-dispatcher /> <factory name="sessionTimeoutSeconds" scope="SESSION" value="#{facesContext.externalContext.getSession(true).getMaxInactiveInterval()}" /> <factory name="basePath" value="#{facesContext.externalContext.request.scheme}://#{facesContext.externalContext.request.serverName}: #{facesContext.externalContext.request.serverPort}#{facesContext.externalContext.request.contextPath}" /> <factory name="contextPath" value="#{facesContext.externalContext.request.contextPath}" /> Example JSF-source (Seam)
<h:form enctype="multipart/form-data"> <s:decorate> <s:fileUpload data="#{uploadBean.fileData}" contentType="#{uploadBean.contentType}" fileName="#{uploadBean.fileName}" /> <h:commandButton value="Upload File" type="submit" /> </s:decorate> </h:form> Example JSF-source (ICEfaces)
<h:form enctype="multipart/form-data"> <ace:fileEntry id="file-entry" relativePath="/files/" fileEntryListener="#{uploadBean.uploadFile}" useSessionSubdir="true" /> <h:commandButton id="submit" type="submit" value="Send File" /> </h:form> JSF maps to a Seam component, having a byte[] for fileData and String's for fileName and contentType. The fileEntryListener maps to a void method which takes a FileEntryEvent as input.
Update
Just to keep you up to date, my findings so far:
Thinking about BalusC's answer, I looked deeper into the filter stuff. I already tried to add/remove the Seam Multipart Filter, but now I found out that when I add it in components.xml and explicitly disable it via
<web:multipart-filter disabled="true"/> at least something is happening with ICEfaces: Exceptions are thrown by the FileEntryPhaseListener, what has never happened before:
At least this is something to look at. If I use the fileEntryListener like
fileEntryListener="#{uploadBean.fileUploadListener}" the above exception is thrown, if I use:
fileEntryListener="#{uploadBean.fileUploadListener()}" It complains that the method requires parameters and if I use it like:
fileEntryListener="#{uploadBean.fileUploadListener(null)}" no exceptions are thrown, but due to the event being null, no files reach my UploadBean. Smells like some library issues, but at least something else to look at.
Upload bean
Not much happens here, it's simply:
@Stateful @Name("uploadBean") @Scope(ScopeType.SESSION) @JndiName(value = "java:app/myApp.jar/UploadBean") public class UploadBean implements IUploadBean { public void fileUploadListener(FileEntryEvent event) { System.out.println("listener called!"); } } Listener is declared in the bean's interface, too.