Võ Văn Hải's blog

Chỉ có một điều tuyệt đối đó là mọi thứ đều tương đối…

TẠO TRANSACTION VỚI CONTAINER-MANAGED TRANSACTION

TẠO TRANSACTION VỚI CONTAINER-MANAGED TRANSACTION

Author: Võ Văn Hải

CNC-Aptech, Tp HCM

Website: https://vovanhai.wordpress.com

Email: vovanhaiqn@google.com

  1. Giới thiệu

Trong EJB với container-managed transactions (CMT), EJB Container sẽ quản lý mọi giao dịch bên dưới với database. Đây là cách phát triển ứng dụng EJB transaction đơn giản và dễ dàng nhất bởi vì người phát triển không phải viết code để begins, commits, và roll-back giao dịch. Container-managed transactions không đòi hỏi tất cả các phương thức pahi3 có sự giao dịch. Khi triển khai 1 bean, chúng ta sẽ chỉ định phương thức nào trong bean sẽ thực thi vói giao dịch bằng cách thiết lập các thuộc tính trong EJB’s deployment descriptor.

  1. Một ví dụ sử dụng CMT

Sau đây là 1 ví dụ EJB với CMT để sinh viên đăng ký các môn học.

  1. Tạo Remote Interface

package cmt;

import java.rmi.RemoteException;

import java.util.Collection;

import javax.ejb.EJBObject;

public interface EnrollmentCart extends EJBObject

{

public void addEnrollment(EnrollmentInfo enroll) throws RemoteException;

public void deleteEnrollment(int itemId) throws RemoteException;

public Collection getEnrollments() throws RemoteException;

public void emptyCart() throws RemoteException;

public void register() throws InsufficientRoomException, RemoteException;

}

  1. Tạo Home Interface

package cmt;

import java.rmi.RemoteException;

import javax.ejb.CreateException;

import javax.ejb.EJBHome;

public interface EnrollmentCartHome extends EJBHome

{

EnrollmentCart create() throws CreateException, RemoteException;

}

  1. Tạo Bean’s Class

package cmt;

import java.rmi.RemoteException;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.Collection;

import java.util.HashSet;

import java.util.Iterator;

import javax.ejb.CreateException;

import javax.ejb.EJBException;

import javax.ejb.SessionBean;

import javax.ejb.SessionContext;

import javax.ejb.SessionSynchronization;

import javax.naming.InitialContext;

public class EnrollmentCartEJB implements SessionBean, SessionSynchronization

{

private SessionContext ejbCtx;

private HashSet cart;

private boolean isFailed = false;

public EnrollmentCartEJB(){}

// SessionSynchronization methods

public void afterBegin() {}

public void beforeCompletion() {

if (isFailed)

ejbCtx.setRollbackOnly();

}

public void afterCompletion(boolean committed) {

if (committed == false)

throw new EJBException(“Transaction afterCompletion failed”);

System.out.println(“afterCompletion: Transaction succeeds…”);

}

// Business methods

public void addEnrollment(EnrollmentInfo enroll) throws RemoteException {

cart.add(enroll);

}

public void register() throws InsufficientRoomException, RemoteException {

java.sql.Statement stmt = null;

java.sql.Statement stmt2 = null;

java.sql.Connection conn = null;

System.out.println(“register: started..”);

try{

InitialContext initCtx = new InitialContext();

javax.sql.DataSource ds =

(javax.sql.DataSource)initCtx.lookup (“java:comp/env/jdbc/studentsDB”);

conn = ds.getConnection();

stmt = conn.createStatement();

stmt2 = conn.createStatement();

} catch (Exception e){

e.printStackTrace();

}

try{

Iterator it = cart.iterator();

while (it.hasNext()){

EnrollmentInfo enroll=(EnrollmentInfo)it.next();

ResultSet rs = stmt.executeQuery

(“SELECT * FROM COURSES WHERE COURSE_ID='” +

enroll.getCourseId()+“‘”);

while (rs.next()){

int mlimit = rs.getInt(“MAX_LIMIT”);

int curr = rs.getInt(“CURR_ENROLL”);

if (mlimit < curr + 1){

isFailed = true;

ejbCtx.setRollbackOnly();

throw new InsufficientRoomException();

}else{

curr++;

stmt2.executeUpdate(“UPDATE COURSES SET CURR_ENROLL =” + curr

+ ” WHERE COURSE_ID='” + enroll.getCourseId()+“‘”);

System.out.println(“register: Database updated for: “+

enroll.getCourseId());

}

}

}

System.out.println(“register: success..”);

}catch (SQLException ex){

// This is a system level exception

throw new EJBException

(“Transaction rollback due to SQLException: “+ ex.getMessage());

}

}

public Collection getEnrollments() throws RemoteException {

return cart;

}

public void emptyCart() throws RemoteException {

cart.clear();

}

public void deleteEnrollment(int itemId) throws RemoteException {

for(Iterator i = getEnrollments().iterator(); i.hasNext(); ) {

EnrollmentInfo tmpEnrol = (EnrollmentInfo) i.next();

if (tmpEnrol.getItemId() == itemId) {

getEnrollments().remove(tmpEnrol);

break;

}

}

}

// EJB methods

public void setSessionContext(SessionContext ctx){

this.ejbCtx = ctx;

}

public void ejbCreate() throws CreateException{

cart = new HashSet();

}

public void ejbRemove() {}

public void ejbActivate(){}

public void ejbPassivate(){}

}

