5 Replies Latest reply on Apr 9, 2007 1:03 PM by Erik Poelmans

    [long read] Info/help needed on extending EJB3 container

    Erik Poelmans Newbie

      I'm a thesis student and have been given the assignment over the past few months to extend or write a J2EE container to support real time adaptation (changing an implementation of a bean with another one without the clients knowing) on the basis of context information. Before this assignment I had good experience with regular Java but none with J2EE.

      After reading up on context management and all kinds of runtime adaptation, I ended up choosing JBoss to do this 'little' college work since it looked to be better documented than glassfish, and because real world developers prefer it.

      I've been looking at source code for over a month and trying to write some as well. I first started with the regular EJB container and then switched over to the EJB3 one to try and keep things simple. But frankly, I'm not feeling like I'm making any progress, the amount of code I wrote at the moment is laughable. The thing is that I'm being drowned in all the code and it's very hard to make out what is for what, how it gets used etc. The documentations provided on the site are all very basic and do not tell anything on how the containers are layered, how an invocation travels through the code for every kind of bean (where does it start at the server side, what invocation object, interceptors, the pools, all those context classes, to the beaninstance?) or something like that. Starting a container from scratch to plug into Jboss doesn't seem like a viable idea either.

      My work plan would read something like this: At this point I would just like to extend the existing EJB3 container so that it supports multiple bean implementations, but only with the same configuration (so nothing else changes..), and have the possibility to add/remove implementations at run time... Does this sound at all doable in a relatively short time without breaking any interoperability? To do this I thought about putting a class between ejbcontainer and sessioncontainer with necessary overrides and extra methods for the extra functionality to achieve this, but am kinda in the dark on what this exactly entails (what do i need multiple instances of and can I change them safely..).

      The next step would then be to route the invocations through a dispatcher which I control from my own developped classes. The dispatchers get held in the extended container and if i ask one to change implementation, it asks a specific implementation to the container and uses that one for every invocation.

      To achieve this step I think I need to change the proxies that are sent to the client to contain a reference to the dispatcher instead of whatever it refers to now (seems different for stateful/stateless/...). From what I understood up till now, I will need to have different dispatchers and adapt all the different end-containers for each kind of bean (or just the end containerinterceptor?).

      Any thoughts on all this and some light or links on how invocations progress through the app server are greatly appreciated.

      As this is work for a thesis, I do not know if any of this is appreciated, since it doesn't involve fixing bugs, completing code, making jboss better for the 'general public'. Any code I write is of course strictly meant for research.

      Sorry if this wasn't all that coherent. Hope this is posted in the right subforum.

        • 1. Re: [long read] Info/help needed on extending EJB3 container
          Bill Burke Master

          EJB3 is built on JBoss AOP framework. ALl the facilities you would need to do this are built in already.

          You need:

          1. A service that holds your routing information and matches it up to an EJBContainer. EJB3 containers are all registered in org.jboss.ejb3.Ejb3Registry

          2. a Server-side aspect that intercepts the invocation and reroutes the invocation. You can add this aspect to all EJB containers by adding your aspect to the ejb3-interceptors-aop.xml file. Server side AOP bindings are defined in various aspect domains in this file.

          3. Use org.jboss.aop.metadata.ThreadMetaData class to associate contextual data with with the calling Thread.

          4. Add the MergeMetaDataInterceptor to the client interceptor chains defined in ejb3-interceptors-aop.xml. This interceptor must be defined before InvokeRemoteInterceptor in the interceptor stack definition. What this interceptor will allow you to do is to pass contextual data you assigned with the ThreadMetaData class over the wire to the server.

          5. The Server-side aspect would do Invocation.getMetaData(key, value) to obtain any contextual metadata you assigned through ThreadMetaData.

          Hope this gives you some hints.


          • 2. Re: [long read] Info/help needed on extending EJB3 container
            Erik Poelmans Newbie

            Took me a while to read up on aspect oriented programming and the aop framework, it was the first time I was confronted with it. Went through the following links to learn (most of which are yours..). Am aware that the first link is outdated when it comes to syntax etc.
            I have a pretty good grasp of it now, as much as you can get without doing some actual development with it anyway.

            Does all this also mean that I have to throw out the model which I worked out thus far, or only that it is implemented in a different way? I'll lay out a bit more thoroughly how I thought about solving the problem before, as I do not clearly see yet how my old idea maps on the service+aspect, but am getting there. Most of it is repetition from before, but there are a few specific problems highlighted that I see with the change.

            The two basic parts of the model I had in mind is extending the container (by the in-between class) to hold and manage multiple implementations of one bean with a certain configuration, and routing the invocation through a dispatcher, which fires the invocation to the beanimplementation it is told to. The selecting of implementation is done by some classes/service instantiated per application, based on external context information for each client and a configuration file that maps context situations to application profiles, so it selects and changes the current implementation per client for each application. There exists one dispatcher for every client, and the client holds a reference to that dispatcher in its proxy, so no lookup of the configuration for that particular client needs to be done serverside (performance). Dispatchers would also be held and created for every client in the container. The deployment plan etc. would need to change of course, but that's a worry for after I get the plumbing of the container done, right now loading a file that describes the configurations and giving the other implementations of the bean is entirely meant to be done by new classes. This all means that stateless interactions aren't really stateless anymore and changing of implementations can be done in a 'safe' way, if no invocations/transactions are running.

            When I look at what you wrote, I see the aspect taking over the role of the dispatcher, and using a service to keep all the configurations for each client over all the applications?
            Since I'm not a seasoned JBOSS developper, I assume what you mean with a service is what is described in chapter 5 of the document:
            How I see it now, this represents a scaling problem in the real world, where you have a single instance/service keep all the routing information for every client of each reconfigurable application on your server. Maybe the service could make some routing-management instances per application, but in the end the aspect still needs to do a thorough lookup (->service->per application manager->clientID->which implementation for this bean) for each invocation, whereas the dispatcher would just have it's pool/cachereference changed and that's the end of it, invocations go to the right implementation. This is assuming I read your hints right, or did I miss anything? Maybe there's an easy solution.
            The next question is, where do I keep the other implementations if not in a specific container extension, or is there a way to expand it? I would like to have the beancontext/cache/pooling abilities if possible... But I can't really deploy every implementation to a different container since the original thesis proposition is supporting adaptation through a container extension, hence the reason why we proposed the requirement of having each beanimplementation have the same containerconfiguration.
            Also, org.jboss.ejb3.stateless.StatelessInstanceInterceptor (the current 'implementation selector' -as an example) will probably have to be removed from the interceptor stack and replaced by the new server aspect I assume. There isn't any specific order to the interceptors that will make or break the container currently in the ejb3-..-aop.xml file? I'm asking because, if I change the target of an invocation, will the next interceptor still be run... And uhm lastly, where do I 'deploy' any new server-side aspect :)

            Are there any docs on developing a service? Using all the links I found on google regarding developing on JBOSS EJB3 container, none of the eclipse configurations I found recognised the @service tag to start with.

            And a stupid one: assuming I have read up on everything I need to and have the right development tools/config, developing an aspect and service to do this and changing the necessary configurations, how much development time would I (only me) be looking at approximatly? A matter of days, weeks or months? :)

            Thanks for reading this far, just writing it down brought a lot of insights already. I'm hoping to make significant headway soon :D

            • 3. Re: [long read] Info/help needed on extending EJB3 container
              Erik Poelmans Newbie

              I've been thinking a bit more on the subject and I think I'm almost there. To add metadata at client side I would also need a new client-side aspect right? It isn't mentioned in the original response, only that ThreadMetaData can be used, but I don't see any way to use it other than with a new client-side aspect, in addition to the mergemetadata interceptor.

              Looking at the code of InvokeRemoteInterceptor it seems there isn't really a problem in sending over references of objects from client to server and vice versa, through the use of metadata (I think if I use the AS_IS type only the unaltered reference gets sent which is sufficient, as the client's only job is to safeguard, not use it). So my new service could create a dispatcher on the server on the first invocation, which holds which target we need for the invocation. The server-side aspect can pass its reference to the client through the invocationresponse. The client can then include that reference with every invocation, the serveraspect asks that reference for the target and changes it in the invocation..

              If this is all correct (confirmation?), it leaves me with this:
              1) Where do i deploy my new developed aspects?
              2) Is there an eclipse configuration that recognises @service etc?
              3) Is there an alternative to deploying each beanimplementation in a seperate container?

              Thanks for listening

              • 4. Re: [long read] Info/help needed on extending EJB3 container
                Bill Burke Master

                Young grasshopper, you seem to be on the right path...Dig further. Enlightenment must come from within.

                • 5. Re: [long read] Info/help needed on extending EJB3 container
                  Erik Poelmans Newbie

                  Maybe not the right way to go about this (bumping up this old thread) but I've got things working -- mostly. There's one big thing that still nags me:

                  Is it possible to send unchanged references (just references, not the associated objects) back and forth using metadata? Or an alternative that's close? I've been trying a few things to make it work but couldn't really. Most of the time it gives a marshalling error (the dispatcher is not serialisable). When I tried doing the rmi stuff so it sends a stub I got another obscure error. Besides, sending back a marshalled stub is not all that useful probably.

                  I would think it's possible since that's basically what the proxy-invoker does to select which container to invoke, right?

                  thx :)