(转贴)How to use JDBC and transactions in Tomcat with JOTM

转载 2004年09月14日 11:16:00

How to use JDBC and transactions in Tomcat with JOTM

Target audience

This howto is intended to Servlet/JSP developpers using Tomcat who want to take advantage of distributed transactions when using JDBC code in their servlets

This howto was written based on the JNDI Datasource HOW-TO provided by Tomcat.

It has been written for:

  • Tomcat 4.1.18
  • JOTM 1.4

It has been successfully reported to work on

  • MySQL
    • version 4.0.12, using InnoDB
    • with mysql-connector-java version 2.0.14
  • PostgreSQL
    • version 7.3.1
    • with pg73jdbc2.jar

1. Introduction

JOTM (Java Open Transaction Manager) is a transaction manager written in Java and implementating JTA (Java Transaction API). It is an Open Source project released under a BSD-style license.

Tomcat is the servlet container that is used in the official Reference Implementation for the Java Servlet and JavaServer Pages (JSP) technologies. Tomcat is released under the Apache Software License

MySQL configuration

Ensure that you follow these instructions as variations can cause problems.

Create a new test user, a new database and a single test table. Your MySQL user must have a password assigned. The driver will fail if you try to connect with an empty password.

mysql> GRANT ALL PRIVILEGES ON *.* TO mojo@localhost
    ->   IDENTIFIED BY 'jojo' WITH GRANT OPTION;
mysql> create database javatest;
mysql> use javatest;
mysql> create table testdata (
    ->   id int not null auto_increment primary key,
    ->   foo int)type=InnoDB;
mysql>

Note: the above user should be removed once testing is complete!

Next insert some test data into the testdata table.

