10 Replies Latest reply on May 19, 2004 9:48 AM by f2racer

    HELP - JBoss 3.0.4/Oracle TopLink 9.0.3/JTS/Oracle (XADataSo

    Michael Huneycutt Newbie

       

      "mhuneycu" wrote:
      "mhuneycu" wrote:
      "mhuneycu" wrote:
      I have be looking through the posts and have not found much so
      I wanted to ask the question myself. My configuration is JDK1.4.1_01,
      Oracle 8.1.7, JBoss 3.0.4, Oracle TopLink 9.0.3 and I am using BMP for
      my EJBs. I am trying to configure TopLink with External JTS so the
      TopLink can participate in transactions, also I am use the Oracle XA
      DataSource because some persistence may span database connections.

      I copy the oracle-xa-service.xml from docs/examples/jca into server/all/deploy.
      I then modify the configuration for my database, I am using the oracle
      thin driver, but I did try the OCI8 driver. Also I am using the JDK 1.4
      Oracle 9.2 JDBC Drivers.

      I startup JBoss so far so good. But when I attempt to integrate with
      TopLink I get the following problems:

      1. Using the TopLink JNDIConnector I the following exception:

      ERROR [STDERR] LOCAL EXCEPTION STACK:
      EXCEPTION [TOPLINK-7060] (TopLink - 9.0.3 (Build 423)):
      oracle.toplink.exceptions.ValidationException
      EXCEPTION DESCRIPTION: Cannot acquire data source
      [XATestDS].
      INTERNAL EXCEPTION: javax.naming.InvalidNameException:
      Not a compound name: XATestDS

      The exception occurs wheter I specify initial context
      properties such as Provider URL, Context Factory and Package,
      or use the defaults from the container. I have tried every
      combination to no avail. Below is the code:

      DatabaseLogin login = project.getLogin();
      Hashtable jndiProperties = new Hashtable();
      jndiProperties.put(Context.PROVIDER_URL,
      "jnp://localhost:1099);
      jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY,
      "org.jnp.interfaces.NamingContextFactory");
      jndiProperties.put(Context.URL_PKG_PREFIXES,
      "org.jboss.naming:org.jnp.interfaces");
      Context context = InitialContext(jndiProperties);
      JNDIConnector connector = new JNDIConnector(context,
      "java:/XATestDS");
      login.setConnector(connector);
      ........
      serverSession.login(); <- This is when it occurs.

      However I did find that I was able to get past the Invalid
      Naming exception with this code. Basically I get the DataSource
      myself and then pass it to the JNDIConnector.

      DatabaseLogin login = project.getLogin();
      Hashtable jndiProperties = new Hashtable();
      jndiProperties.put(Context.PROVIDER_URL,
      "jnp://localhost:1099);
      jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY,
      "org.jnp.interfaces.NamingContextFactory");
      jndiProperties.put(Context.URL_PKG_PREFIXES,
      "org.jboss.naming:org.jnp.interfaces");
      Context context = InitialContext(jndiProperties);

      javax.sql.DataSource ds =
      (javax.sql.DataSource) JNDIHelper.lookup(
      "java:/XATestDS");
      JNDIConnector connector = new JNDIConnector(ds);
      login.setConnector(connector);
      ........
      serverSession.login(); No Exceptions.

      So I got past the naming exceptions. My guess is that form some reason
      TopLink if converting java:/XATestDS to XATestDS as other servers
      like WebLogic use this form of naming. But that is pure speculation,
      I am debugging to see if that is the case.

      So I get past this problem only to find that neither an Oracle
      XADataSource nor a regular Oracle DataSource will work.
      I get exceptions in both cases. I have read on the forums that
      the Oracle XA DataSource has problems, but I use it in WebLogic
      and WebSphere pretty regularly without issue, so I am not sure
      what the forum users means by buggy. With the following code
      and the Oracle XA DataSource:

      login.useExternalTransactionController();
      String jtsControllerClassName =
      oracle.toplink.jts.JTSExternalTransactionController
      Class jtsControllerClass =
      Thread.currentThread().getContextClassLoader().loadClass(jtsCon
      trollerClassName);
      ExternalTransactionController jtsController =
      (ExternalTransactionController) jtsControllerClass.newInstance();
      serverSession.setExternalTransactionController(jtsController);
      login.useExternalConnectionPooling();

      The class oracle.toplink.jts.JTSExternalTransactionController implements the
      registration of a synchronization object according to the JTS 1.0 standard. Since
      there is not JTSExternalTransactionController for JBoss supplied with TopLink as there
      is in WebLogic and WebSphere, I had to use the generic one provided. With the above code
      and an Oracle XA DataSource I get the following exception:

      at org.jboss.resource.connectionmanager.
      BaseConnectionManager2.allocateConnection
      (BaseConnectionManager2.java:534)
      at org.jboss.resource.connectionmanager.BaseConnectionManager2$
      ConnectionManagerProxy.
      allocateConnection(BaseConnectionManager2.java:814)
      at org.jboss.resource.adapter.jdbc.JDBCDataSource.getConnection(
      JDBCDataSource.java:131)
      at oracle.toplink.jndi.JNDIConnector.connect(Unknown Source)
      at oracle.toplink.sessions.DatabaseLogin.connect(Unknown Source)
      at oracle.toplink.internal.databaseaccess.DatabaseAccessor.connect(Unknown Source)
      at oracle.toplink.internal.databaseaccess.DatabaseAccessor.connect(Unknown Source)
      at oracle.toplink.threetier.ConnectionPool.buildConnection(Unknown Source)
      at oracle.toplink.threetier.ExternalConnectionPool.startUp(Unknown Source)
      at oracle.toplink.threetier.ServerSession.connect(Unknown Source)
      at oracle.toplink.publicinterface.DatabaseSession.login(Unknown Source)


      When I use the above code with a plain old Oracle DataSource I get a NullPointer
      exception pointing with a message stating an exception occured within JTS.
      I initiate a read first which works fine with the Oracle DataSource, but even
      reads fail with the Oracle XA DataSource. The stack trace is the following:

      at oracle.toplink.exceptions.ValidationException.jtsExceptionRai
      sed(Unknown Source)
      at oracle.toplink.jts.AbstractExternalTransactionController.getA
      ctiveUnitOfWork(Unknown Source)
      at oracle.toplink.publicinterface.Session.getActiveUnitOfWork(Un

      INTERNAL STACK TRACE:
      java.lang.NullPointerException
      at oracle.toplink.jts.JTSExternalTransactionController.getExtern
      alTransaction(Unknown Source)
      at oracle.toplink.jts.AbstractExternalTransactionController.getA
      ctiveUnitOfWork(Unknown Source)
      at oracle.toplink.publicinterface.Session.getActiveUnitOfWork(Un
      known Source)


      Any help in this situation would be greatly appreciated.

      Thanks

      Mike H. Sr.


        • 1. Re: HELP - JBoss 3.0.4/Oracle TopLink 9.0.3/JTS/Oracle (XADa
          Michael Huneycutt Newbie

           

          "mhuneycu" wrote:
          "mhuneycu" wrote:
          "mhuneycu" wrote:
          I made some progress today. My problem with Transactions was a simple one from a Oracle DataSource Standpoint. In WebLogic you do not have to set the TransactionManager using the TopLink JTSSynchronizationListener, but in JBoss you do. So the following code fixed the problem with exception using the Oracle DataSource:

          javax.transaction.TransactionManager tm =
          (TransactionManager)JNDIHelper.lookup("java:/TransactionManager");
          JTSSynchronizationListener.setTransactionManager(tm);


          I still cannot get Oracle XA DataSources to work. I am still getting the XAER_RMERR I mentioned in my first email. So if anyone has ideas on the Oracle XA DataSource that would be great thanks.

          Thanks

          Mike H. Sr.


          • 2. Re: HELP - JBoss 3.0.4/Oracle TopLink 9.0.3/JTS/Oracle (XADa
            David Jencks Master

             

            "davidjencks" wrote:
            "davidjencks" wrote:
            "davidjencks" wrote:
            I recommend you use jboss 3.2 with oracle-xa-ds.xml for oracle xa. For more info, look for posts by igor fedorenko, mostly in the jboss-dev mailing list.


            • 3. Re: HELP - JBoss 3.0.4/Oracle TopLink 9.0.3/JTS/Oracle (XADa
              Michael Huneycutt Newbie

               

              "mhuneycu" wrote:
              "mhuneycu" wrote:
              "mhuneycu" wrote:
              More info. I believe the InvalidNamingException not a CompoundName is a result of the fact that JNDIConnector does not return a CompoundName, but CompositeName. In looking at the code for JBoss 3.0.4 I noticed that JBoss only will handle the CompoundName, so that was my problem. Any suggestion on handling CompositeNames.

              The XA Problem I believe is related to the fact that initxa.sql has not been run in the Oracle Database.


              • 4. Re: HELP - JBoss 3.0.4/Oracle TopLink 9.0.3/JTS/Oracle (XADa
                Michael Huneycutt Newbie

                 

                "mhuneycu" wrote:
                "mhuneycu" wrote:
                "mhuneycu" wrote:
                Turns out that initxa.sql and initjvm.sql had not been run in the database I was trying to connect to. I confirmed this by connecting to a database that has JAVA_XA installed and the Oracle XA DataSource worked fine.

                Thanks

                Mike H. Sr.


                • 5. Re: HELP - JBoss 3.0.4/Oracle TopLink 9.0.3/JTS/Oracle (XADa
                  Michael Huneycutt Newbie

                   

                  "mhuneycu" wrote:
                  "mhuneycu" wrote:
                  "mhuneycu" wrote:
                  Quick HOW-TO

                  Setting up:
                  TopLink 9.0.3/Oracle (8.1.7,9.2,9.0)/Oracle XA
                  DataSource/JBoss 3.0.4/JDK1.4.1

                  1. Run initjvm.sql and initxa.sql in the oracle databases
                  that you will be connecting to with the Oracle XA
                  DataSources configured in JBoss. They can be
                  found in $ORACLE_HOME/javavm/install.

                  2. Get the latest Oracle JDBC Driver from
                  http://technet.oracle.com. The one I used is the
                  latest and is named ojdbc14.jar (not classes12.zip).

                  3. Copy $JBOSS_HOME/docs/examples/jca/
                  oracle-xa-service.xml to the appropriate
                  $JBOSS_HOME/server/[all|default|minimal]/deploy
                  and configure it for your database.

                  4. Modify $JBOSS_HOME/server/[all|default|minimal]/conf/
                  jboss-service.xml to include the attribute pad true
                  for the XidFactory. It should look as follows:
                  <mbean code="org.jboss.tm.XidFactory"
                  name="jboss:service=XidFactory">
                  <attribute name="Pad">true</attribute>
                  </mbean>

                  5. In your code to connect up to JNDI using the TopLink
                  JNDIConnector you will need to lookup and get the
                  DataSource yourself and pass it in the JNDIConnector
                  constructor. If you user the a jndi name string
                  the JNDIConnector will generate a CompositeName, which
                  results in a InvalidNamingException - not a
                  CompoundName. It appears that CompositeNames do not
                  work in JBoss 3.0.4. Here is some sample code:

                  //jndiProperties are the your properties
                  Context context = InitialContext(jndiProperties);
                  javax.sql.DataSource ds =
                  (javax.sql.DataSource) context.lookup(
                  "java:/XATestDS");
                  JNDIConnector connector = new JNDIConnector(ds);
                  login.setConnector(connector);

                  6. You will need to write code to lookup and get
                  the JBoss TransactionManager and then use the
                  TopLink JTSSynchronizationListener to set the
                  transaction manager so TopLink knows about it.
                  The following code is an example:
                  import javax.transaction.TransactionManager;
                  import oracle.toplink.jts.*;
                  ......
                  TransactionManager tm =
                  (TransactionManager)context.lookup(
                  transactionMgrJndiName);
                  JTSSynchronizationListener.
                  setTransactionManager(tm);

                  7. Finally you need to also set in TopLink the
                  the external JTS Controller class and let
                  TopLink know you want to use external
                  transactions. The generic TopLink class
                  JTSExternalTransactionController seems to
                  work so far. An example:

                  login.useExternalTransactionController();

                  String jtsControllerClassName =
                  "JTSExternalTransactionController";
                  Class jtsControllerClass =
                  Thread .currentThread()
                  .getContextClassLoader()
                  .loadClass(
                  jtsControllerClassName);
                  ExternalTransactionController jtsController =
                  (ExternalTransactionController)
                  jtsControllerClass
                  .newInstance();
                  serverSession.setExternalTransactionController(
                  jtsController);
                  login.useExternalConnectionPooling();


                  That does it. Hopefully this helps others who may
                  struggle as well.


                  • 6. Re: HELP - JBoss 3.0.4/Oracle TopLink 9.0.3/JTS/Oracle (XADa
                    jcgagne Newbie

                     

                    "jcgagne" wrote:
                    "jcgagne" wrote:
                    "jcgagne" wrote:
                    Hi mhuneycu,

                    Thanks for your quick how-to.

                    I see that you configure manually a login instance, that you probably got from the project or session. I'm using SessionManager.getSession() to obtain a session and I get the same error (Not a compound name...). Then it's too late to configure anything manually... So I have 2 questions :

                    - How do you get a reference to a login instance ?

                    - I suppose this code should be executed only once. So where do you put that code ?


                    We use JBoss 3.2.2, TopLink 9.0.3 (with configuration in "sessions.xml"), Oracle 9i


                    Thanks


                    Jean-Christian Gagne


                    • 7. Re: HELP - JBoss 3.0.4/Oracle TopLink 9.0.3/JTS/Oracle (XADa
                      fdutreuil Newbie

                       

                      "fdutreuil" wrote:
                      "fdutreuil" wrote:
                      "fdutreuil" wrote:
                      Hi,

                      I am experiencing the exact same problem while using the session.xml file.

                      I tried your sample code but cannot manage to obtain the DataSource. I have a ClassNotFoundException on javax.sql.DataSource. I believe this is because I had to load toplink.jar using the main unified class loader (I specify it in the JBOSS_CLASSPATH) and then toplink classes wil not see classes loaded from the server\default\lib directory.
                      I am getting stuck!

                      Anyone has a solution?
                      Thanks
                      Frederic


                      • 8. Re: HELP - JBoss 3.0.4/Oracle TopLink 9.0.3/JTS/Oracle (XADa
                        James Olsen Newbie

                         

                        "jim_b_o" wrote:
                        "jim_b_o" wrote:
                        "jim_b_o" wrote:
                        The CompoundName problem can be solved with a quick hack to oracle.toplink.jndi.JNDIConnector to change it to request a CompositeName. The original source code is in the TopLink source.jar.

                        This is the changed method:

                        public Connection connect(Properties properties) throws DatabaseException, ValidationException {
                         String user = properties.getProperty("user");
                         String password = properties.getProperty("password");
                        
                         DataSource dataSource = getDataSource();
                         if (dataSource == null) {
                         try {
                         /* START - Get around the CompositeName vs CompoundName problem with JBoss */
                         CompositeName name = (CompositeName)getName();
                        // if (name != null) {
                         dataSource = (DataSource)getContext().lookup(name.toString());
                        // }
                        // else {
                        // dataSource = (DataSource)getContext().lookup(name);
                        // }
                         /* END */
                        // dataSource = (DataSource) getContext().lookup(getName());
                         this.setDataSource(dataSource);
                         } catch (NamingException exception) {
                         throw ValidationException.cannotAcquireDataSource(getName(), exception);
                         }
                         }
                        
                         try {
                         // WebLogic connection pools do not require a user name and password.
                         // JDBCLogin usually initializes these values with an empty string.
                         // WebLogic data source does not support the getConnection() call with arguments
                         // it only supports the zero argument call. DM 26/07/2000
                         if((user == null)||(user.equalsIgnoreCase(""))){
                         return dataSource.getConnection();
                         } else {
                         return dataSource.getConnection(user, password);
                         }
                         } catch (SQLException exception) {
                         throw DatabaseException.sqlException(exception);
                         }
                        }


                        This means you don't have to do the lookup yourself and it will work fine with SessionManager.getSession().


                        • 9. Re: HELP - JBoss 3.0.4/Oracle TopLink 9.0.3/JTS/Oracle (XADa
                          weljo Newbie

                          Hi Mike,

                          Your how to has been very helpful however I am still struggling with my configurations. I am using toplink's BMP to persist my bean. On initial startup of Jboss, I am able to update my entity bean but subsequent updates only changes the entity bean but it does not commit to the database. The same goes on call to create, An object gets created but no database insert causing an exception to occur when ejbLoad gets called. If anyone has any inputs on what I may have overlooked your help would be greatly appreciated! Currently I am using jboss-3.2.3 with Toplink 9.0.4

                          Thanks,
                          weljo

                          Provided herein also are some suggested solutions on some issues that I encountered for future references.

                          1. I encountered this when I was using Toplink 9.0.3: java.lang.VerifyError: (class: oracle/toplink/tools/sessionconfiguration/XMLLoader, method: retreiveDOM signature: (Ljava/lang/ClassLoader;)Lorg/w3c/dom/Document;) Incompatible object argument for function call

                          Solution: Upgrade to Toplink 9.0.4. I want my toplink.jar to be shared by all deployment jars I couldn't use 9.0.3 because it has a lower xerces version than what Jboss 3.2.3 is using.

                          2. Where to put the JTSSynchronizationListener.setTransactionManager(...) call when using a sessions.xml file?

                          I created a SessionListener extending oracle.toplink.sessions.SessionEventAdapter, overriding the PreLogin (...) method. and then adding this tag to my sessions.xml file:
                          <event_listener_class>helpers.SessionListener</event_listener_class>

                          3. datasource not a compound name exception: Also placed the code within the PreLogin event.

                          • 10. Re: HELP - JBoss 3.0.4/Oracle TopLink 9.0.3/JTS/Oracle (XADa
                            f2racer Newbie

                             

                            "weljo" wrote:
                            Hi Mike,

                            3. datasource not a compound name exception: Also placed the code within the PreLogin event.


                            weljo, what code did you put in the PreLogin event to get this to work? Can you please post the source for this class?

                            Thanks!