  1. Tạo Helper Classes

package cmt;

public class EnrollmentInfo implements java.io.Serializable {

public int itemId = 0;

public int studentId = 0;

public String courseId = null;

public EnrollmentInfo (int itemId, int studentId, String courseId) {

this.itemId = itemId;

this.studentId = studentId;

this.courseId = courseId;

}

public int getItemId(){

return itemId;

}

public int getStudentId(){

return studentId;

}

public String getCourseId(){

return courseId;

}

}

package cmt;

public class InsufficientRoomException extends Exception {

public InsufficientRoomException() {

super();

}

public InsufficientRoomException(Exception e) {

super(e.toString());

}

public InsufficientRoomException(String s) {

super(s);

}

}

  1. Đóng gói thành file jar
    1. Tạo file ejb-jar.xml

<?xml version=“1.0”?>

<!DOCTYPE ejb-jar PUBLIC

‘-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN’

http://java.sun.com/dtd/ejb-jar_2_0.dtd&#8217;>

<ejb-jar>

<enterprise-beans>

<session>

<ejb-name>EnrollmentCart</ejb-name>

<home>cmt.EnrollmentCartHome</home>

<remote>cmt.EnrollmentCart</remote>

<ejb-class>cmt.EnrollmentCartEJB</ejb-class>

<session-type>Stateful</session-type>

<transaction-type>Container</transaction-type>

<resource-env-ref>

<resource-env-ref-name>jdbc/studentsDB</resource-env-ref-name>

<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>

</resource-env-ref>

</session>

</enterprise-beans>

<assembly-descriptor>

<container-transaction>

<description>All methods must be make transaction</description>

<method>

<ejb-name>EnrollmentCart</ejb-name>

<method-name>*</method-name>

</method>

<trans-attribute>Required</trans-attribute>

</container-transaction>

</assembly-descriptor>

</ejb-jar>

    1. Tạo file jboss.xml

<?xml version=“1.0” encoding=“UTF-8”?>

<jboss>

<enterprise-beans>

<session>

<ejb-name>EnrollmentCart</ejb-name>

<jndi-name>cmt/EnrollmentCartCMT</jndi-name>

<resource-env-ref>

<resource-env-ref-name>jdbc/studentsDB</resource-env-ref-name>

<jndi-name>java:/Students_DSN</jndi-name>

</resource-env-ref>

</session>

</enterprise-beans>

<container-configurations>

<container-configuration>

<container-name>Standard Stateful SessionBean</container-name>

<container-cache-conf>

<cache-policy>

org.jboss.ejb.plugins.LRUStatefulContextCachePolicy

</cache-policy>

<cache-policy-conf>

<max-capacity>10</max-capacity>

</cache-policy-conf>

</container-cache-conf>

</container-configuration>

</container-configurations>

</jboss>

    1. Tạo file build.bat

javac -d . *.java

pause

Chạy file này để biên dịch. Đảm bảo mọi thứ phải OK.