mysql> insert into testdata values(null, 1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from testdata;
+----+-----+
| ID | FOO |
+----+-----+
|  1 |   1 |
+----+-----+
1 row in set (0.00 sec)
mysql>

PostgreSQL configuration is similar.

Installing Required JARs

In order for a web application to use JOTM, the webapp and Tomcat need to have access to the JOTM jars, as well as the jars it requires

Here is a list of the required jars. They are all included with JOTM 1.4 binary distribution, available at http://www.objectweb.org/jotm

  • in the lib/ directory
    • jotm.jar
    • jotm_jrmp_stubs.jar
    • jonas_timer.jar
    • carol.jar
    • jta-spec1_0_1.jar
    • jts1_0.jar
    • objectweb-datasource.jar
    • xapool.jar

All these jar files need to be placed on $TOMCAT_HOME/common/lib/ so that both Tomcat and your web application will see them.

You also need to copy the jar of your JDBC driver to $TOMCAT_HOME/common/lib/.

Configuring JOTM

You'll need to create a file named carol.properties with the following properties:

# lmi stands for Local Method Invocation (it's a "fake" RMI)
carol.protocols=lmi
# do not use CAROL JNDI wrapper
carol.start.jndi=false
# do not start a name server
carol.start.ns=false
    

this file needs to be placed on $TOMCAT_HOME/common/classes/ so that Tomcat and JOTM will see it.

Configuring Tomcat

server.xml configuration

Now that you've installed JOTM in Tomcat, you need to configure Tomcat so that it can access JDBC and transaction resources. This is done in the dbtest.xml file which will be used by Tomcat to initialize the resources used by your web application.

<Context path="/dbtest" docBase="dbtest.war" debug="0"
  reloadable="true" crossContext="true">
  <!-- Resource configuration for JDBC datasource
       use XAPool
  -->
  <Resource name="jdbc/myDB" auth="Container"
    type="javax.sql.DataSource"/>
  <ResourceParams name="jdbc/myDB">
    <parameter>
      <name>factory</name>
      <value>org.objectweb.jndi.DataSourceFactory</value>
    </parameter>
    <!-- configured by default for PostgreSQL, just change the values
         to set it for your database
    -->
    <parameter><name>username</name><value>mojo</value></parameter>
    <parameter><name>password</name><value>jojo</value></parameter>
    <parameter><name>driverClassName</name>
      <value>org.postgresql.Driver</value></parameter>
    <parameter><name>url</name>
      <value>jdbc:postgresql://localhost/javatest</value></parameter>
    <!--
       <parameter><name>driverClassName</name>
       <value>org.gjt.mm.mysql.Driver</value></parameter>
       <parameter><name>url</name>
       <value>jdbc:mysql://localhost/javatest</value></parameter>
    -->
  </ResourceParams>
  <!-- Resource configuration for UserTransaction
  use JOTM
  -->
  <Resource name="UserTransaction" auth="Container"
    type="javax.transaction.UserTransaction"/>
  <ResourceParams name="UserTransaction">
    <parameter>
      <name>factory</name>
      <value>org.objectweb.jotm.UserTransactionFactory</value>
    </parameter>
    <parameter>
      <name>jotm.timeout</name>
      <value>60</value>
    </parameter>
  </ResourceParams>
</Context>

web.xml configuration

Now you have to configure the web.xml file of your web application

<?xml version="1.0" encoding="ISO-8859-1"?>
 <!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
  <resource-env-ref>
    <description>
      DB Connection
    </description>
    <resource-env-ref-name>
      jdbc/myDB
    </resource-env-ref-name>
    <resource-env-ref-type>
      javax.sql.DataSource
    </resource-env-ref-type>
  </resource-env-ref>
</web-app>

Test Code

Now create a simple test.jsp for use later.

<html>
  <head>
    <title>DB Test</title>
  </head>
  <body>
    <%
    String completion = request.getParameter("completion");
    foo.DBTest test = new foo.DBTest();
    test.init(completion);
    %>
    <h2>Transaction completion</h2>
    Transaction completion is :<strong><%= completion %></strong>
    <h2>Results</h2>
    Int stored in JDBC : <strong><%= test.getFoo() %></strong><br />
    <hr />
    <form action="test.jsp" method="get">
      <input type="radio" name="completion" value="commit" checked="true"> Commit<BR>
      <input type="radio" name="completion" value="rollback">Rollback<BR>
      <button type="submit">Completion</button>
    </form>
  </body>
</html>

And create a Java class to actually use your new Datasource and transactions. Note: this code isn't anywhere near production ready - it's only supposed to be used as a simple test :-)

package foo;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.transaction.UserTransaction;
public class DBTest{
    int foo = -1;
    // value stored in DB
    public void init(String completion) {
        try{
            Context ctx = new InitialContext();
            // JDBC stuff
            DataSource ds =
                (DataSource)ctx.lookup("java:comp/env/jdbc/myDB");
            UserTransaction ut = (UserTransaction)ctx.lookup("java:comp/UserTransaction");
            java.sql.Connection conn = ds.getConnection();
            System.out.println("<<< beginning the transaction >>>");
            ut.begin();
             // JDBC statements
             Statement stmt = conn.createStatement();
             ResultSet rst =
                 stmt.executeQuery("select id, foo from testdata");
             if(rst.next()) {
                 foo=rst.getInt(2);
             }
             System.out.println("foo = "+ foo +" (before completion)");
             PreparedStatement pstmt = conn.prepareStatement("update testdata set foo=? where id=1");
             pstmt.setInt(1,++foo);
             pstmt.executeUpdate();
              if (completion != null && completion.equals("commit")) {
                  System.out.println("<<< committing the transaction >>>");
                  ut.commit();
              } else {
                  System.out.println("<<< rolling back the transaction >>>");
                  ut.rollback();
              }
             // we set foo to the value stored in the DB
             rst =
                 stmt.executeQuery("select id, foo from testdata");
             if(rst.next()) {
                 foo=rst.getInt(2);
             }
             System.out.println("foo = "+ foo +" (after completion)");
             conn.close();
             System.out.println("<<< done >>>");
        }catch(Exception e) {
            System.out.print("DBTest >> ");
            e.printStackTrace();
        }
    }
    public String getFoo() { return ""+foo; }
}

Finally deploy your web app into $CATALINA_HOME/webapps as a warfile called dbtest.war.

Once deployed, point a browser at http://localhost:8080/dbtest/test.jsp to view the fruits of your hard work.

使用JOTM进行Tomcat的JTA调用

前段时间碰到一个需要访问多个数据库的例子,由于项目上是采用tomcat作为项目开发和布署,所以就没有考虑采用特定厂商的JTA实现,而是通过一个开源的JTA实现来完成tomcat和多个数据库之间的直接交...
  • andymu077
  • andymu077
  • 2015年07月20日 11:12
  • 1332

在Spring中使用JOTM实现JTA事务管理

Spring 通过AOP技术可以让我们在脱离EJB的情况下享受声明式事务的丰盛大餐,脱离Java EE应用服务器使用声明式事务的道路已经畅通无阻。但是很大部分人都还认为脱离Java EE应用服务器...
  • zmx729618
  • zmx729618
  • 2016年07月19日 16:19
  • 2037

《how tomcat works》翻译开篇

《how tomcat work》翻译此书只为学习,有错误,不到位之处,请指出。文笔欠佳,请多海涵。简介概述欢迎来到《how tomcat works》,这本书剖析了当下免费的 ,开源的,并且是最为流...
  • tomcat_how_work
  • tomcat_how_work
  • 2015年11月01日 23:26
  • 664

Spring分布式事务实现jotm,atomikos

分布式事务是指操作多个数据库之间的事务,spring的org.springframework.transaction.jta.JtaTransactionManager,提供了分布式事务支持。如果使用...
  • zhousenshan
  • zhousenshan
  • 2017年05月06日 09:08
  • 489

Eclipse修改tomcat输出路径配置

有些笔记不记下来,总以为用的时候就知道了,不需要记。可是,由于经常不记,总会重复去解决同样的问题。但,如果我们能记下笔记,偶尔看看,那么有些问题是可以避免的,也就不会浪费时间了。 Eclip...
  • YY_LOVE_MY
  • YY_LOVE_MY
  • 2014年11月27日 09:28
  • 2385

年纪轻轻记忆力就衰退得厉害,我还有救吗?

转自:http://36kr.com/p/5097688.html 如果我有一小时的时间来背诵一段材料,我会花 55 分钟搞清楚为什么要背它、它能给我带来什么价值,然后再用 5 分钟时间去记住它。 ...
  • shellching
  • shellching
  • 2017年10月18日 17:40
  • 353

tomcat_配置jdbc(小例)

tomcat下配置jdbc举例        使用tomcat手工配置jdbc时,一般会到应用下面的webapps中的“应用名称\WEB-INF\classes”文件夹中找到jdbc.properti...
  • huangyanlong
  • huangyanlong
  • 2015年07月25日 12:34
  • 2633

Keil C51编译及连接技术(覆盖技术OVERLAY)

http://www.cnblogs.com/heiyue/p/3271421.html Keil C51编译及连接技术
  • chungle2011
  • chungle2011
  • 2014年12月20日 21:22
  • 4877

Go实战--golang中使用号称全世界最快的JSON解析器json-iterator(json-iterator/go)

生命不止,继续go go go!!!号外号外,差不一条广告,我的博客六月到十一月UV的地域分布: golang中的使用json一点也不陌生,golang为我们提供了官方的encoding/json:...
  • wangshubo1989
  • wangshubo1989
  • 2017年12月04日 14:57
  • 12010

开发环境配置-tomcat的安装、配置与使用-7

tomcat eclipse
  • TD_ZM
  • TD_ZM
  • 2016年04月06日 10:04
  • 903
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:(转贴)How to use JDBC and transactions in Tomcat with JOTM
举报原因:
原因补充:

(最多只允许输入30个字)