5 Replies Latest reply on Jan 31, 2010 2:45 AM by Arbi Sookazian

    Mavenized seam, exploded ears and hot deployment

    Riccardo Serafin Newbie

      The other day i was trying to have the seam hot deploy feature working with my mavenized, ear-packaged, seam application running on JBoss 4.2.3. As this proved tricky (for me) and made me waste a lot of time, I though it could be helpful for others to write down how in the end I managed to get it working.


      In order to have hot deployment working you need to have the application deployed to JBoss as an exploded ear, as you then need access to the war/WEB-INF/dev directory to redeploy. So the first problem was how to get the exploded ear working. My original ear was packaged like this:


      ear.ear
      - ejb.jar
      - war.war
      ->META-INF
          application.xml
          etc.
      ->lib
          jboss-seam.jar
          all others jars
      



      with jboss-seam.jar referenced as a module in application.xml


      ...
      <module>
          <ejb>lib/jboss-seam.jar</ejb>
      </module>
      ...
      



      This configuration worked just fine when the application was deployed as a normal ear, but
      unfortunately it created the nasty problem of the SeamPhaseListener being installed twice when deployed as an exploded ear. After many trials, I discovered that apparently JBoss was deploying the seam jar twice, once as a lib and once as module. To solve the problem, I needed to change the location of the seam jar and put it in the root directory (and of course change accordingly the application.xml). So the final layout looks like:


      ear.ear
      - ejb.jar
      - jboss-seam.jar
      ->war.war
          - all xhtml resources, properties, page.xml, etc.
          ->META-INF
          ->WEB-INF
              - all descriptors (components.xml, web.xml, etc.)
              ->classes
                  - non hot deployment classes.
                  - seam.properties
              ->dev
                  - hot deployment classes.
      ->META-INF
          application.xml
          etc.
      ->lib
          all others lib jars
      



      and application.xml:


      ...
      <module>
          <ejb>jboss-seam.jar</ejb>
      </module>
      ...
      



      Finally, to enabled hot deployment I created a separated maven module that I use to contain all needed classes during development (which then I move to the proper modules when done).


      A couple of maven-antrun-plugin are then used both to copy and explode the ear to jboss during the packaging phase (in a separated development profile in the ear pom), and to copy the hot deployment classes (in hot module). For instance like this:


      <plugins>
              <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.1</version>
                <executions>
                     <execution>
                          <id>hot-deploy</id>
                          <phase>process-classes</phase>
                          <configuration>
                               <tasks>
                                    <copy toDir="${jboss.deploy.dir}/ear.ear/web.war/WEB-INF/dev" overwrite="true">
                                         <fileset dir="${project.build.directory}/classes" >
                                              <include name="**/*.class"/>
                                         </fileset>
                                    </copy>
                               </tasks>
                          </configuration>
                          <goals>
                               <goal>run</goal>
                          </goals>
                     </execution>
                </executions>
           </plugin>
      </plugins>
      



      The important point here, however, is that for ear exploded deployment the seam jar can't be put in the lib directory but must be placed in the root ear directory. Hope this can help someone else to avoid some wasted time to figure this out.


      Best,
      Riccardo.

        • 1. Re: Mavenized seam, exploded ears and hot deployment
          Viggo Navarsete Expert
          Hi,

          I'm in the same process as you've been into: Create a perfect development environment based Seam + Maven (running inside JBoss Developer Studie/Eclipse).
          Would you mind sharing your pom.xml files as well as the solution to the problem? The hard part for us has been to create the pom files so that it creates the same result (ear) as a vanilla seam generated project.
          • 2. Re: Mavenized seam, exploded ears and hot deployment
            Sander S Newbie

            I created a setup like this a while with the use of the assembly plugin, you can use filters to select the classes that should be in the hotdeployment /dev directory and do unpack stuff. Therefore seam compoments must be in different packages then the other things to do effective filtering.


            It would be best when seam components are on a different build path for eclipse so you can set the build for eclipse direct to the /dev dir. Downside here is that you'd need another buildpath (besides src/main/java) and that is something you'd might not want. plus you'd need to add this buildpath to the standard maven source buildpath. Plus side is that you dont need to do the maven build everytime and just let eclipse do the building of the components for even faster development. I choose not to, but just something to think about.


            I should have the assembly file somewhere but cannot find it right now, if I'd find it I'll post it, but don't count on it.


            The assembly plugin is well documented, use assembly:directory


            I might even be possible to create different profiles for development and production  so that there is no /dev directory for production but I havent tried that


            Good luck!

            • 3. Re: Mavenized seam, exploded ears and hot deployment
              Viggo Navarsete Expert

              Thanks a lot for the input!! I'll jump into the code tomorrow when I'm back at work (evening i Norway now..). If I stumble into any problems I'll share them here at the forum :)

              • 4. Re: Mavenized seam, exploded ears and hot deployment
                Arbi Sookazian Master

                Looks like this is what I'm looking for.  Anybody had success with these instructions?  How is the exploded EAR being copied to JBoss?

                • 5. Re: Mavenized seam, exploded ears and hot deployment
                  Arbi Sookazian Master

                  Perhaps this would be helpful as well:  https://jira.jboss.org/jira/browse/JBSEAM-2026


                  <profile>
                       <id>hot</id>
                       <activation>
                            <property>
                                 <name>mode</name>
                                 <value>hot</value>
                            </property>
                       </activation>
                       <build>
                            <plugins>
                                 <plugin>
                                      <artifactId>maven-antrun-plugin</artifactId>
                                      <executions>
                                           <execution>
                                                <!-- NOTE: sync the hot-deployable class files and the web resources -->
                                                <id>hot-deploy-sync</id>
                                                <phase>process-classes</phase>
                                                <goals>
                                                     <goal>run</goal>
                                                </goals>
                                                <configuration>
                                                     <tasks>
                                                          <copy todir="target/${project.build.finalName}/WEB-INF/dev">
                                                               <fileset dir="${project.build.outputDirectory}">
                                                                    <!-- adjust the pattern here to define what gets hot deployed -->
                                                                    <include name="**/*.class"/>
                                                                    <exclude name="**/model/**/*.class"/>
                                                               </fileset>
                                                          </copy>
                                                          <copy todir="target/${project.build.finalName}/WEB-INF/dev">
                                                               <fileset dir="src/main/groovy">
                                                                    <!-- assumes Groovy classes aren't entities (which aren't hot deployable) -->
                                                                    <include name="**/*.groovy"/>
                                                               </fileset>
                                                          </copy>
                                                          <!-- sync the web resources eagerly -->
                                                          <copy todir="target/${project.build.finalName}">
                                                               <fileset dir="src/main/webapp">
                                                                    <include name="**/*"/>
                                                                    <exclude name="WEB-INF/web.xml"/>
                                                                    <exclude name="META-INF/context.xml"/>
                                                               </fileset>
                                                          </copy>
                                                     </tasks>
                                                </configuration>
                                           </execution>
                                           <execution>
                                                <!-- NOTE: purge the non-hot deployable class files from the exploded archive -->
                                                <id>hot-deploy-purge</id>
                                                <phase>package</phase>
                                                <goals>
                                                     <goal>run</goal>
                                                </goals>
                                                <configuration>
                                                     <tasks>
                                                          <delete>
                                                               <fileset dir="target/${project.build.finalName}/WEB-INF/classes">
                                                                    <include name="**/*.class"/>
                                                                    <!-- adjust the pattern here to define what gets hot deployed (same as above) -->
                                                                    <exclude name="**/model/**/*.class"/>
                                                               </fileset>
                                                          </delete>
                                                     </tasks>
                                                </configuration>
                                           </execution>
                                      </executions>
                                 </plugin>
                                 <!-- duplicate the war plugin here to exclude compiled groovy classes -->
                                 <!-- NOTE: unfortunately, there is no way to keep files out of the staging area, 
                                      so the generated package is going to have hot-deployable classes in WEB-INF/classes -->
                                 <plugin>
                                      <artifactId>maven-war-plugin</artifactId>
                                      <version>2.0.2</version>
                                      <!--
                                      <version>2.1-alpha-2-SNAPSHOT</version>
                                      -->
                                      <configuration>
                                           <outputDirectory>${project.build.directory}/dist</outputDirectory>
                                           <!-- when the packagingExcludes becomes available (>=2.1), we can simply copy
                                           the Java classes into the hot deployment classloader -->
                                           <!--
                                           <packagingExcludes>WEB-INF/classes/**</packagingExcludes>
                                           -->
                                           <warSourceExcludes>META-INF/context.xml</warSourceExcludes>
                                           <webResources>
                                                <resource>
                                                     <directory>${basedir}/src/main/webapp</directory>
                                                     <filtering>true</filtering>
                                                     <targetPath>/</targetPath>
                                                     <includes>
                                                          <include>WEB-INF/web.xml</include>
                                                     </includes>
                                                </resource>
                                           </webResources>
                                      </configuration>
                                 </plugin>
                            </plugins>
                       </build>
                       <dependencies>
                            <dependency>
                                 <groupId>org.jboss.seam</groupId>
                                 <artifactId>jboss-seam-debug</artifactId>
                            </dependency>
                       </dependencies>
                       <properties>
                            <mode>dev</mode>
                            <debug>true</debug>
                       </properties>
                  </profile>