8 Replies Latest reply on Jul 19, 2004 11:24 AM by jamesstrachan

    EJB's + Java Preferences

    cranphin

      Right, lessee if I can explain my problem :)

      - I'm building a server application including Message Driven Beans.
      - These Beans have settings such as url's to retrieve things from.
      - These settings need to be changable in runtime via a servlet/www interface.
      - I'd like to use a generic preferences/settings/configuration framework that handles loading/saving/persistance of configuration for me, and provides a global configuration object from which all my war's/ejb's can retrieve their configuration.

      Now I've chosen the Java Preferences API as this framework, cause it provides most of what I like, but this poses a problem as to changing settings in runtime.

      The problem is that java preferences give us the ability to use listeners to listen to configuration changes in runtime, which is what I want, but these listeners all run in a single thread.

      If I'm not mistaken you don't want to do things inside an EJB from a not ejb/container related thread, cause you might interfer with the ejb server, and als I've found out (the hard way;) that trying this also gives problems with classloaders, the classloader of the thread being different then those of the ejb's.

      I'd consider calling my ejb's via home/remote interfaces from the preferences thread to update their configuration, but this doesn't work for MDB's, they are only 'callable' via jms messages (right? )

      Does anyone have a good idea how to set this up, possibly using a different configuration framework, or can I just use the listeners , or can I call MDB's somehow from the thread ? Has someone done anything like this before ?

      Any help 'd be greatly appreciated :)

      If you know a forum/mailinglist on wich this post would be more on topic I'd also like to hear so I can post there :)

        • 1. Re: EJB's + Java Preferences
          cranphin

          Btw. JMX seems to be what I've after, and I've considered using it a lot, but with JMX I have some problems:
          - JMX does not ofer persistence by itself
          - Which means I'd have to write my own jmx persistence, which seems a task that'd be too great for this project.
          - Even if I would there's the problem of where/how to store the jmx configuration in a global place, java preferences solves this by two implementations, a windows one which uses the registry, and a unix one using /etc
          - My other problem with JMX is that only JBoss seems to really support it, I'd like to be able to use it on several servers.
          - I'd also like to be able to use it in standalone war's on tomcat, I don't think tomcat supports jmx either ?

          Mayby there's sollutions to all of this, I'd like to know if that's the case, JMX does look like what I'm after in a lot of ways

          Many thanks in advance! :)

          • 2. Re: EJB's + Java Preferences
            jamesstrachan

            I would suggest :-

            Use an Entity Bean to hold the configuration data. This will give you persistence. The Entity Bean can be either a singleton (see earlier discussion) or a set of Entity Beans with a key for each parameter.

            The Entity Bean can then be updated from a web client or Java client.

            The MDB's can update their data from the Entiity Bean either on every call or at a configurable timer interval.

            This doesn't give you an immediate response to a parameter change but will enable the application to reconfigure itself, and will be portable to different servers.

            James

            • 3. Re: EJB's + Java Preferences
              cranphin

              Thanks for the input :)

              Looks like an option, but it doesn't make me very happy, especially the fact that I have to wait (possibly long) for the configuration change to have any effect (I'd like it to be soon, cause thisway it's possible to notice configuration mistakes).

              you mention using a timer, how would this work ? you can't let a timer call a mdb in some way can you ?

              I've been looking into JMX+EJB, and have found only obsucre references, I'm figuringthis might have the same problem of not being able to call the MDB from an JMX MBean ?

              • 4. Re: EJB's + Java Preferences
                cranphin

                hmm, been pondering more ^_^
                I think I know better what I want now.

                let's say we want a MDB that puts received messages in a database, I use a 3'd party db binding so I'm not using entity beans.

                I want a jdbc connection for this, I want to share it between the MDB's, and I want it to be changeable in runtime to point to another DB.

                More generally said, I want resources that can be shared, and updated in realtime. (and updated right away when preferences change so we can get feedback on invalid configurations asap )

                Now sharing isn't too hard, we stick it in jndi as a DataSource and everyone's happy, if I make MDB's pick it up from jndi on each onMessage call then it can even change while the server is running, and the MDB's will speak to the new db on their next onMessage, that's all ok :) (except performance for jndi lookups might get a bit high, is that gonna be an issue ? )

                updating is harder.
                One problem is the context we're gonna be doing things (the thread,classloader, etc.).
                Currently I'm deploying everythign in an .ear, and some of the resources will need the jar's provided with the ear, which means they need to use the classloaders associated with this ear, if you have a single global thread like java preferences does to manage configuration this becomes a major problem because if you redeploy an application the thread will still be associated with the old classloaders (I've run into this problem ;) , and it can't reach the newly deployed jars.

                Alternativly I could use one thread per ear, destroying the thread when the ear gets un/redeployed. This would mean I can't use java preferences tho, what does jmx use threadwise anyways, a global thread aswell ?

                Ofcourse there's not really any functionality to start/stop threads with the deployment/undeployment of an ear, best guess would be to use a servlet's init/destroy methods for this (or ejb create/destroy, and keep count of instances)

                I feel I'm just running circles, there has to be a decent method to do these things in j2ee ;)

                • 5. Re: EJB's + Java Preferences
                  cranphin

                  Ok, here's an idea ;)

                  -I set up a java preferences listener from an InitServlet.
                  -The listenere gets destroyed along with the servlet, so it won't hang around after an undeploy.
                  -The listener will hava a constructor that looks up an ejb with lookup/home/narrow etc. , plain client ejb lookup.
                  -The listener calls the ejb as a plain ejb client whenever it's called itself.

                  That's part one, result is I've got a ejb in the proper context that gets called on java preferences updates :)

                  This ejb can then build things and put them in jndi for other mdb's/ejb's to use.

                  Is this a good idea, is this madness? ;)

                  Please let me know what you think :)

                  • 6. Re: EJB's + Java Preferences
                    jamesstrachan

                    Let's start with the timer, as that's simple.

                    You use an environment variable in the deployment descriptor to set a reload interval in seconds.

                    You then read that and covert it to milliseconds

                    
                    Integer temp = context.lookup( "java:comp/env/ReloadInterval");
                    reloadInterval = temp.getValue() *1000;
                    


                    You keep the time last loaded, and compare it with the current time when deciding to reload.

                    Date currentTime = new Date();
                    if ( (currentTime.getTime() - lastLoaded.getTime()) > reloadInterval ) {
                     reloadParameters();
                     lastLoaded = currentTime;
                     }
                    


                    That gives you a trigger that works, and can be adjusted to reload as frequently as you require.

                    I think that your idea of using a Listener to pick up a change off Properties would probably work, but I wonder whether it is a little complex.

                    The sequence

                    Man changes Properties which triggers Listener which runs EJB which sets JNDI parameters which are read by Session Bean

                    seems rather complex.

                    Over to you.



                    • 7. Re: EJB's + Java Preferences
                      cranphin

                       

                      "jamesstrachan" wrote:
                      Let's start with the timer, as that's simple.

                      ...

                      That gives you a trigger that works, and can be adjusted to reload as frequently as you require.

                      from where would you call this code tho ? If you do it from onMessage it might not be called for a long time if there's no messages :)
                      If I'd use a timer I'd do so to make sure things get updated at a gueranteed regular interval :)

                      "jamesstrachan" wrote:

                      I think that your idea of using a Listener to pick up a change off Properties would probably work, but I wonder whether it is a little complex.

                      The sequence

                      Man changes Properties which triggers Listener which runs EJB which sets JNDI parameters which are read by Session Bean

                      seems rather complex.


                      Good point :)
                      Question is if we can simplify it without giving up features tho ;)
                      Let's look at it step by step.

                      - Man changes properties which triggers listener could be removed by letting man directly call ejb, or by letting man directly put things in JNDI, the problem is that if we do that we remove java preferences which offers me persistence, and I want easy persistence of all settings :)

                      - Listener which runs EJB, well, I could make the listener put things directly in jndi, but since the listener runs in a global thread I'll have problems accessing my ear jars after say redeploying an ear. I call the ejb cause the ejb will be in the right context.

                      - EJB puts things (like datasource) in JNDI. Well, I can remove this step by making the things directly available as a EJB call (getDatasource), but isn't jndi a goodthing(tm) ? :)

                      Mind ya, I've had a nights sleep over it, and I've already decided that it's acceptable for most things to only check configuration on the next event (next onMessage call, next ejb invocation, next doPost invocation ). Possibly with a test button for the user to generate a test event :)

                      This simplifies this a lot, I can just pick up text string parameters from java preferences, without messing with listeners :)

                      The one exception is database connections tho, if I fetch the db string parameters (url, username, etc.) on each onMessage call and build a new connection things are gonna be real slow, I want to keep a connection around over several onMessage calls really.

                      So what to do here ?

                      Go back to my idea, have a preferences listener call an ejb that sets up a datasource(pool) in jndi ? :)

                      What I want is do the normally deploy time configuration of jdbc datasources (which then end up in jndi) in runtime via a servlet :)

                      Hmm, guess in this case I could just let the servlet create the datasource and put it in jndi, but again then I circumvent java preferences api, and have no persistence of my settings :)

                      Any ideas still greatly welcomed, thanks! :)


                      • 8. Re: EJB's + Java Preferences
                        jamesstrachan

                        The timer code is, as you have guessed, in the onMessage() method. The timeout is checked before doing work so that anything out of date can be refreshed.

                        You can then read directly from Preferences, a Properties file, or an Entity bean as I suggested. You may have problems reading a file as the J2EE specification says that you can't use classes from the java.io package. However, log4j writes OJK so you may be able to read a file.

                        I would suggest that you don't try to create JDBC connections in code. That won't be very performant, as you need to create a connection on each stateless session beabn call, andf the connections can't be pooled.

                        What you could do is to create two or more DataSource objects, each with a different JNDI name and connection pool.

                        You can then read the JNDI name of the Datasource to look up from your Preferences file.

                        An alternative, if you have control of the database schema, is to use a single database with a single Datasource and connection pool, and then to create separate logical schema in the Database by using a composite key, of which the first column identifies the schema :-

                        create table myData( varchar schemaId, varchar myKey, ..... );
                        


                        That will be the fastest solution, and will use less resources, but may not be practical in your environment.