5 Replies Latest reply on Dec 23, 2002 11:49 PM by Bruce

    JDBCTemporalCommandFactory

    Ryan Ramage Newbie

      Dain, I know you browse in here quite often, so I have a question to ask to you. I am trying to modify the functionality of the Persistance manager. I am going to add bean versioning functionality. What this entails is creating a second table for every bean, called bean_shadow. This will have all the fields of the original bean plus two timestamp fields to give the bean a transaction start and end time. Any insert, update, or delete will write into this table and the original table so as not to affect the application.

      Anyway, I have been trying to keep it *clean* so I dont have to modify the JBoss source yet. All I want to do is extendend a few of the JDBCCommand classes so that it adds the extra sql needed, Create a jar, and then in standardjboss.xml set the persistence-manager to my new org.jboss.ejb.plugins.cmp.jdbc.JDBCTemporalStoreManager class. This way it can be turned on or off.



      The easiest way I see this is to extend the JDBCTemporalCommandFactory class. The only problem is this class is hard coded when it is created in the JDBCStoreManager not following factory pattern.

      commandFactory = new JDBCCommandFactory(this);

      Is there a way around this that you can see? Any suggestions?


      I tried to extend JDBCStoreManager, changing only the above code to :
      ommandFactory = new JDBCTemporalCommandFactory(this);

      but when the bean is deployed, I get:


      2002-12-17 23:52:26,750 INFO [org.jboss.ejb.EjbModule] Creating
      2002-12-17 23:52:26,800 INFO [org.jboss.ejb.EjbModule] Deploying Address
      2002-12-17 23:52:27,020 INFO [org.jboss.ejb.EjbModule] Created
      2002-12-17 23:52:27,020 INFO [org.jboss.ejb.EjbModule] Starting
      2002-12-17 23:52:27,240 WARN [org.jboss.system.ServiceController] Problem starting service jboss.j2ee:jndiName=ejb/realManagement/Address,service=EJB
      org.jboss.deployment.DeploymentException: Configuration found in jbosscmp-jdbc.xml for entity Address but bean is not a jbosscmp-jdbc-managed cmp entity in ejb-jar.xml
      at org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCApplicationMetaData.(JDBCApplicationMetaData.java:277)
      at org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCXmlFileLoader.load(JDBCXmlFileLoader.java:75)
      at org.jboss.ejb.plugins.cmp.jdbc.JDBCTemporalStoreManager.loadJDBCEntityMetaData(JDBCTemporalStoreManager.java:687)
      at org.jboss.ejb.plugins.cmp.jdbc.JDBCTemporalStoreManager.initStoreManager(JDBCTemporalStoreManager.java:399)
      at org.jboss.ejb.plugins.cmp.jdbc.JDBCTemporalStoreManager.start(JDBCTemporalStoreManager.java:349)
      at org.jboss.ejb.plugins.CMPPersistenceManager.start(CMPPersistenceManager.java:198)
      at org.jboss.ejb.EntityContainer.start(EntityContainer.java:376)
      at org.jboss.ejb.Container.invoke(Container.java:756)
      at org.jboss.ejb.EntityContainer.invoke(EntityContainer.java:1058)
      at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:517)
      at org.jboss.system.ServiceController$ServiceProxy.invoke(ServiceController.java:978)
      at $Proxy5.start(Unknown Source)
      at org.jboss.system.ServiceController.start(ServiceController.java:398)
      at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:324)
      at org.jboss.mx.capability.ReflectedMBeanDispatcher.invoke(ReflectedMBeanDispatcher.java:284)
      at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:517)
      at org.jboss.util.jmx.MBeanProxy.invoke(MBeanProxy.java:174)
      at $Proxy20.start(Unknown Source)
      at org.jboss.ejb.EjbModule.startService(EjbModule.java:430)
      at org.jboss.system.ServiceMBeanSupport.start(ServiceMBeanSupport.java:165)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:324)
      at org.jboss.mx.capability.ReflectedMBeanDispatcher.invoke(ReflectedMBeanDispatcher.java:284)
      at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:517)
      at org.jboss.system.ServiceController$ServiceProxy.invoke(ServiceController.java:978)
      at $Proxy5.start(Unknown Source)
      at org.jboss.system.ServiceController.start(ServiceController.java:398)
      at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:324)
      at org.jboss.mx.capability.ReflectedMBeanDispatcher.invoke(ReflectedMBeanDispatcher.java:284)
      at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:517)
      at org.jboss.util.jmx.MBeanProxy.invoke(MBeanProxy.java:174)
      at $Proxy9.start(Unknown Source)
      at org.jboss.ejb.EJBDeployer.start(EJBDeployer.java:395)
      at org.jboss.deployment.MainDeployer.start(MainDeployer.java:807)
      at org.jboss.deployment.MainDeployer.deploy(MainDeployer.java:621)
      at org.jboss.deployment.MainDeployer.deploy(MainDeployer.java:585)
      at sun.reflect.GeneratedMethodAccessor9.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:324)
      at org.jboss.mx.capability.ReflectedMBeanDispatcher.invoke(ReflectedMBeanDispatcher.java:284)
      at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:517)
      at org.jboss.util.jmx.MBeanProxy.invoke(MBeanProxy.java:174)
      at $Proxy4.deploy(Unknown Source)
      at org.jboss.deployment.scanner.URLDeploymentScanner.deploy(URLDeploymentScanner.java:435)
      at org.jboss.deployment.scanner.URLDeploymentScanner.scanDirectory(URLDeploymentScanner.java:656)
      at org.jboss.deployment.scanner.URLDeploymentScanner.scan(URLDeploymentScanner.java:507)
      at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.doScan(AbstractDeploymentScanner.java:212)
      at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.loop(AbstractDeploymentScanner.java:225)
      at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.run(AbstractDeploymentScanner.java:202)
      2002-12-17 23:52:27,350 INFO [org.jboss.ejb.EjbModule] Started
      2002-12-17 23:52:27,350 INFO [org.jboss.deployment.MainDeployer] Deployed package: file:/C:/devel/jboss_Package/jboss-3.0.4_tomcat-4.0.6/server/default/deploy/realManagement-ejb.jar
      2002-12-17 23:52:27,350 ERROR [org.jboss.deployment.scanner.URLDeploymentScanner] MBeanException: Exception in MBean operation 'checkIncompleteDeployments()'
      Cause: Incomplete Deployment listing:
      Packages waiting for a deployer:

      Incompletely deployed packages:

      MBeans waiting for classes:

      MBeans waiting for other MBeans:
      [ObjectName: jboss.j2ee:jndiName=ejb/realManagement/Address,service=EJB
      state: FAILED
      I Depend On:
      Depends On Me: org.jboss.deployment.DeploymentException: Configuration found in jbosscmp-jdbc.xml for entity Address but bean is not a jbosscmp-jdbc-managed cmp entity in ejb-jar.xml]




        • 1. Re: JDBCCommandFactory
          Ryan Ramage Newbie

          Well, I found the issue. In the class JDBCApplicationMetaData there is code that reads:

          public final static String JDBC_PM =
          "org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager";

          and a conditional section:

          if(entity.isCMP() && entity.getContainerConfiguration().getPersistenceManager().equals(JDBC_PM))

          since in my standardjboss.xml file the persistance manager is org.jboss.ejb.plugins.cmp.jdbc.JDBCTemporalStoreManager and the JDBC_PM string in hard coded in, this section never executes.

          Now I cant extend JDBCApplicationMetaData because it is a final class. From this point I have two options.
          1) Change the jboss source code so the JDBCCommand classes can be swapped with new ones using the abstract factory pattern. Have an optional element in standardjboss.xml that is sets which JDBCCommandFactory is to be used.

          2) keep it seperate from the src code and just copy all of the package org.jboss.ejb.plugins.cmp.jdbc to a new package, rename it and change all the refrences, and all the few lines of SQL code that are needed.

          From the other post I have seen, it seems like it would be nice to have the first option so that we can still use all of the persistance engine already written and then we can swap in the JDBC commands that we need.

          What do others think? Any suggestions?




          • 2. Re: JDBCCommandFactory
            Alexey Loubyansky Master

            Sorry, I don't get the purpose of your effort.
            Are you trying to implement optimistic locking? It's already in HEAD. It has among other options version columns (counter, timestamp and id generated by KeyGenerator).

            alex

            • 3. Re: JDBCTemporalCommandFactory
              Ryan Ramage Newbie

              Sorry for not being clear. I try to make sense sometimes. =)

              I am trying to implement bean versioning. For each bean there is a table that keeps track of all the changes made to the bean. I call it a shadow table. This table has all the same fields that the bean has, plus a transaction_valid_start timestamp, a transaction_valid_end timestamp, and a String of the principle who modified/created/deleted the bean.

              This allows for many things, including:
              1) time based queries. These show all the changes that have been made to the bean over a period of time. For example a Person bean might have a 1-N relationship with an Address Bean so as to keep track of changing address over time. With bean versioning, a 1-1 relationship could be used, and then to see all the history of addresses you could do time based query to the shadow table. Picture it like a 3 dimensional table with the z axis keeping all the temporal changes. I try to make sense sometimes. =)

              2) Security. You can see who made changes and when in a database independant way.

              3) Data back-up. Archive all the history of the database from the shadow table.

              And much much more....

              Make sense? So no, it is not optimistic locking. I am not sure if it is similar to the timestamps you talked about.

              • 4. Re: JDBCTemporalCommandFactory
                Alexey Loubyansky Master

                I would implement it as a separate deployable/pluggable service rather than the core functionality. Consider writting custom interceptor to track transactions and invocations.
                I wouldn't redesign CMP engine for this.

                alex

                • 5. Re: JDBCTemporalCommandFactory
                  Bruce Newbie

                  I agree. Why not build this as an interceptor? This functionality should not be hard-coded into the persistence framework. As an interceptor it could be deployed/undeployed as a separate service.

                  Bruce