[jboss-svn-commits] JBL Code SVN: r35930 - in labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US: extras and 1 other directory.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Wed Nov 10 01:52:56 EST 2010
Author: misty at redhat.com
Date: 2010-11-10 01:52:56 -0500 (Wed, 10 Nov 2010)
New Revision: 35930
Added:
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/class.forName.java
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/creating_and_using_a_connection.java
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/failure_recovery_example.java
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/instantiating_dynamic_class.java
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/instantiating_transactional_driver.java
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/jdbc_example.java
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/jrmp_invoker_proxy.java
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/passing_connection_url_to_jdbc.java
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/registering_transactionaldriver_using_jdbc_driver_manager.java
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/storing_datasource_in_jndi.java
Modified:
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/Configuring_JBossTA.xml
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/Examples.xml
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/JDBC.xml
labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/Using_JBossTA_In_Application_Servers.xml
Log:
Finished initial conversion of JTA Development Guide
Modified: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/Configuring_JBossTA.xml
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/Configuring_JBossTA.xml 2010-11-10 04:42:27 UTC (rev 35929)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/Configuring_JBossTA.xml 2010-11-10 06:52:56 UTC (rev 35930)
@@ -4,6 +4,39 @@
%BOOK_ENTITIES;
]>
<chapter>
- <title></title>
+ <title>Configuring JBossJTA</title>
+
+ <section>
+ <title>Configuration loading mechanism</title>
+ <para>
+ In general, configuration is managed the same as ArjunaCore. Refer to the <citetitle>ArjunaCore Development
+ Guide</citetitle> for more information.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Configuration options</title>
+ <para>
+ The canonical reference for configuration options is the javadoc of the various EnvironmentBean classes. For
+ ArjunaJTA, these classes are the ones provided by ArjunaCore, as well as:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ com.arjuna.ats.jdbc.common.JDBCEnvironmentBean.java
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ com.arjuna.ats.jta.common.JTAEnvironmentBean.java
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Modules built on ArjunaCore and ArjunaJTA may add additional beans. Please refer to the relevant Development
+ Guides for details of these.
+ </para>
+ </section>
</chapter>
Modified: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/Examples.xml
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/Examples.xml 2010-11-10 04:42:27 UTC (rev 35929)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/Examples.xml 2010-11-10 06:52:56 UTC (rev 35930)
@@ -4,6 +4,58 @@
%BOOK_ENTITIES;
]>
<chapter>
- <title></title>
+ <title>Examples</title>
+
+ <section>
+ <title>JDBC example</title>
+
+ <example>
+ <title>JDBC example</title>
+ <para>
+ This simplified example assumes that you are using the transactional JDBC driver provided with JBossTS. For
+ details about how to configure and use this driver see the previous Chapter.<!-- Link? -->
+ </para>
+ <programlisting language="Java" role="JAVA"><xi:include href="extras/jdbc_example.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ </example>
+ </section>
+
+ <section>
+ <title>Failure recovery example with BasicXARecovery</title>
+ <para>
+ This class implements the <interfacename>XAResourceRecovery</interfacename> interface for XAResources. The parameter supplied in <varname>setParameters</varname>
+ can contain arbitrary information necessary to initialize the class once created. In this example, it contains the
+ name of the property file in which the database connection information is specified, as well as the number of
+ connections that this file contains information on. Each item is separated by a semicolon.
+ </para>
+ <para>
+ This is only a small example of the sorts of things an XAResourceRecovery implementer could do. This implementation
+ uses a property file that is assumed to contain sufficient information to recreate connections used during the
+ normal run of an application so that recovery can be performed on them. Typically, usernames and passwords should
+ never be presented in raw text on a production system.
+ </para>
+ <example>
+ <title>Database parameter format for the properties file</title>
+ <screen>
+ DB_x_DatabaseURL=
+ DB_x_DatabaseUser=
+ DB_x_DatabasePassword=
+ DB_x_DatabaseDynamicClass=
+ </screen>
+ <para>
+ <replaceable>x</replaceable> is the number of the connection information.
+ </para>
+ </example>
+ <para>
+ Some error-handling code is missing from this example, to make it more readable.
+ </para>
+ <example>
+ <title>Failure recovery example with BasicXARecovery</title>
+ <programlisting language="Java" role="JAVA"><xi:include href="extras/failure_recovery_example.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ <para>
+ You can use the class <classname>com.arjuna.ats.internal.jdbc.recovery.JDBC2RecoveryConnection</classname> to
+ create a new connection to the database using the same parameters used to create the initial connection.
+ </para>
+ </example>
+ </section>
</chapter>
Modified: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/JDBC.xml
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/JDBC.xml 2010-11-10 04:42:27 UTC (rev 35929)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/JDBC.xml 2010-11-10 06:52:56 UTC (rev 35930)
@@ -4,6 +4,307 @@
%BOOK_ENTITIES;
]>
<chapter>
- <title></title>
+ <title>JDBC and Transactions</title>
+
+ <section>
+ <title>Using the transactional JDBC driver</title>
+ <para>
+ JBossJTA supports construction of both local and distributed transactional applications which access databases
+ using the JDBC APIs. JDBC supports two-phase commit of transactions, and is similar to the XA X/Open
+ standard. JBossTS provides JDBC support in package <package>com.arjuna.ats.jdbc</package>. A list of the tested
+ drivers is available from the JBossTS website.<!-- Put this in an appendix? Link directly to it? -->
+ </para>
+ <para>
+ Only use the transactional JDBC support provided in package <package>com.arjuna.ats.jdbc</package> when you are
+ using JBossTS outside of an application server, such as JBoss Application Server, or another container. Otherwise,
+ use the JDBC support provided by your application server or container.
+ </para>
+ <section>
+ <title>Managing transactions</title>
+ <para>
+ JBossJTA needs the ability to associate work performed on a JDBC connection with a specific
+ transaction. Therefore, applications need to use a combination of implicit transaction propagation and indirect
+ transaction management. For each JDBC connection, JBossJTA must be able to determine the invoking thread's
+ current transaction context.
+ </para>
+ </section>
+ <section>
+ <title>Restrictions</title>
+ <para>
+ Nested transactions are not supported by JDBC. If you try to use a JDBC connection within a subtransaction,
+ JBossJTA throws a suitable exception and no work is allowed on that connection. However, if you need nested
+ transactions, and are comfortable with straying from the JDBC standard, you can set property
+ <varname>com.arjuna.ats.jta.supportSubtransactions</varname> property to <literal>YES</literal>.
+ </para>
+ </section>
+ </section>
+
+ <section>
+ <title>Transactional drivers</title>
+ <para>
+ The approach JBossJTA takes for incorporating JDBC connections within transactions is to provide transactional
+ JDBC drivers as conduits for all interactions. These drivers intercept all invocations and ensure that they are
+ registered with, and driven by, appropriate transactions. The driver
+ <classname>com.arjuna.ats.jdbc.TransactionalDriver</classname> handles all JDBC drivers, implementing the
+ <interfacename>java.sql.Driver</interfacename> interface. If the database is not transactiona, ACID properties
+ cannot be guaranteed.
+ </para>
+ <section>
+ <title>Loading drivers</title>
+ <example>
+ <title>Instantiating and using the driver within an application</title>
+ <programlisting language="Java" role="JAVA"><xi:include href="extras/instantiating_transactionaldriver.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ </example>
+
+ <example>
+ <title>Registering the drivers with the JDBC driver manager using the Java system properties</title>
+ <programlisting language="Java" role="JAVA">
+ <xi:include href="extras/registering_transactionaldriver_using_jdbc_driver_manager.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ <para>
+ The jdbc.drivers property contains a colon-separated list of driver class names, which the JDBC driver manager
+ loads when it is initialized. After the driver is loaded, you can use it to make a connection wtih a
+ database.
+ </para>
+ </example>
+ <example>
+ <title>Using the <methodname>Class.forName</methodname> method</title>
+ <para>
+ Calling <methodname>Class.forName()</methodname> automatically registers the driver with the JDBC driver
+ manager. It is also possible to explicitly create an instance of the JDBC driver.
+ </para>
+ <programlisting language="Java" role="JAVA"><xi:include href="extras/class.forName.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ </example>
+ </section>
+ </section>
+
+
+ <section>
+ <title>Connections</title>
+ <para>
+ Because JBossJTA provides JDBC connectivity via its own JDBC driver, application code can support transactions
+ witho relatively small code chnges. Typically, the application programmer only needs to start and terminate
+ transactions.
+ </para>
+ <section>
+ <title>JDBC</title>
+ <para>
+ The JBossJTA driver accepts the following properties, all located in class
+ <classname>com.arjuna.ats.jdbc.TransactionalDriver</classname>.
+ </para>
+ <informaltable>
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry>username</entry>
+ <entry>
+ <para>
+ the database username
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>password</entry>
+ <entry>
+ <para>
+ the database password
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>createDb</entry>
+ <entry>
+ <para>
+ creates the database automatically if set to <literal>true</literal>. Not all JDBC implementations
+ support this.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>dynamicClass</entry>
+ <entry>
+ <para>
+ specifies a class to instantiate to connect to the database, instead of using JNDI.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </section>
+ <section>
+ <title>XADataSources</title>
+ <para>
+ JDBC connections are created from appropriate DataSources. Connections which participate in distributed
+ transactions are obtained from XADataSources. When using a JDBC driver, JBossJTA uses the appropriate DataSource
+ whenever a connection to the database is made. It then obtains XAResources and registers them with the
+ transaction via the JTA interfaces. The transaction service uses these XAResources when the transaction
+ terminates in order to drive the database to either commit or roll back the changes made via the JDBC
+ connection.
+ </para>
+ <para>
+ JBossJTA JDBC support can obtain XADataSources through the Java Naming and Directory Interface (JNDI) or dynamic
+ class instnatiation.
+ </para>
+ <section>
+ <title>Java naming and directory interface (JNDI)</title>
+ <para>
+ A JDBC driver can use arbitrary DataSources without having to know specific details about their
+ implementations, by using JNDI. A specific DataSource or XADataSource can be created and registered with an
+ appropriate JNDI implementation, and the application, or JDBC driver, can later bind to and use it. Since JNDI
+ only allows the application to see the DataSource or XADataSource as an instance of the interface (e.g.,
+ javax.sql.XADataSource) rather than as an instance of the implementation class (e.g.,
+ com.mydb.myXADataSource), the application is not tied at build-time to only use a specific implementation.
+ </para>
+ <para>
+ For the TransactionalDriver class to use a JNDI-registered XADataSource, you need to create the
+ XADataSource instance and store it in an appropriate JNDI implementation. Details of how to do this can be
+ found in the JDBC tutorial available at the Java web site.<!--Link?-->
+ </para>
+ <example>
+ <title>Storing a datasource in a JNDI implementation</title>
+ <programlisting language="Java" role="JAVA"><xi:include href="extras/storing_datasource_in_jndi.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /> </programlisting>
+ <para>
+ The Context.INITIAL_CONTEXT_FACTORY property is the JNDI way of specifying the type of JNDI
+ implementation to use.
+ </para>
+ <para>
+ The application must pass an appropriate connection URL to the JDBC driver:
+ </para>
+ <programlisting language="Java" role="JAVA">
+ <xi:include href="extras/passing_connection_url_to_jdbc.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ <para>
+ The JNDI URL must be pre-pended with <literal>jdbc:arjuna:</literal> in order for the TransactionalDriver to
+ recognise that the DataSource must participate within transactions and be driven accordingly.
+ </para>
+ </example>
+ </section>
+ <section>
+ <title>Dynamic class instantiation</title>
+ <para>
+ If a JNDI implementation is not available. you can specify an implementation of the
+ <interfacename>DynamicClass</interfacename> interface, which is used to get the XADataSource object. This is
+ not recommended, but provides a fallback for environments where use of JNDI is not feasible.
+ </para>
+ <para>
+ Use the property <varname>TransactionalDriver.dynamicClass</varname> to specify the implementation to use. An
+ example is <literal>PropertyFileDynamicClass</literal>, a DynamicClass implementation that reads the
+ XADataSource implementation class name and configuration properties from a file, then instantiates and
+ configures it.
+ </para>
+ <note>
+ <title>Deprecated class</title>
+ <para>
+ The oracle_8_1_6 dynamic class is deprecated and should not be used.
+ </para>
+ </note>
+ <example>
+ <title>Instantiating a dynamic class</title>
+ <para>
+ The application code must specify which dynamic class the TransactionalDriver should instantiate when
+ setting up the connection:
+ </para>
+ <programlisting language="Java" role="JAVA"><xi:include href="extras/instantiating_dynamic_class.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ </example>
+ </section>
+ </section>
+ <section>
+ <title>Using the connection</title>
+ <para>
+ Once the connection is established, all operations on the connection are monitored by JBossJTA. you do not need
+ to use the transactional connection within transactions. If a transaction is not present when the connection is
+ used, then operations are performed directly on the database.
+ </para>
+ <important>
+ <para>
+ JDBC does not support subtransactions.
+ </para>
+ </important>
+ <para>
+ You can use transaction timeouts to automatically terminate transactions if a connection is not terminated
+ within an appropriate period.
+ </para>
+ <para>
+ You can use JBossJTA connections within multiple transactions simultaneously. An example would be different
+ threads, with different notions of the current transaction. JBossJTA does connection pooling for each
+ transaction within the JDBC connection. Although multiple threads may use the same instance of the JDBC
+ connection, internally there may be a separate connection for each transaction. With the exception of method
+ <methodname>close</methodname>, all operations performed on the connection at the application level are only
+ performed on this transaction-specific connection.
+ </para>
+ <para>
+ JBossJTA automatically registers the JDBC driver connection with the transaction via an appropriate
+ resource. When the transaction terminates, this resource either commits or rolls back any changes made to the
+ underlying database via appropriate calls on the JDBC driver.
+ </para>
+ <para>
+ Once created, the driver and any connection can be used in the same way as any other JDBC driver or connection.
+ </para>
+ <example>
+ <title>Creating and using a connection</title>
+ <programlisting language="Java" role="JAVA"><xi:include href="extras/creating_and_using_a_connection.java"
+ xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ </example>
+ </section>
+
+ <section>
+ <title>Connection pooling</title>
+ <para>
+ For each user name and password, JBossJTA maintains a single instance of each connection for as long as that
+ connection is in use. Subsequent requests for the same connection get a reference to the original connection,
+ rather than a new instance. Yuo can try to close the connection, but the connection will only actually be closed
+ when all users (including transactions) have either finished with the connection, or issued
+ <methodname>close</methodname> calls.
+ </para>
+ </section>
+
+ <section>
+ <title>Reusing connections</title>
+ <para>
+ Some JDBC drivers allow the reuse of a connection for multiple different transactions once a given transaction
+ completes. Unfortunately this is not a common feature, and other drivers require a new connection to be
+ obtained for each new transaction. By default, the JBossJTA transactional driver always obtains a new
+ connection for each new transaction. However, if an existing connection is available and is currently unused,
+ JBossJTA can reuse this connection. To turn on this feature, add option <varname>reuseconnection=true</varname>
+ to the JDBC URL. For instance, <code>jdbc:arjuna:sequelink://host:port;databaseName=foo;reuseconnection=true</code>
+ </para>
+ </section>
+
+ <section>
+ <title>Terminating the transaction</title>
+ <para>
+ When a transaction with an associated JDBC connection terminates, because of the application or because a
+ transaction timeout expires, JBossJTA uses the JDBC driver to drive the database to either commit or roll back
+ any changes made to it. This happens transparently to the application.
+ </para>
+ </section>
+
+ <section>
+ <title>AutoCommit</title>
+ <para>
+ If property <varname>AutoCommit</varname> of the interface <varname>java.sql.Connection</varname> is set to
+ <literal>true</literal> for JDBC, the execution of every SQL statement is a separate top-level transaction, and
+ it is not possible to group multiple statements to be managed within a single OTS transaction. Therefore,
+ JBossJTA disables <varname>AutoCommit</varname> on JDBC connections before they can be used. If
+ <varname>AutoCommit</varname> is later set to <literal>true</literal> by the application, JBossJTA throws the
+ <systemitem>java.sql.SQLException</systemitem>.
+ </para>
+ </section>
+
+ <section>
+ <title>Setting isolation levels</title>
+ <para>
+ When you use the JBossJTA JDBC driver, you may need to set the underlying transaction isolation level on the XA
+ connection. By default, this is set to <literal>TRANSACTION_SERIALIZABLE</literal>, but another value may be
+ more appropriate for your application. To change it, set the property
+ <varname>com.arjuna.ats.jdbc.isolationLevel</varname> to the appropriate isolation level in string form. Example
+ values are <literal>TRANSACTION_READ_COMMITTED</literal> or <literal>TRANSACTION_REPEATABLE_READ</literal>.
+ </para>
+ <note>
+ <para>
+ Currently, this property applies to all XA connections created in the JVM.
+ </para>
+ </note>
+ </section>
+ </section>
</chapter>
Modified: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/Using_JBossTA_In_Application_Servers.xml
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/Using_JBossTA_In_Application_Servers.xml 2010-11-10 04:42:27 UTC (rev 35929)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/Using_JBossTA_In_Application_Servers.xml 2010-11-10 06:52:56 UTC (rev 35930)
@@ -4,6 +4,83 @@
%BOOK_ENTITIES;
]>
<chapter>
- <title></title>
+ <title>Using JBossJTA in application servers</title>
+ <para>
+ JBoss Application Server is discussed here. Refer to the documentation for your application server for differences.
+ </para>
+ <section>
+ <title>Configuration</title>
+ <para>
+ When JBossJTA runs embedded in JBossAS, the transaction system is configured primarily through the
+ <filename>transaction-jboss-beans.xml</filename> deployment descriptor, which overrides properties read from the
+ default properties file embedded in the .<filename>jar</filename> file.
+ </para>
+ <table>
+ <title>Common configuration attributes</title>
+ <tgroup cols="2">
+ <tbody>
+ <row>
+ <entry>CoordinatorEnvironmentBean.defaultTimeout</entry>
+ <entry>
+ <para>
+ The default transaction timeout to be used for new transactions. Specified as an integer in seconds.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>CoordinatorEnvironmentBean.enableStatistics</entry>
+ <entry>
+ <para>
+ This determines whether or not the transaction service should gather statistical information. This
+ information can then be viewed using the TransactionStatistics MBean. Specified as a Boolean. The
+ default is to not gather this information.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ See the <filename>transaction-jboss-beans.xml</filename> file and the JBoss Application Server administration and
+ configuration guide for further information.
+ </para>
+ </section>
+
+ <section>
+ <title>Logging</title>
+ <para>
+ To make JBossTS logging semantically consistent with JBossAS, the
+ <interfacename>TransactionManagerService</interfacename> modifies the level of some log messages, by overriding
+ the value of the <varname>LoggingEnvironmentBean.loggingFactory</varname> property in the
+ <filename>jbossts-properties.xml</filename> file. Therefore, the value of this property has no effect on the
+ logging behavior when running embedded in JBossAS. By forcing use of the <systemitem>log4j_releveler</systemitem>
+ logger, the <interfacename>TransactionManagerService</interfacename> changes the level of all
+ <literal>INFO</literal> level messages in the transaction code to <literal>DEBUG</literal>. Therefore, these
+ messages do not appear in log files if the filter level is <literal>INFO</literal>. All other log messages behave
+ as normal.
+ </para>
+ </section>
+
+ <section>
+ <title>The services</title>
+ <para>
+ The <interfacename>TransactionManager</interfacename> bean provides transaction management services to other
+ components in JBossAS. There are two different version of this bean and they requires different configuation. Take
+ care to select the <filename>transaction-jboss-beans.xml</filename> suitable for your needs (local JTA or JTS).
+ </para>
+ </section>
+
+ <section>
+ <title>Ensuring transactional context is propatated to the server</title>
+ <para>
+ You can coordinate transactions from a coordinator which is not located within the JBoss server
+ , such as when using transactions created by an external OTS server. To ensure the transaction context is propagated via
+ JRMP invocations to the server, the transaction propagation context factory needs to be explicitly set for the
+ JRMP invoker proxy. This is done as follows:
+ </para>
+ <programlisting language="Java" role="JAVA"><xi:include href="extras/jrmp_invoker_proxy.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ </section>
+
+
</chapter>
Added: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/class.forName.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/class.forName.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/class.forName.java 2010-11-10 06:52:56 UTC (rev 35930)
@@ -0,0 +1,3 @@
+sun.jdbc.odbc.JdbcOdbcDriver drv = new sun.jdbc.odbc.JdbcOdbcDriver();
+
+DriverManager.registerDriver(drv);
Added: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/creating_and_using_a_connection.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/creating_and_using_a_connection.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/creating_and_using_a_connection.java 2010-11-10 06:52:56 UTC (rev 35930)
@@ -0,0 +1,14 @@
+Statement stmt = conn.createStatement();
+
+try
+ {
+ stmt.executeUpdate("CREATE TABLE test_table (a INTEGER,b INTEGER)");
+ }
+catch (SQLException e)
+ {
+ // table already exists
+ }
+
+stmt.executeUpdate("INSERT INTO test_table (a, b) VALUES (1,2)");
+
+ResultSet res1 = stmt.executeQuery("SELECT * FROM test_table");
Added: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/failure_recovery_example.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/failure_recovery_example.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/failure_recovery_example.java 2010-11-10 06:52:56 UTC (rev 35930)
@@ -0,0 +1,167 @@
+/*
+ * Some XAResourceRecovery implementations will do their startup work here,
+ * and then do little or nothing in setDetails. Since this one needs to know
+ * dynamic class name, the constructor does nothing.
+ */
+
+public BasicXARecovery () throws SQLException
+{
+ numberOfConnections = 1;
+ connectionIndex = 0;
+ props = null;
+}
+
+/**
+ * The recovery module will have chopped off this class name already. The
+ * parameter should specify a property file from which the url, user name,
+ * password, etc. can be read.
+ *
+ * @message com.arjuna.ats.internal.jdbc.recovery.initexp An exception
+ * occurred during initialisation.
+ */
+
+public boolean initialise (String parameter) throws SQLException
+{
+ if (parameter == null)
+ return true;
+
+ int breakPosition = parameter.indexOf(BREAKCHARACTER);
+ String fileName = parameter;
+
+ if (breakPosition != -1)
+ {
+ fileName = parameter.substring(0, breakPosition - 1);
+
+ try
+ {
+ numberOfConnections = Integer.parseInt(parameter
+ .substring(breakPosition + 1));
+ }
+ catch (NumberFormatException e)
+ {
+ return false;
+ }
+ }
+
+ try
+ {
+ String uri = com.arjuna.common.util.FileLocator
+ .locateFile(fileName);
+ jdbcPropertyManager.propertyManager.load(XMLFilePlugin.class
+ .getName(), uri);
+
+ props = jdbcPropertyManager.propertyManager.getProperties();
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * @message com.arjuna.ats.internal.jdbc.recovery.xarec {0} could not find
+ * information for connection!
+ */
+
+public synchronized XAResource getXAResource () throws SQLException
+{
+ JDBC2RecoveryConnection conn = null;
+
+ if (hasMoreResources())
+ {
+ connectionIndex++;
+
+ conn = getStandardConnection();
+
+ if (conn == null) conn = getJNDIConnection();
+ }
+
+ return conn.recoveryConnection().getConnection().getXAResource();
+}
+
+public synchronized boolean hasMoreResources ()
+{
+ if (connectionIndex == numberOfConnections)
+ return false;
+ else
+ return true;
+}
+
+private final JDBC2RecoveryConnection getStandardConnection ()
+ throws SQLException
+{
+ String number = new String("" + connectionIndex);
+ String url = new String(dbTag + number + urlTag);
+ String password = new String(dbTag + number + passwordTag);
+ String user = new String(dbTag + number + userTag);
+ String dynamicClass = new String(dbTag + number + dynamicClassTag);
+
+ Properties dbProperties = new Properties();
+
+ String theUser = props.getProperty(user);
+ String thePassword = props.getProperty(password);
+
+ if (theUser != null)
+ {
+ dbProperties.put(TransactionalDriver.userName, theUser);
+ dbProperties.put(TransactionalDriver.password, thePassword);
+
+ String dc = props.getProperty(dynamicClass);
+
+ if (dc != null)
+ dbProperties.put(TransactionalDriver.dynamicClass, dc);
+
+ return new JDBC2RecoveryConnection(url, dbProperties);
+ }
+ else
+ return null;
+}
+
+private final JDBC2RecoveryConnection getJNDIConnection ()
+ throws SQLException
+{
+ String number = new String("" + connectionIndex);
+ String url = new String(dbTag + jndiTag + number + urlTag);
+ String password = new String(dbTag + jndiTag + number + passwordTag);
+ String user = new String(dbTag + jndiTag + number + userTag);
+
+ Properties dbProperties = new Properties();
+
+ String theUser = props.getProperty(user);
+ String thePassword = props.getProperty(password);
+
+ if (theUser != null)
+ {
+ dbProperties.put(TransactionalDriver.userName, theUser);
+ dbProperties.put(TransactionalDriver.password, thePassword);
+
+ return new JDBC2RecoveryConnection(url, dbProperties);
+ }
+ else
+ return null;
+}
+
+private int numberOfConnections;
+private int connectionIndex;
+private Properties props;
+private static final String dbTag = "DB_";
+private static final String urlTag = "_DatabaseURL";
+private static final String passwordTag = "_DatabasePassword";
+private static final String userTag = "_DatabaseUser";
+private static final String dynamicClassTag = "_DatabaseDynamicClass";
+private static final String jndiTag = "JNDI_";
+
+/*
+ * Example:
+ *
+ * DB2_DatabaseURL=jdbc\:arjuna\:sequelink\://qa02\:20001
+ * DB2_DatabaseUser=tester2 DB2_DatabasePassword=tester
+ * DB2_DatabaseDynamicClass=com.arjuna.ats.internal.jdbc.drivers.sequelink_5_1
+ *
+ * DB_JNDI_DatabaseURL=jdbc\:arjuna\:jndi DB_JNDI_DatabaseUser=tester1
+ * DB_JNDI_DatabasePassword=tester DB_JNDI_DatabaseName=empay
+ * DB_JNDI_Host=qa02 DB_JNDI_Port=20000
+ */
+private static final char BREAKCHARACTER = ';'; // delimiter for parameters
\ No newline at end of file
Added: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/instantiating_dynamic_class.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/instantiating_dynamic_class.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/instantiating_dynamic_class.java 2010-11-10 06:52:56 UTC (rev 35930)
@@ -0,0 +1,9 @@
+Properties dbProps = new Properties();
+
+dbProps.setProperty(TransactionalDriver.userName, "user");
+dbProps.setProperty(TransactionalDriver.password, "password");
+dbProps.setProperty(TransactionalDriver.dynamicClass,
+ "com.arjuna.ats.internal.jdbc.drivers.PropertyFileDynamicClass");
+
+TransactionalDriver arjunaJDBC2Driver = new TransactionalDriver();
+Connection connection = arjunaJDBC2Driver.connect("jdbc:arjuna:/path/to/property/file", dbProperties);
Added: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/instantiating_transactional_driver.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/instantiating_transactional_driver.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/instantiating_transactional_driver.java 2010-11-10 06:52:56 UTC (rev 35930)
@@ -0,0 +1 @@
+TransactionalDriver arjunaJDBC2Driver = new TransactionalDriver();
\ No newline at end of file
Added: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/jdbc_example.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/jdbc_example.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/jdbc_example.java 2010-11-10 06:52:56 UTC (rev 35930)
@@ -0,0 +1,120 @@
+public class JDBCTest
+{
+ public static void main (String[] args)
+ {
+ /*
+ */
+
+ Connection conn = null;
+ Connection conn2 = null;
+ Statement stmt = null; // non-tx statement
+ Statement stmtx = null; // will be a tx-statement
+ Properties dbProperties = new Properties();
+
+ try
+ {
+ System.out.println("\nCreating connection to database: "+url);
+
+ /*
+ * Create conn and conn2 so that they are bound to the JBossTS
+ * transactional JDBC driver. The details of how to do this will
+ * depend on your environment, the database you wish to use and
+ * whether or not you want to use the Direct or JNDI approach. See
+ * the appropriate chapter in the JTA Programmers Guide.
+ */
+
+ stmt = conn.createStatement(); // non-tx statement
+
+ try
+ {
+ stmt.executeUpdate("DROP TABLE test_table");
+ stmt.executeUpdate("DROP TABLE test_table2");
+ }
+ catch (Exception e)
+ {
+ // assume not in database.
+ }
+
+ try
+ {
+ stmt.executeUpdate("CREATE TABLE test_table (a INTEGER,b INTEGER)");
+ stmt.executeUpdate("CREATE TABLE test_table2 (a INTEGER,b INTEGER)");
+ }
+ catch (Exception e)
+ {
+ }
+
+ try
+ {
+ System.out.println("Starting top-level transaction.");
+
+ com.arjuna.ats.jta.UserTransaction.userTransaction().begin();
+
+ stmtx = conn.createStatement(); // will be a tx-statement
+
+ System.out.println("\nAdding entries to table 1.");
+
+ stmtx.executeUpdate("INSERT INTO test_table (a, b) VALUES (1,2)");
+
+ ResultSet res1 = null;
+
+ System.out.println("\nInspecting table 1.");
+
+ res1 = stmtx.executeQuery("SELECT * FROM test_table");
+ while (res1.next())
+ {
+ System.out.println("Column 1: "+res1.getInt(1));
+ System.out.println("Column 2: "+res1.getInt(2));
+ }
+
+ System.out.println("\nAdding entries to table 2.");
+
+ stmtx.executeUpdate("INSERT INTO test_table2 (a, b) VALUES (3,4)");
+ res1 = stmtx.executeQuery("SELECT * FROM test_table2");
+ System.out.println("\nInspecting table 2.");
+
+ while (res1.next())
+ {
+ System.out.println("Column 1: "+res1.getInt(1));
+ System.out.println("Column 2: "+res1.getInt(2));
+ }
+ System.out.print("\nNow attempting to rollback changes.");
+ com.arjuna.ats.jta.UserTransaction.userTransaction().rollback();
+
+ com.arjuna.ats.jta.UserTransaction.userTransaction().begin();
+ stmtx = conn.createStatement();
+ ResultSet res2 = null;
+
+ System.out.println("\nNow checking state of table 1.");
+
+ res2 = stmtx.executeQuery("SELECT * FROM test_table");
+ while (res2.next())
+ {
+ System.out.println("Column 1: "+res2.getInt(1));
+ System.out.println("Column 2: "+res2.getInt(2));
+ }
+
+ System.out.println("\nNow checking state of table 2.");
+
+ stmtx = conn.createStatement();
+ res2 = stmtx.executeQuery("SELECT * FROM test_table2");
+ while (res2.next())
+ {
+ System.out.println("Column 1: "+res2.getInt(1));
+ System.out.println("Column 2: "+res2.getInt(2));
+ }
+
+ com.arjuna.ats.jta.UserTransaction.userTransaction().commit(true);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ System.exit(0);
+ }
+ }
+ catch (Exception sysEx)
+ {
+ sysEx.printStackTrace();
+ System.exit(0);
+ }
+ }
\ No newline at end of file
Added: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/jrmp_invoker_proxy.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/jrmp_invoker_proxy.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/jrmp_invoker_proxy.java 2010-11-10 06:52:56 UTC (rev 35930)
@@ -0,0 +1 @@
+JRMPInvokerProxy.setTPCFactory( new com.arjuna.ats.internal.jbossatx.jts.PropagationContextManager() );
\ No newline at end of file
Added: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/passing_connection_url_to_jdbc.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/passing_connection_url_to_jdbc.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/passing_connection_url_to_jdbc.java 2010-11-10 06:52:56 UTC (rev 35930)
@@ -0,0 +1,13 @@
+Properties dbProps = new Properties();
+
+dbProps.setProperty(TransactionalDriver.userName, "user");
+dbProps.setProperty(TransactionalDriver.password, "password");
+
+// the driver uses its own JNDI context info, remember to set it up:
+jdbcPropertyManager.propertyManager.setProperty(
+ "Context.INITIAL_CONTEXT_FACTORY", initialCtx);
+jdbcPropertyManager.propertyManager.setProperty(
+ "Context.PROVIDER_URL", myUrl);
+
+TransactionalDriver arjunaJDBCDriver = new TransactionalDriver();
+Connection connection = arjunaJDBCDriver.connect("jdbc:arjuna:jdbc/foo", dbProps);
Added: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/registering_transactionaldriver_using_jdbc_driver_manager.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/registering_transactionaldriver_using_jdbc_driver_manager.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/registering_transactionaldriver_using_jdbc_driver_manager.java 2010-11-10 06:52:56 UTC (rev 35930)
@@ -0,0 +1,13 @@
+Properties p = System.getProperties();
+
+switch (dbType)
+{
+case MYSQL:
+ p.put("jdbc.drivers", "com.mysql.jdbc.Driver");
+ break;
+case PGSQL:
+ p.put("jdbc.drivers", "org.postgresql.Driver");
+ break;
+}
+
+System.setProperties(p);
Added: labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/storing_datasource_in_jndi.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/storing_datasource_in_jndi.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/docs/ArjunaTA_Development_Guide/en-US/extras/storing_datasource_in_jndi.java 2010-11-10 06:52:56 UTC (rev 35930)
@@ -0,0 +1,9 @@
+XADataSource ds = MyXADataSource();
+Hashtable env = new Hashtable();
+String initialCtx = PropertyManager.getProperty("Context.INITIAL_CONTEXT_FACTORY");
+
+env.put(Context.INITIAL_CONTEXT_FACTORY, initialCtx);
+
+initialContext ctx = new InitialContext(env);
+
+ctx.bind("jdbc/foo", ds);
More information about the jboss-svn-commits
mailing list