5 Replies Latest reply on Jun 6, 2012 3:10 PM by shadowcreeper

    JBoss 5 deployment ordering (.last directory) issues


      When deploying an EAR in ...server/default/deploy/deploy.last/ (so that it will not be started until everything else has started) there is complete failure of all included beans.


      Apparently, if there are beans in the EAR, it is in some cases listed (incorrectly?) in JNDI as "...ear=deploy.last,jar=..." rather that "...ear=test-ear.ear,jar=..."

      According to the server log, the bean is (incorrectly?) bound to "deploy/TestSoloBean/local" rather than "test-ear/TestSoloBean/local"


      I have attached a simple test case deploy.last directory with sources (using JBoss 5.1.0.GA).


      Server log file details:


      12:03:14,081 INFO  [JBossASKernel] Created KernelDeployment for: test-ejb-01.00.00.jar

      12:03:14,081 INFO  [JBossASKernel] installing bean: jboss.j2ee:jar=test-ejb-01.00.00.jar,name=TestSoloBean,service=EJB3

      12:03:14,081 INFO  [JBossASKernel]   with dependencies:

      12:03:14,081 INFO  [JBossASKernel]   and demands:

      12:03:14,081 INFO  [JBossASKernel]      jboss.ejb:service=EJBTimerService

      12:03:14,081 INFO  [JBossASKernel]   and supplies:

      12:03:14,081 INFO  [JBossASKernel]      jndi:deploy/TestSoloBean/local-test.server.ejb.TestSolo

      12:03:14,082 INFO  [JBossASKernel]      jndi:deploy/TestSoloBean/remote

      12:03:14,082 INFO  [JBossASKernel]      jndi:deploy/TestSoloBean/local

      12:03:14,082 INFO  [JBossASKernel]      Class:test.server.ejb.TestSolo

      12:03:14,082 INFO  [JBossASKernel] Added bean(jboss.j2ee:jar=test-ejb-01.00.00.jar,name=TestSoloBean,service=EJB3) to KernelDeployment of: test-ejb-01.00.00.jar

      12:03:14,082 INFO  [EJB3EndpointDeployer] Deploy AbstractBeanMetaData@4f94aaa1{name=jboss.j2ee:ear=deploy.last,jar=test-ejb-01.00.00.jar,name=TestSoloBean,service=EJB3_endpoint bean=org.jboss.ejb3.endpoint.deployers.impl.EndpointImpl properties=[container] constructor=null autowireCandidate=true}

      12:03:14,098 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=test-ejb-01.00.00.jar,name=TestSoloBean,service=EJB3

      12:03:14,098 INFO  [EJBContainer] STARTED EJB: test.server.ejb.TestSoloBean ejbName: TestSoloBean

      12:03:14,103 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:


              deploy/TestSoloBean/local - EJB3.x Default Local Business Interface

              deploy/TestSoloBean/local-test.server.ejb.TestSolo - EJB3.x Local Business Interface


      12:03:14,142 ERROR [ProfileServiceBootstrap] Failed to load profile: Summary of incomplete deployments (SEE PREVIOUS ERRORS FOR DETAILS):



        Deployment "jboss.j2ee:ear=deploy.last,jar=test-ejb-01.00.00.jar,name=TestSoloBean,service=EJB3_endpoint" is missing the following dependencies:

          Dependency "jboss.j2ee:ear=deploy.last,jar=test-ejb-01.00.00.jar,name=TestSoloBean,service=EJB3" (should be in state "Configured", but is actually in state "** NOT FOUND Depends on 'jboss.j2ee:ear=deploy.last,jar=test-ejb-01.00.00.jar,name=TestSoloBean,service=EJB3' **")



        Deployment "jboss.j2ee:ear=deploy.last,jar=test-ejb-01.00.00.jar,name=TestSoloBean,service=EJB3" is in error due to the following reason(s): ** NOT FOUND Depends on 'jboss.j2ee:ear=deploy.last,jar=test-ejb-01.00.00.jar,name=TestSoloBean,service=EJB3' **



      Could somebody tell me if this is a bug? Or, if not, what I am doing wrong and if possible how to work around the issue?


      The only way to get the ".last" directory to deploy anything is if the EAR in the ".last" directory has no beans.



        • 1. Re: JBoss 5 deployment ordering (.last directory) issues

          Are there any specific reasons why one would like to deploy the applications at the end once server started rather allowing it to deploy when ever server finds?

          • 2. Re: JBoss 5 deployment ordering (.last directory) issues

            Say you have app-0.ear which creates app-0/BeanA/remote which app-1.ear needs in order to start. Say also that app-1.ear creates app-1/BeanB/remote that app-2.ear needs.


            You now need to ensure that app-0.ear starts first, then app-1.ear, then app-2.ear. In this one instance you are good since they are all in alphabetical order, but if they were named something a little more meaningful, they may not be in alphabetical order.


            These apps may be on separate JBoss servers or they may all be in the same one. In JBoss7 I hear there is a way you can define optional dependencies, so that they are pulled up in order if they exist, and ignored if they don't (since they may be running on another JBoss7 server). But I am not aware of any way to do this on JBoss5?

            • 3. Re: JBoss 5 deployment ordering (.last directory) issues

              But I am not aware of any way to do this on JBoss5?

              See jboss-deployment.xml and jboss-depenency.xml.

              * https://community.jboss.org/wiki/JBoss5CustomMetadataFiles

              • 4. Re: JBoss 5 deployment ordering (.last directory) issues

                Could you please provide more details?


                I looked at your page and tried using a jboss-dependency.xml file. This appears to work only if all beans are local (on the same JBoss server) and it causes failure if any dependencies could not be found (are on a separate JBoss server). I am unsure how jboss-deployment.xml fits in to this problem.



                • 5. Re: JBoss 5 deployment ordering (.last directory) issues

                  This is a bug in JBoss 5. A ticket has been logged in JIRA: http://issues.jboss.org/browse/JBAS-9487


                  I found a workaround to this issue.


                  You must create a custom {code}Comparator<DeploymentContext>{code}, something like the following:


                  /** A comparator for deploying jboss contexts with {@link #DIRECTORY_LAST_TEXT} in their name after all others. */

                  public class OrderedDeploymentContextComparator

                     extends LegacyDeploymentContextComparator


                     public static final OrderedDeploymentContextComparator INSTANCE = new OrderedDeploymentContextComparator();

                     private static final Comparator<String> DIRECTORY_LAST_TEXT_COMPARATOR = new OrderedDeploymentContextDirectoryComparator();


                     private static final String DIRECTORY_LAST_TEXT = "-last/";

                     private static final int DIRECTORY_LAST_TEXT_LENGTH = DIRECTORY_LAST_TEXT.length();


                     public int compare ( DeploymentContext c1, DeploymentContext c2 )


                        final String name1 = c1.getName();

                        final String name2 = c2.getName();

                        if( name1.contains( DIRECTORY_LAST_TEXT ) && name2.contains( DIRECTORY_LAST_TEXT ) )


                           int comparison = DIRECTORY_LAST_TEXT_COMPARATOR.compare( name1, name2 );

                           // use the legacy comparator if both contexts are in the same "-last" directory

                           return comparison == 0 ? super.compare( c1, c2 ) : comparison;


                        if( name1.contains( DIRECTORY_LAST_TEXT ) )

                           return 1;

                        if( name2.contains( DIRECTORY_LAST_TEXT ) )

                           return -1;

                        // neither context is in a "-last" directory, use legacy comparator

                        return super.compare( c1, c2 );



                     public static OrderedDeploymentContextComparator getInstance ()


                        return INSTANCE;



                     Object readResolve ()


                        return INSTANCE;





                  And a custom {code}Comparator<String>{code}, which sorts directory entries, something like the following:


                      /** Compares "-last" directories only, recursively, returns 0 if nested identically. */

                     public class OrderedDeploymentContextDirectoryComparator

                        implements Comparator<String>


                        public int compare ( String s1, String s2 )


                           final int indexLast1 = s1.indexOf( DIRECTORY_LAST_TEXT );

                           final int indexLast2 = s2.indexOf( DIRECTORY_LAST_TEXT );

                           if( indexLast1 >= 0 && indexLast2 >= 0 )


                              final int preLastSlash1 = s1.substring( 0, indexLast1 ).lastIndexOf( "/" );

                              final int preLastSlash2 = s2.substring( 0, indexLast2 ).lastIndexOf( "/" );

                              final String dirLast1 = s1.substring( preLastSlash1 + 1, indexLast1 );

                              final String dirLast2 = s2.substring( preLastSlash2 + 1, indexLast2 );

                              final int comparison = dirLast1.compareTo( dirLast2 );

                              if( comparison != 0 )

                                 return comparison;

                              // both current-level "-last" directories identical, check for nested "-last" directories

                              final String postLast1 = s1.substring( indexLast1 + DIRECTORY_LAST_TEXT_LENGTH );

                              final String postLast2 = s2.substring( indexLast2 + DIRECTORY_LAST_TEXT_LENGTH );

                              return compare( postLast1, postLast2 );


                           if( indexLast1 >= 0 )

                              return 1;

                           if( indexLast2 >= 0 )

                              return -1;

                           // both strings represent the same "-last" directory

                           return 0;





                  Then modify server/.../conf/bootstrap/deployers.xml to include the jar containing the above to classes and use the {code}Comparator<DeploymentContext>{code} (whatever class name you gave it) as the topContextComparator. You should also leave an entry for the old {code}org.jboss.system.deployers.LegacyDeploymentContextComparator{code} as "otherContextComparator" so that it gets setup and can still be used to sort between deployments within your ear file.


                  Now you can use "deploy-last" rather than "deploy.last" to do the same thing but without the issues.


                  I hope this helps others too.