1 2 Previous Next 20 Replies Latest reply on Feb 11, 2009 1:27 PM by mwringe

    Design of Portal Deployer

    mwringe

      Currently we have all the deployment happen within the portal sar and its tied into the internals of the server. With JBoss AS5 we want to remove this functionality from the sar and use the microcontainer deployment framework.

      This will require the addition of a new jboss-portal.deployer that will need to be placed in the /deployers directory of JBoss AS5 along with the jboss-portal.sar in the /deploy directory.

      Portlets and our other deployables require a runtime container and these containers have dependencies on other deployables (ie datasources, hibernate, transaction manager). Since these wont be started until after the deployer is running we can't have the containers within the deployer, they must remain in the portal sar.

      We could place the deployer inside the sar but this would create a race condition of when the deployer is started and when the deployable is deployed.

      Portal Deployer
      Will behave like most other deployers and how our current deployment works inside the sar. It will detemine when something of interest is being deployed, parse throught the xml files, gather data about the deployment, manipulate the deployable (adding tlds, the command servlet, ...) and pass the information to the runtime container in the portal sar.
      It will add a dependency to the deployable to make sure the runtime container is started before deploying it.

      Runtime Container
      This is just the various containers we have right now in the sar (instance, portlet, ...). Work is being done here to remove some of the elements to the deployer when required. Still havn't exactly figured out how best to interface the container to the deployer, working right now with mbeans but could also just interface with pojo's running in the microcontainer.

        • 1. Re: Design of Portal Deployer
          alesj

          A few comments to your current work and we'll pick it up from here.

          1) Deployer - Portal Container dependency

          (a) like you're doing it now by adding dependencies to deployment

          (b) making deployers optionally depend on the portal container
          e.g. @Inject(option=InjectOption.CALLBACK)
          Then if the portal container is not present do nothing.

          I like (a) better, as it holds all the dependencies at a single place.
          It's just the way your doing it - not cleaning up in undeploy + duplication code.

          See how I do it with DependenciesMetaDataDeployer or DeploymentDependencyDeployer,
          meaning you only need to provide Portal specific DependenciesMetaData or DeploymentDependencies impl.

          WRT "container - deployer" interface, I would go to a bean directly, via some proper interface.

          2) PortletTLDDeployer

          TLD usage in portal should be metadata driven,
          as is the rest of the metadata stuff that we do in JBossAS.
          Hence making it easier and cleaner to do this tld addition.

          I guess this approach would still work if we still always unpack .war deployment.
          Dunno if that's true with the VFS usage?

          3) PortletDeployer

          What's the point of this one?

          4) PortletDependencyDeployer

          As already mentioned.
          This one should just produce custom portal DependenciesMetaData or DeploymentDependencies impl.
          The way it's currently done is wrong, as ControllerContext is only present in top deployment unit.

          5) CommandServletDeployer

          Looks OK.
          This is how TLD stuff should look like. ;-)

          6) PortalPostWebDeployer

          What does this do?

          And using such hacks:

           public int getRelativeOrder()
           {
           //return the order just after the war deployer
           //note: should really be +1 but other portal deployer is getting in the way right now
           return warDeployerOrder + 2;
           }
          

          defeats the purpose of deployers chain/changeability/inputs/outputs/...

          7) LibDirectoryStructure

          What should this do?
          Similar to my legacy DirectoryStructure?

          8) ParsingDeployers

          OK, we just need tests so we know they work.

          Overall the stuff makes sense, it's the details that are missing.
          Perhaps some work on Portal Container side, to incorporate all the hooks.

          I mostly don't like the WarDeployer hacks, there should be a better way to do this.
          Perhaps a direct deployer-container communication?
          Then it means you need a clean spi split, placing it along with the deployer.
          But that should be fine for a container, since it will see those classes.


          • 2. Re: Design of Portal Deployer
            mwringe

             

            "alesj" wrote:
            A few comments to your current work and we'll pick it up from here.

            1) Deployer - Portal Container dependency

            (a) like you're doing it now by adding dependencies to deployment

            (b) making deployers optionally depend on the portal container
            e.g. @Inject(option=InjectOption.CALLBACK)
            Then if the portal container is not present do nothing.

            I like (a) better, as it holds all the dependencies at a single place.
            It's just the way your doing it - not cleaning up in undeploy + duplication code.


            I don't think (b) is even possible since we can't guarantee the order of when the container or deployment is deployed. We could do something like storing the deployment data in the deployer until the container starts or making the container directly contact the server to check what it has already deployed, but I don't like these ideas.


            See how I do it with DependenciesMetaDataDeployer or DeploymentDependencyDeployer,
            meaning you only need to provide Portal specific DependenciesMetaData or DeploymentDependencies impl.

            ok


            WRT "container - deployer" interface, I would go to a bean directly, via some proper interface.

            agreed


            2) PortletTLDDeployer

            TLD usage in portal should be metadata driven,
            as is the rest of the metadata stuff that we do in JBossAS.
            Hence making it easier and cleaner to do this tld addition.

            I guess this approach would still work if we still always unpack .war deployment.
            Dunno if that's true with the VFS usage?


            I really don't like how this is working right now, its a hack. It's something that needs to be fixed. I will need to read up on how tlds work to see if it can done in a different manner (perhaps referencing the tld location in metadata instead of imbedding it into the war).

            I took some time to look into the VFS, but couldn't figure out a way to make this work nicely. If anyone has any suggestions on how to add a file to a webapp during the deployment phase please speak up :)


            3) PortletDeployer

            What's the point of this one?

            No point right now, it was just initially done to check somethings while I am working on the deployer.


            4) PortletDependencyDeployer

            As already mentioned.
            This one should just produce custom portal DependenciesMetaData or DeploymentDependencies impl.
            The way it's currently done is wrong, as ControllerContext is only present in top deployment unit.

            Ah, good point, this will be fixed. But it does get a little tricky when the top deployment is the dependency of a child deployment, last I tried doing this it doesn' work as expected.


            5) CommandServletDeployer

            Looks OK.
            This is how TLD stuff should look like. ;-)

            This is how I want the TLD stuff to work, I just need to figure out how.


            6) PortalPostWebDeployer

            What does this do?

            This is a hack that will be removed once the portal is completely moved over to using the microcontainer deployment. The way portal used to get this type of information was changed too much in AS5 so this replaces the lost functionality. Its meant to be removed at some point.


            And using such hacks:
             public int getRelativeOrder()
             {
             //return the order just after the war deployer
             //note: should really be +1 but other portal deployer is getting in the way right now
             return warDeployerOrder + 2;
             }
            

            defeats the purpose of deployers chain/changeability/inputs/outputs/...


            For those deployers right now, knowing when the war deployer has finished deploying the app is required as we access that information from the war deployer in our own deployer.
            This is only being used in deployers that are meant to be removed or the TLD deployer which needs to be rewritten more cleanly anyways. So this issue will be gone.

            FYI, the manipulation of deployer order based on another deployer's order is also used in a few other deployers in AS5.


            7) LibDirectoryStructure

            What should this do?
            Similar to my legacy DirectoryStructure?

            Yes, except it doesn't look through the whole directory structure, only at directories called "lib" within the first level of the deployment. I don't believe its needed anymore, but it used to cause all sorts of problems without it when nested deployments (like sars) were used that would have worked fine on AS4.
            And I know that using jboss-structure.xml files would have worked, but it meant that we could no longer add or remove wars to the portal sar without rewriting that file each time.



            • 3. Re: Design of Portal Deployer
              alesj

               

              "mwringe" wrote:

              I really don't like how this is working right now, its a hack. It's something that needs to be fixed. I will need to read up on how tlds work to see if it can done in a different manner (perhaps referencing the tld location in metadata instead of embedding it into the war).

              I took some time to look into the VFS, but couldn't figure out a way to make this work nicely. If anyone has any suggestions on how to add a file to a webapp during the deployment phase please speak up :)

              I guess once you have more TLD info we can discuss further.
              Till then it would just be a guessing game. ;-)

              "mwringe" wrote:

              But it does get a little tricky when the top deployment is the dependency of a child deployment, last I tried doing this it doesn' work as expected.

              Tricky how?
              What about if you change the deployer hierarchy order?
              e.g. setParentFirst == false

              "mwringe" wrote:

              FYI, the manipulation of deployer order based on another deployer's order is also used in a few other deployers in AS5.

              Where? To kick some butt ... :-)

              "mwringe" wrote:

              And for the TLD deployer, I haven't figured out a clean way of implementing it yet.

              Np, we'll get there eventually. :-)

              The nicest idea, and you already mentioned it,
              would be to get the current TLD recognition/lookup based on additional metadata path.
              e.g. for JBP based deployments we would simply add default (container) metadata to each deployment,
              which would hold the common/default tld, ... files

              It just depends how much VFS/VDF exposure would be needed there.
              e.g.1. lookup is done via some interface, we only provide the VFS/VDF based wrapper/impl
              e.g.2. we completely replace the lookup with VFS/VDF
              e.g.3 non of the above as it's completely un-plugable :-( ... as were Facelets



              • 4. Re: Design of Portal Deployer
                mwringe

                 


                "mwringe" wrote:

                But it does get a little tricky when the top deployment is the dependency of a child deployment, last I tried doing this it doesn' work as expected.


                Tricky how?
                What about if you change the deployer hierarchy order?
                e.g. setParentFirst == false

                I must not understand this part enough. If I have a sar with a nested war, the war is sent to the tomcat deployer last no matter what parentfirst is set in the sar deployer.
                Note that I tested this deploying the sar after the server has been started. If the sar is in the deploy directory as the server starts its behaves differently.

                I have been trying it using the dependency deployer, but it doesn't work. If I specify I want the war to be deployed after the sar is done with the real stage, it fails since it can't find the sar dependency. It will work perfectly fine in the war is removed from the sar and is no longer nested.

                I would prefer to use the dependency mechanism rather than changing the portal from a sar into something else with its own custom deployer, but I can if necessary.

                "mwringe" wrote:


                FYI, the manipulation of deployer order based on another deployer's order is also used in a few other deployers in AS5.

                Where? To kick some butt ... :-)

                EARContentsDeployer and WebServiceDeployerPreJSE do at least. There could be others.

                • 5. Re: Design of Portal Deployer
                  alesj

                   

                  "mwringe" wrote:

                  I must not understand this part enough. If I have a sar with a nested war, the war is sent to the tomcat deployer last no matter what parentfirst is set in the sar deployer.
                  Note that I tested this deploying the sar after the server has been started. If the sar is in the deploy directory as the server starts its behaves differently.

                  I have been trying it using the dependency deployer, but it doesn't work. If I specify I want the war to be deployed after the sar is done with the real stage, it fails since it can't find the sar dependency. It will work perfectly fine in the war is removed from the sar and is no longer nested.

                  I would prefer to use the dependency mechanism rather than changing the portal from a sar into something else with its own custom deployer, but I can if necessary.

                  OK, the parentFirst == false was a guess/quick attemp :-), which doesn't work here.

                  What exactly are you trying to do?
                  As it sounds weird/wrong. :-)
                  e.g. .sar is only finished when its children (in this case .war) are finished
                  but your .war should wait for .sar to finish ... chicken and egg problem ;-)

                  Although in this case you might even get away with this,
                  as .war at the end is nothing more than a mbean --> ServiceDeployer.
                  And if you put proper depends on it, it would have the right order dependencies.
                  I'm just not sure how easy/hard it is to add dependencies to a .war's mbean representation.

                  What about if you deploy things separately - with proper jboss-dependency.xml in the top level?
                  The classloading should work, as long as the flat (non-scoped) model is used.
                  Or it's part of common/server lib - which I guess is right place so real jbp users can write against your custom jbp api.


                  • 6. Re: Design of Portal Deployer
                    mwringe

                     

                    "alesj" wrote:

                    What exactly are you trying to do?
                    As it sounds weird/wrong. :-)
                    e.g. .sar is only finished when its children (in this case .war) are finished
                    but your .war should wait for .sar to finish ... chicken and egg problem ;-)

                    The portal sar packages some wars within it, but these wars are going to have to be deployed after the container service is started in the sar. The old way of doing this was looping through everything that was deployed on the server when the service is started.
                    I don't actually need the whole sar to be finished, just as long as the container service is started.

                    "alesj" wrote:

                    Although in this case you might even get away with this,
                    as .war at the end is nothing more than a mbean --> ServiceDeployer.
                    And if you put proper depends on it, it would have the right order dependencies.
                    I'm just not sure how easy/hard it is to add dependencies to a .war's mbean representation.

                    Adding a jboss-dependency.xml file to the WEB-INF folder does properly add dependencies to the war, so I don't think I need to do anything else there.
                    It just doesn't seem to work nicely when inside a sar (as you have mentioned above).

                    "alesj" wrote:

                    What about if you deploy things separately - with proper jboss-dependency.xml in the top level?
                    The classloading should work, as long as the flat (non-scoped) model is used.
                    Or it's part of common/server lib - which I guess is right place so real jbp users can write against your custom jbp api.

                    Things work properly is deployed separetely, it just means there will be more things to deploy on the server than just a single sar.


                    • 7. Re: Design of Portal Deployer
                      mwringe

                       

                      "mwringe" wrote:

                      Things work properly is deployed separetely, it just means there will be more things to deploy on the server than just a single sar.

                      Ok, this is rather easy to get around, I can just deploy a directory that contains the sar and wars and with the proper dependency setup it will work fine and it will only be a single artifact to deploy.

                      • 8. Re: Design of Portal Deployer
                        alesj

                         

                        "mwringe" wrote:
                        "mwringe" wrote:

                        Things work properly is deployed separetely, it just means there will be more things to deploy on the server than just a single sar.

                        Ok, this is rather easy to get around, I can just deploy a directory that contains the sar and wars and with the proper dependency setup it will work fine and it will only be a single artifact to deploy.

                        Exactly. ;-)
                        Just make sure you don't have any '.' in the directory name.

                        btw: any more info on tld?

                        • 9. Re: Design of Portal Deployer
                          mwringe

                           

                          "alesj" wrote:
                          btw: any more info on tld?

                          TLD is still a problem.

                          It has to reside within the war, so we can't just make it reference an outside location for it.

                          I have looked into the VFS deployments more, and it doesn't seem like it will help. The VFS will allow adding files to the classpath of the deployment, but adding a tld to the classpath doesn't help.
                          Ideally I would be able to do something like unit.addResouce(virtualFile, pathInUnitRoot) just like how I can do unit.addClasspath(virtualFile), and then the WarDeployer would know what to do with it.

                          I might be able to do something like add a tomcat valve to intercept the tld call, but this is starting to become a lot of effort just to add a single file to the deployment.

                          • 10. Re: Design of Portal Deployer
                            alesj

                             

                            "mwringe" wrote:

                            I have looked into the VFS deployments more, and it doesn't seem like it will help. The VFS will allow adding files to the classpath of the deployment, but adding a tld to the classpath doesn't help.
                            Ideally I would be able to do something like unit.addResouce(virtualFile, pathInUnitRoot) just like how I can do unit.addClasspath(virtualFile), and then the WarDeployer would know what to do with it.

                            I've added methods that allow you to add/remove metadata locations:
                            - http://www.jboss.com/index.html?module=bb&op=viewtopic&t=149197

                            The deployers snapshot should be in the repo in a few hours.
                            You can then test if this helps you.

                            • 11. Re: Design of Portal Deployer
                              mwringe

                               

                              "alesj" wrote:

                              I've added methods that allow you to add/remove metadata locations:
                              - http://www.jboss.com/index.html?module=bb&op=viewtopic&t=149197

                              The deployers snapshot should be in the repo in a few hours.
                              You can then test if this helps you.


                              unless I am missing something, this is never going to work with the way we are trying to do this.

                              JBoss Web only uses a small subject of all available 'metadata' files with the deployer, most things are directly handled internally. The deployer doesn't have anything to do with individual html files, jsp files, images, or tlds. I don't see how we can make it work in these situations without rewritting JBoss Web to be more dependent on the microcontainer.

                              FYI, I did try it with adding the metadata file to the deployment, it just that the deployment doesn't handle tld files, it's looked up through the web app's context which doesn't use the metadata location(see org.apache.jasper.compiler.TagLibraryInfoImpl.generateTLDLocation).

                              So back to the original TLD deployer. I don't really like how we have to access the tomcat deployment directory and move files around that way, but I don't see how we can modify the war in any other way.

                              I am missing some relevant information that would make using the metadata location make sense?

                              • 12. Re: Design of Portal Deployer
                                alesj

                                 

                                "mwringe" wrote:
                                without rewritting JBoss Web to be more dependent on the microcontainer.

                                FYI, I did try it with adding the metadata file to the deployment, it just that the deployment doesn't handle tld files, it's looked up through the web app's context which doesn't use the metadata location(see org.apache.jasper.compiler.TagLibraryInfoImpl.generateTLDLocation).

                                I'll have a look at what can be done.
                                e.g. to make this TLD stuff run off VFSDeploymentUnit

                                • 13. Re: Design of Portal Deployer
                                  mwringe

                                  ok

                                  FYI it also checks the file path so that its located within the war, so it wont work if you try and reference it from another location on the file system.

                                  • 14. Re: Design of Portal Deployer
                                    mwringe

                                    OK, so I have done some more work on this. There are still some remaining issues where we have to use the tomcat deployer to get a reference to a webapplication running in the server, but there is not much we can do about that right now.

                                    As far as doing things the "proper" way with deployers, which is the better approach:

                                    1) The current approach is that we have all the jars that used to exist in the portlet container sar moved over to the deployer. The sar is then used to just to start the portlet container at run time (it becomes basically just a jboss-service.xml file).
                                    The deployer uses the microcontainer kernel to get a reference to the portlet containers runtime objects and uses those to directly inject the information into the running server.

                                    2) more distinct separation between the deployer and the portlet container.
                                    The deployer would only contain jars for the metadata, the deployers themselves and for interface classes that will be used to pass data between the deployer and the portlet container.
                                    In this case the deployer would parse the xml files into metadata, then convert the metadata into the proper classes for the common interface, then have the portal container have new classes to interface with the deployer to convert the common interface into the classes that it requires.

                                    Thoughts?

                                    1 2 Previous Next