    1. Tạo file makejar.bat

jar cvf EJB_CMT.jar cmt/*.class META-INF/*.xml

pause

Tạo file này để tạo file jar, nếu OK ta được file EJB_CMT.jar

  1. Triển khai
    1. Tạo database:

CREATE TABLE COURSES
(
COURSE_ID      VARCHAR(10) NOT NULL,
COURSE_NAME   VARCHAR(64),
FEE           NUMERIC(18),
MAX_LIMIT     INT,
CURR_ENROLL   INT
);

CREATE TABLE STUDENTS
(
STUDENT_ID VARCHAR(12) NOT NULL,
FIRST_NAME VARCHAR(15) ,
LAST_NAME VARCHAR(15) ,
ADDRESS VARCHAR(164),
EMAIL_ADDRESS VARCHAR(64)
);

CREATE TABLE ENROLLMENTS
(
ENROLLMENT_ID VARCHAR(64),
STUDENT_ID VARCHAR(64),
COURSE_ID VARCHAR(64)
) ;

    1. Tạo 1 ODBC Data source với tên là students

    1. Tạo file (hoặc sửa file) mssql-ds.xml trong thư mục %JBOSS_HOME%\server\default\deploy\

<?xml version=“1.0” encoding=“UTF-8”?>

<!– Các Datasource khac neu co nam o day –>

<datasources>

<local-tx-datasource>

<jndi-name>Students_DSN</jndi-name>

<connection-url>jdbc:odbc:students</connection-url>

<driver-class>sun.jdbc.odbc.JdbcOdbcDriver</driver-class>

<user-name>sa</user-name>

<password></password>

<metadata>

<type-mapping>MS SQLSERVER2000</type-mapping>

</metadata>

</local-tx-datasource>

</datasources>

    1. Triển khai EJB_CMT.jar bằng cách copy file EJB_CMT.jar vào thư mục %JBOSS_HOME%\server\default\deploy\

Kết quả:

13:30:14,644 INFO [ProxyFactory] Bound EJB Home ‘EnrollmentCart’ to jndi ‘cmt/EnrollmentCartCMT’

13:30:14,660 INFO [EJBDeployer] Deployed: file:/C:/javaSoft/jboss-4.2.2.GA/server/default/deploy/EJB_CMT.jar

  1. Thiết kế client
    1. Tạo thư mục client, copy thư mục cmt vào đó, sau đó xóa bỏ file EnrollmentCartEJB.class
    2. Tạo file Client.java có nội dung sau

import java.util.Collection;

import java.util.Iterator;

import javax.naming.Context;

import javax.naming.InitialContext;

import cmt.EnrollmentCart;

import cmt.EnrollmentCartHome;

import cmt.EnrollmentInfo;

public class Client

{

public static void main(String[] argv){

System.out.print(“Demonstration the use of CMT\n”);

try{

//thiet lap bien moi truong System.setProperty(“java.naming.factory.initial”,

“org.jnp.interfaces.NamingContextFactory”);

System.setProperty( “java.naming.provider.url”, “localhost:1099” );

System.setProperty( “java.naming.factory.url.pkgs”, “org.jboss.naming” );

Context initialContext = new InitialContext();

Object object = initialContext.lookup(“cmt/EnrollmentCartCMT”);

EnrollmentCartHome enrollmentCartHome = (EnrollmentCartHome)

javax.rmi.PortableRemoteObject.narrow(object, EnrollmentCartHome.class);

EnrollmentCart enrollmentCart = (EnrollmentCart)

enrollmentCartHome.create();

// Add enrollment courses

enrollmentCart.addEnrollment(new EnrollmentInfo(1, 15, “CS201”));

enrollmentCart.addEnrollment(new EnrollmentInfo(2, 15, “CS205”));

enrollmentCart.addEnrollment(new EnrollmentInfo(3, 15, “CS231”));

// register the courses

enrollmentCart.register();

print(“Following courses are registered successfully:”);

Collection coll = enrollmentCart.getEnrollments();

for (Iterator i = coll.iterator(); i.hasNext();){

EnrollmentInfo enroll = (EnrollmentInfo) i.next();

print(“Course id: “ + enroll.getCourseId());

}

enrollmentCart.remove();

}

catch ( Exception e){

print(“Enrolled courses failed to register.\n”);

e.printStackTrace();

}

}

static void print(String s){

System.out.println(s);

}

}

    1. Tạo file build.bat

javac -d . *.java

pause

    1. Tạo file run.bat

java Client

pause

  1. Thử nghiệm
    1. Chạy file run.bat. Kết quả sẽ cho như sau

Demonstration the use of CMT

Following courses are registered successfully:

Course id: CS201

Course id: CS205

Course id: CS231

CHÚC THÀNH CÔNG!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: