14 Replies Latest reply on Aug 31, 2010 6:22 AM by jaikiran pai

    AS bootime improvement - On demand deployment of EJB3 timerservice

    jaikiran pai Master

      Since JBoss AS 6.0.0.M4 JBoss EJB3 has moved to a new timerservice implementation for EJB3.1 which is now based on JPA. Ever since this was integrated into AS, people who keep a watch on the AS boot time would have noticed that the AS startup time is increased by around 3-4 seconds. These 3-4 seconds are spent on deploying the persistence unit contained in the timerservice implementation. This new timerservice implementation is only relevant for EJB3.x deployments, which means that we really don't have to deploy it until there's a first EJB3.x deployment in the server. By default, AS doesn't ship any EJB3.x (or other EJB) apps. This means that we can save these 3-4 seconds by deploying the timerservice on demand.  So with that in mind, I decided to come up with a way to deploy timerservice only when there's a first EJB3.x deployment. Inspired by Brian's on-demand web application deployment support since 6.0.0.M2 (http://community.jboss.org/thread/147220 and http://community.jboss.org/wiki/On-DemandDeploymentofWebApplications), I now have a org.jboss.ejb3.deployers.MetaDataBasedOnDemanDeploymentDeployer (within AS trunk). This deployer uses the ProfileService to deploy an on-demand EJB3 profile. The on-demand EJB3 profile currently consists of just one single deployment JBOSS_HOME/common/deploy/jboss-ejb3-timerservice-mk2.jar (Note that in this process, I have moved the timerservice deployment jar to JBOSS_HOME/common/deploy, similar to the admin-console.war). This deployer works as follows: 1) Picks up deployments which have JBossMetaData as a attachment 2) Further checks whether the JBossMetaData corresponds to EJB3.x deployment 3) If it's a EJB3.x deployment, it activates the profile configured (in the -deployer-jboss-beans.xml). That profile current contains timerservice deployment jar The code of the deployer is very similar to the OnDemandContextProfileManager (except that this new MetaDataBasedOnDemanDeploymentDeployer doesn't depend on any web related services, for obvious reasons). Here's what it looks like: {code:java} public class MetaDataBasedOnDemanDeploymentDeployer extends AbstractDeployer {    private static final Logger log = Logger.getLogger(MetaDataBasedOnDemanDeploymentDeployer.class);    private static final String DEFAULT_EJB3_ONDEMAND_PROFILE_NAME = "EJB3-OnDemand-Profile";    /** The profile service */    private ProfileService profileService;    /** The root of the profile */    private URI deploymentRoot;    /** The deployment names. */    private Collection deploymentNames;    /** Whether this node has activated its profile */    private boolean activated;    /** The profile service key domain */    private String profileDomain;    /** The profile service key server */    private String profileServer;    /** The profile service key name */    private String profileName;    /** The profile service key */    private ProfileKey profileKey;    private boolean activateOnDemand = true;    public MetaDataBasedOnDemanDeploymentDeployer()    {       this.setStage(DeploymentStages.POST_CLASSLOADER);       this.setInput(JBossMetaData.class);       // ordering       this.addInput(AttachmentNames.PROCESSED_METADATA);    }    /**     * Get the deployment root     *     * @return the deployment root     */    public URI getDeploymentRoot()    {       return deploymentRoot;    }    /**     * Set the deployment root.     *     * @param deploymentRoot the deployment root     */    public void setDeploymentRoot(URI deploymentRoot)    {       this.deploymentRoot = deploymentRoot;    }    /**     * Get the deployment names.     *     * @return the deployment names     */    public Collection getDeploymentNames()    {       return deploymentNames;    }    /**     * Set the deployment names     *     * @param deploymentNames the deployment names     */    public void setDeploymentNames(Collection deploymentNames)    {       this.deploymentNames = deploymentNames;    }    /**     * Set a single deployment     *     * @param name the deployment name     */    public void setSingleDeployment(String name)    {       this.deploymentNames = Collections.singleton(name);    }    /**     * Gets the value that should be used for the     * {@link ProfileKey#getDomain() domain} portion of     * the on-demand @{link Profile}'s {@link #getProfileKey() ProfileKey}.     *     * @return the domain, or null if not set     */    public String getProfileDomain()    {       return profileDomain;    }    /**     * Sets the value that should be used for the     * {@link ProfileKey#getDomain() domain} portion of     * the singleton @{link Profile}'s {@link #getProfileKey() ProfileKey}.     *     * @param profileDomain the domain, or null    */    public void setProfileDomain(String profileDomain)    {       this.profileDomain = profileDomain;    }    /**     * Gets the value that should be used for the     * {@link ProfileKey#getServer() server} portion of     * the on-demand @{link Profile}'s {@link #getProfileKey() ProfileKey}.     *     * @return the server, or null if not set     */    public String getProfileServer()    {       return profileServer;    }    /**     * Sets the value that should be used for the     * {@link ProfileKey#getServer() server} portion of     * the on-demand @{link Profile}'s {@link #getProfileKey() ProfileKey}.     *     * @param profileServer the server, or null    */    public void setProfileServer(String profileServer)    {       this.profileServer = profileServer;    }    /**     * Gets the value that should be used for the     * {@link ProfileKey#getName() name} portion of     * the on-demand @{link Profile}'s {@link #getProfileKey() ProfileKey}.     *     * @return the name, or null if not set and     *         {@link #setContextName(String) contextName} is also unset.     */    public String getProfileName()    {       if (profileName == null)       {          this.profileName = DEFAULT_EJB3_ONDEMAND_PROFILE_NAME;       }       return profileName;    }    /**     * Sets the value that should be used for the     * {@link ProfileKey#getName() name} portion of     * the singleton @{link Profile}'s {@link #getProfileKey() ProfileKey}.     *     * @param profileName the name, or null    */    public void setProfileName(String profileName)    {       this.profileName = profileName;    }    /**     * Gets whether this object has activated its profile.     *     * @return true if {@link #activateProfile()} has successfully     *         completed and {@link #releaseProfile()} has not been called;     *         false otherwise.     */    public boolean isActivated()    {       return activated;    }    /**     * Sets the ProfileService reference.     *     * @param profileService the profileService. Cannot be null    *     * @throws IllegalArgumentException if profileService is null    */    public void setProfileService(ProfileService profileService)    {       if (profileService == null)       {          throw new IllegalArgumentException("profileService is null");       }       this.profileService = profileService;    }       /**     * Gets whether the profile should be activated on during the {@link #start()}     * phase of this bean's deployment rather than on receipt of an HTTP request.     * This property allows a simple configuration to turn off the "on-demand"     * behavior for environments (e.g. production servers) where a more     * deterministic startup is appropriate.     *     * @return false if the profile should be activated as part of     *         startup of this bean; true if activation should     *         be deferred until an HTTP request is received. Default is     *         true    *             * @deprecated This is a temporary API for AS 6.0.0.M2; something else     *             may replace it in later releases     */    public boolean isActivateOnDemand()    {       return activateOnDemand;    }    /**     * Sets whether the profile should be activated on during the {@link #start()}     * phase of this bean's deployment rather than on receipt of an HTTP request.     * This property allows a simple configuration to turn off the "on-demand"     * behavior for environments (e.g. production servers) where a more     * deterministic startup is appropriate.     *     * @param activateOnDemand false if the profile should be     *                          activated as part of startup of this bean;     *                          true if activation should be     *                          deferred until an HTTP request is received.     *             * @deprecated This is a temporary API for AS 6.0.0.M2; something else     *             may replace it in later releases     */    public void setActivateOnDemand(boolean activateOnDemand)    {       this.activateOnDemand = activateOnDemand;    }    /**     * Builds a profile from the {@link #getURIList() URI list} and registers     * it under the configured {@link #getProfileKey()}.     */    public void start() throws Exception    {       if (profileService == null)       {          throw new IllegalStateException("Must configure ProfileService");       }       if (deploymentRoot == null)       {          throw new IllegalStateException("Must configure deployment root");       }       if (deploymentNames == null)       {          throw new IllegalStateException("Must configure deployment name(s)");       }       // TODO add dependencies on bootstrap profiles       String[] rootSubProfiles = new String[0];       // Create a hotdeployment profile       // FIXME JBAS-7720 restore hot deploy capability (and make it configurable too)       ProfileMetaData profileMetaData = ProfileMetaDataFactory.createFilteredProfileMetaData(getProfileName(),             deploymentRoot, this.deploymentNames.toArray(new String[this.deploymentNames.size()]));       this.profileKey = this.profileService.registerProfile(profileMetaData);       if (this.activateOnDemand == false)       {          // FIXME we don't validate as we expect the PS to do it at the end          // of startup; need to check if this is correct          activateProfile(false);       }    }    /**     * Unregisters the profile registered in {@link #start()}.     */    public void stop() throws Exception    {       ProfileKey profKey = null;       try       {          profKey = getProfileKey();       }       catch (IllegalStateException e)       {          return;       }       if (profileService != null && profKey != null)       {          try          {             // Inactivate first if needed             if (profileService.getActiveProfileKeys().contains(profKey))             {                releaseProfile();             }             profileService.unregisterProfile(profKey);          }          catch (NoSuchProfileException e)          {             log.warn("Could not unregister unknown profile " + profKey);          }          finally          {          }       }    }    /**     * Tells the ProfileService to     * {@link ProfileService#activateProfile(ProfileKey) activate the on-demand profile}.     */    public void activateProfile() throws Exception    {       activateProfile(true);    }    /**     * Gets the key for the {@link Profile} that we activate and release.     *     * @return the key. Will not return null    *     * @throws IllegalStateException if {@link #getProfileName()} returns null    *     * @see #getProfileDomain()     * @see #getProfileServer()     * @see #getProfileName()     */    public ProfileKey getProfileKey()    {       if (this.profileKey == null)       {          String profileName = getProfileName();          if (profileName == null)          {             throw new IllegalStateException("Must configure profileName or contextName before calling getProfileKey()");          }          this.profileKey = new ProfileKey(getProfileDomain(), getProfileServer(), profileName);       }       return this.profileKey;    }    @Override    public void deploy(DeploymentUnit unit) throws DeploymentException    {       if (this.isActivated())       {          return;       }       JBossMetaData metadata = unit.getAttachment(JBossMetaData.class);       if (metadata.isEJB3x() == false)       {          return;       }       // activate the on-demand profile       try       {          this.activateProfile(true);       }       catch (Exception e)       {          throw new DeploymentException("Could not activate on-demand profile: " + this.getProfileName()                + " while deploying unit: " + unit);       }    }    private synchronized void activateProfile(boolean validate) throws Exception    {       if (this.profileService == null)       {          throw new IllegalStateException("Must configure the ProfileService");       }       ProfileKey profKey = getProfileKey();       if (this.profileService.getActiveProfileKeys().contains(profKey) == false)       {          this.profileService.activateProfile(profKey);          if (validate)          {             // Validate if the activation was successful             this.profileService.validateProfile(profKey);          }          this.activated = true;       }       else       {          log.warn("Profile " + profKey + " is already activated");          this.activated = true;       }    }    /**     * Tells the ProfileService to {@link ProfileService#releaseProfile(ProfileKey) release the profile}.     * Called by the HASingletonController when we are no longer the singleton master.     */    private synchronized void releaseProfile() throws Exception    {       if (this.activated)       {          try          {             this.profileService.deactivateProfile(getProfileKey());          }          catch (NoSuchProfileException e)          {             log.warn("No Profile is registered under key " + getProfileKey());          }          this.activated = false;       }    } } {code} The deployer is configured as follows: {code:xml} <bean name="MetadataBasedOnDemandDeploymentDeployer" class="org.jboss.ejb3.deployers.MetaDataBasedOnDemanDeploymentDeployer">             <property name="profileService"><inject bean="jboss.profileservice:service=ProfileService"/></property>       <!-- Build a profile from the contents of this single URI -->       <property name="deploymentRoot">${jboss.common.base.url}deploy</property>       <property name="singleDeployment">jboss-ejb3-timerservice-mk2.jar</property>             <!--         Whether activation of the profile (i.e. deployment of the URI contents)         should be deferred until the first request (true) or done as part of         the start of this bean (false).                 WARNING: This configuration option may be altered in a subsequent AS 6.0         milestone release.                 FIXME: https://jira.jboss.org/jira/browse/JBAS-7714                -->       <property name="activateOnDemand">${jboss.as.deployment.ondemand:true}</property>    </bean>    {code}   I just gave this a try against AS trunk and I can see that my server boots 3-4 seconds faster (as expected). I have further tested that when there's a EJB3 deployment in the server, the timerservice is deployed on demand. This deployer probably need not be EJB3 specific, but I don't have any plans right now to make it more general. Expect for some name cleanup and javadocs, the current version looks good enough. If there are no objections, I plan to introduce this in AS trunk soon. Thoughts?

        • 1. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
          Ales Justin Master
          If there are no objections, I plan to introduce this in AS trunk soon. Thoughts?

          I would do it differently. :-)

           

          Since MC already has a notion of on_demand, and afais,

          you just need the right timer service present when EJB3.x deployment is deployed.

          (correct me if I'm wrong)

           

          So, you could deploy all of those timer beans as on_demand,

          and then keep an eye on them in this new deployer,

          simply just adding a <demands>those timer beans</demands> to the deployment,

          which would then automagically trigger their full install -- hence no need for extra PS deployment.

          • 2. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
            jaikiran pai Master

            Ales Justin wrote:

             


             

            Since MC already has a notion of on_demand, and afais,

            you just need the right timer service present when EJB3.x deployment is deployed.

            (correct me if I'm wrong)


            There will just be one timerservicefactory in the entire server, so all we have to do is pick it up. No problems there.

             

            Ales Justin wrote:

             


            So, you could deploy all of those timer beans as on_demand,

            and then keep an eye on them in this new deployer,

            simply just adding a <demands>those timer beans</demands> to the deployment,

            which would then automagically trigger their full install -- hence no need for extra PS deployment.

            I had thought about MC on-demand notion too :-) But that doesn't apply to this timerservice deployment because a timerservice deployment is just a JPA deployment (like any other user application) which has just one MC specific bean (the presence of which doesn't really play any part in the initialization). The important part is that, this JPA deployment is picked up by PersistenceUnitDeployers and Hibernate for the initialization and that's where the time is spent.

             

            To put in simpler terms, consider A.jar which contains persistence.xml. I don't want this jar to be deployed until there's an EJB3 deployment in the server.

            • 3. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
              Ales Justin Master
              To put in simpler terms, consider A.jar which contains persistence.xml. I don't want this jar to be deployed until there's an EJB3 deployment in the server.

              I see.

              Also no need for PS usage. ;-)

               

              Simply add jboss-deployment.xml in which you change deployment's required stage to some non-final stage.

              e.g. could be even PRE_PARSE

              And then in the new deployer simply change that deployment to fully installed.

               

              Simple info about jboss-deployment.xml:

              * http://community.jboss.org/wiki/JBoss5custommetadatafiles

              Or check our deployers tests, or let me know and I'll help you with this stuff.

              • 4. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
                jaikiran pai Master

                Ales Justin wrote:

                 

                I see.

                Also no need for PS usage. ;-)


                Cool :-) PS isn't really a requirement, so I'm ready to try simpler ways.

                 

                Ales Justin wrote:

                 

                Simply add jboss-deployment.xml in which you change deployment's required stage to some non-final stage.

                e.g. could be even PRE_PARSE

                And then in the new deployer simply change that deployment to fully installed.

                 

                Simple info about jboss-deployment.xml:

                * http://community.jboss.org/wiki/JBoss5custommetadatafiles

                Or check our deployers tests, or let me know and I'll help you with this stuff.

                Let me take a look at some of those tests and see what it takes. Will ping you if I can't get it working :-)

                • 5. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
                  jaikiran pai Master

                  I looked up a couple of test cases and a jboss-deployment.xml file on what you suggested. I get what has to be done with the jboss-deployment.xml:

                   

                  <deployment xmlns="urn:jboss:deployment:1.0" required-stage="PreDescribe" >
                  
                  
                  </deployment>
                  

                   

                  That would be the jboss-deployment.xml for the timerservice.jar file. Now I would additionally have a deployer, which would look for DUs containing, EJB3 JBossMetaData and if such a DU exists, I would then (somehow) get hold of the timerservice.jar DU and push it to "Real" stage:

                   

                  public class MetaDataBasedOnDemanDeploymentDeployer extends AbstractDeployer
                  {
                  ...
                      @Override
                     public void deploy(DeploymentUnit unit) throws DeploymentException
                     {
                        if (this.isActivated())
                        {
                           return;
                        }
                        JBossMetaData metadata = unit.getAttachment(JBossMetaData.class);
                  
                        if (metadata.isEJB3x() == false)
                        {
                           return;
                        }
                        // Push the DeploymentMetaData in timerservice.jar to "Real"(?)
                        // How?
                     }
                     
                  ...
                  }
                  

                   

                  A few questions related to this:

                   

                  1) How would this new deployer (MetaDataBasedOnDemanDeploymentDeployer or whatever we name it later) get hold of the timerservice.jar DU?
                  2) Is "pushing" the DeploymentMetaData of timerservice.jar DU to "Real" in this deployer the right thing? Or should it be pushed to some other state?
                  3) From what I understand of http://community.jboss.org/wiki/JBoss5custommetadatafiles, the "required-stage" attribute is meant to specify a DeploymentStage to which the deployment will be "stalled" until some other condition pushes it forward. Did I understand it right?

                  • 6. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
                    Ales Justin Master
                          // Push the DeploymentMetaData in timerservice.jar to "Real"(?)
                          // How?
                    

                    See the usage of DeployerClientChangeExt from Deployers.

                    That's the easy way of doing it.

                     

                    If you wanna that your deployer is portable to older - pre-DeployerClientChangeExt - code,

                    then there is a bit more work -- let me know if you need it.

                    1) How would this new deployer (MetaDataBasedOnDemanDeploymentDeployer or whatever we name it later) get hold of the timerservice.jar DU?

                    For DeployerClientChangeExt you only need the right name.

                     

                    For older handling, you would use MainDeployerStructure to get a hold of DeploymentUnit,

                    from which you would then get deployment's ControllerContext,

                    pushing this then to Controller::change.

                    2) Is "pushing" the DeploymentMetaData of timerservice.jar DU to "Real" in this deployer the right thing? Or should it be pushed to some other state?

                    To INSTALLED.

                    3) From what I understand of http://community.jboss.org/wiki/JBoss5custommetadatafiles, the "required-stage" attribute is meant to specify a DeploymentStage to which the deployment will be "stalled" until some other condition pushes it forward. Did I understand it right?

                    Exactly.

                    • 7. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
                      jaikiran pai Master

                      Ales Justin wrote:

                       

                            // Push the DeploymentMetaData in timerservice.jar to "Real"(?)
                            // How?
                      

                      See the usage of DeployerClientChangeExt from Deployers.

                      That's the easy way of doing it.

                       

                      If you wanna that your deployer is portable to older - pre-DeployerClientChangeExt - code,

                      then there is a bit more work -- let me know if you need it.

                      DeployerClientChangeExt is fine. I don't want it to work with the older versions (since that's out of scope).

                       

                       

                      Ales Justin wrote:

                       


                      1) How would this new deployer (MetaDataBasedOnDemanDeploymentDeployer or whatever we name it later) get hold of the timerservice.jar DU?

                      For DeployerClientChangeExt you only need the right name.

                       

                      The API looks easy enough, but the internal impl details are causing some issues. Here's what I mean -

                       

                      I now have the deployer which checks for presence of EJB3 deployments and then pushes timerservice deployment jar to INSTALLED state. The deploy() looks like this:

                       

                      @Override
                         public void deploy(DeploymentUnit unit) throws DeploymentException
                         {
                            if (this.isActivated())
                            {
                               return;
                            }
                            JBossMetaData metadata = unit.getAttachment(JBossMetaData.class);
                      
                            if (metadata.isEJB3x() == false)
                            {
                               return;
                            }
                            MainDeployer mainDeployer = unit.getMainDeployer();
                            if (mainDeployer instanceof DeployerClientChangeExt == false)
                            {
                               log.warn("MainDeployer " + mainDeployer + " isn't of type " + DeployerClientChangeExt.class
                                     + " Cannot install timerservice on-demand");
                               return;
                            }
                            DeployerClientChangeExt deployerClient = (DeployerClientChangeExt) mainDeployer;
                            log.info("Deploying on-demand deployment(s)");
                      
                            deployerClient.change(DeploymentStages.INSTALLED, true, this.deployments.toArray(new String[this.deployments.size()]));
                            this.activated = true;
                      
                         }
                      

                       

                      The "deployments" are passed through the bean config and points to the timerservice jar:

                       

                      <bean name="MetadataBasedOnDemandDeploymentDeployer"> 
                             
                                <property name="singleDeployment">${jboss.server.home.url}deploy/jboss-ejb3-timerservice-mk2.jar</property> 
                                
                          </bean> 
                      

                       

                      The deployment URI gets translated to file:/// URI. The VDF MainDeployerImpl internally stores top level deployments using vfs:/// scheme in a map. Effectively when the deployer calls:

                       

                      deployerClient.change(DeploymentStages.INSTALLED, true, this.deployments.toArray(new String[this.deployments.size()]));

                       

                      it can't find the deployment corresponding to that name and throws an exception.

                       

                      So I added a piece of code in my deployer to translate the file:/// URIs to VFS URIs:

                       

                      private Collection<String> getVFSDeploymentPaths()
                         {
                            Collection<String> vfsPaths = new HashSet<String>(this.deploymentURIs.size());
                            for (URI deployment : this.deploymentURIs)
                            {
                               VirtualFile virtualFile = VFS.getChild(deployment);
                               try
                               {
                                  vfsPaths.add(virtualFile.toURI().toString());
                               }
                               catch (URISyntaxException urse)
                               {
                                  log.warn("Cannot create VFS path for on-demand deployment: " + deployment + " Skipping this deployment");
                                  log.debug("Could not create vfs path for on-demand deployment: " + deployment, urse);
                               }
                            }
                            return vfsPaths;
                         }

                       

                       

                      This correctly translates the file:/// URIs to vfs:/// URIs. However, the new problem is - the timerservice jar is an exploded deployment. VFS.getChild() for that path leads to a vfs:/// URI with a trailing slash in the end (as documented in that API). Something like: vfs:///home/me/jboss/wc/jbossas/trunk/build/target/jboss-6.0.0-SNAPSHOT/server/default/deploy/jboss-ejb3-timerservice-mk2.jar/ . The MainDeployerImpl, however, internally stores the deployment against vfs:///home/me/jboss/wc/jbossas/trunk/build/target/jboss-6.0.0-SNAPSHOT/server/default/deploy/jboss-ejb3-timerservice-mk2.jar (note that there's no trailing slash). This again effectively leads to deployment not found exception.

                       

                      In short, I don't (yet) have a way to pass in the correct deployment name without any hacks and without making that deployer too brittle. I'll see if I can workaround this issue, but if you know of some easy way to fix this, then let me know.

                      • 8. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
                        Ales Justin Master
                        In short, I don't (yet) have a way to pass in the correct deployment name without any hacks and without making that deployer too brittle. I'll see if I can workaround this issue, but if you know of some easy way to fix this, then let me know.

                        What exactly do you need to load from that timer service jar?

                         

                        Since what about if we used the jboss-deployment.xml to the full extent?

                        e.g. setup lazy classloading filter, and MC/VDF would automagically push that deployment fwd when certain class is needed

                        --> no need for that deployer or deployment name details

                        • 9. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
                          jaikiran pai Master

                          Ales Justin wrote:

                           

                          In short, I don't (yet) have a way to pass in the correct deployment name without any hacks and without making that deployer too brittle. I'll see if I can workaround this issue, but if you know of some easy way to fix this, then let me know.

                          What exactly do you need to load from that timer service jar?

                           

                          I don't need to load anything. I just need the file path of that jar so that I can pass it to DeployerClientChangeExt.change() as the deployment name

                           

                          DeployerClientChangeExt.change(.., .., deploymentName); // deploymentName = path to timerservice.jar

                           

                           

                          Ales Justin wrote:

                          Since what about if we used the jboss-deployment.xml to the full extent?

                          e.g. setup lazy classloading filter, and MC/VDF would automagically push that deployment fwd when certain class is needed

                          --> no need for that deployer or deployment name details

                          Pushing the timerservice.jar for deployment isn't based on availability of certain classes. Instead it's based on the presence of a metadata type (JBossMetaData which is EJB3.x, in this case). The jboss-deployment.xml doesn't have ability to handle this condition on its own.

                          • 10. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
                            jaikiran pai Master

                            For now, I'll go with the initial profile service approach which worked out fine and doesn't look brittle. Later, when I find some time or if we decide to switch to jboss-deployment.xml, then I'll come back to this.

                            • 11. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
                              Ales Justin Master
                              Pushing the timerservice.jar for deployment isn't based on availability of certain classes. Instead it's based on the presence of a metadata type (JBossMetaData which is EJB3.x, in this case). The jboss-deployment.xml doesn't have ability to handle this condition on its own.

                              I think we don't understand eachother + plus the concept of jboss-deployment.xml is proorly documented.

                               

                              The idea behind jboss-classloading.xml is that you can setup classloading filters,

                              which on first hit would trigger push of owning dpeloyment fwd.

                              e.g. timer.jar is in Describe stage, waiting for some o.j.TimerImpl class to be loaded,

                              when something tries to load that class, the VDF will intercept it and act accordingly

                               

                              So, if you know your code somewhere needs some class from timer.jar, simply setup proper filter.

                              Or, we can hack this loading, by doing the "hack" exact classloding in your new deployer.

                              e.g. the deployer would load some class from the timer.jar, instead of needing to know the name details

                              • 12. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
                                Ales Justin Master
                                For now, I'll go with the initial profile service approach which worked out fine and doesn't look brittle. Later, when I find some time or if we decide to switch to jboss-deployment.xml, then I'll come back to this.

                                The PS approach looks too complicated, as it involves having timer.jar outside normal deployment paths; e.g. not in deploy/.

                                And using PS inside VDF looks odd -- you're already in VDF, simply take advantage of it.

                                 

                                Anyway, I cannot stop you from what you're doing,

                                but I think it's never good to jump into 1st-solution notion -- just for the sake "cuz it's working". ;-)

                                • 13. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
                                  jaikiran pai Master

                                  Ales Justin wrote:

                                   

                                  I think we don't understand eachother + plus the concept of jboss-deployment.xml is proorly documented.

                                   

                                  Let's for a moment forget that the timerservice.jar is a system level deployment. Let's just consider it to be a plain user deployment. That will help in understanding what I'm trying to do. So:

                                   

                                  1) I have a myapp.jar which looks like this:

                                   

                                  myapp.jar
                                  |
                                  |--- META-INF
                                  |        |
                                  |        |--- persistence.xml
                                  |
                                  |--- [other things]

                                   

                                  2) That's just a plain JPA deployment in the "deploy" folder.

                                  3) When the server boots up, the persistence unit deployers and other hibernate related code picks up this deployment and starts processing it - which including checking for DB tables, mapping the entities to tables etc...

                                  4) I want to avoid step#3 until the server contains a deployment which is an EJB3 deployment. i.e. I don't want myapp.jar to be processed/deployed until there's a blah.jar which is an EJB3 deployment.

                                   

                                  As can be seen, the condition to deploy doesn't depend on loading of some specific class. It depends on the presence of JBossMetaData in any of the deployments (i.e. unless a blah.jar is deployed, there won't be any units containing JBossMetaData as an attachment).

                                   

                                  The profile service approach allows me to achieve this by 1) first moving myapp.jar out of the server/servername/deploy folder to the (unscanned) common/deploy folder 2) And then when a JBossMetaData is found (i.e. when blah.jar is deployed), allowing me to deploy the common/deploy/myapp.jar using a Profile service API.

                                  • 14. Re: AS bootime improvement - On demand deployment of EJB3 timerservice
                                    jaikiran pai Master

                                    Ales Justin wrote:

                                     


                                    but I think it's never good to jump into 1st-solution notion -- just for the sake "cuz it's working". ;-)

                                    At the moment, the PS is the only solution that I got working  :-) So I don't have options. I did try the jboss-deployment.xml and am willing to try it further, but based on what I have seen of the testcases and the implementation, I don't think there's a straightforward way of achieving this same thing with that approach. But again, I don't mind trying it.