Thursday, August 12, 2010

JDBC 2.0 and JDBC 4.0 features

1. Scrollable ResultSets

It's a very common procedure in JDBC to create a Connection object (or obtain an existing one) and use it to create aStatement. The Statement, being fed an SQL SELECT, returns a ResultSet. The ResultSet is then fed through a while loop (not unlike an Iterator) until the ResultSet says it's empty, with the body of the loop extracting one column at a time in left-to-right order.

This whole operation is so common that is has become almost sacred: it's done that way simply because that's the way it's done. Alas, it's completely unnecessary.

Introducing the scrollable ResultSet

Many developers are unaware of the fact that JDBC has been considerably enhanced over the years, even though those enhancements are reflected in new version numbers and releases. The first major enhancement, JDBC 2.0, occurred around the time of JDK 1.2. As of this writing, JDBC stands at version 4.0.

One of the interesting (though frequently ignored) enhancements to JDBC 2.0 is the ability to "scroll" through the ResultSet, meaning we can go forward or backward, or even both, as need dictates. Doing so requires a bit of forward-thinking, however — the JDBC call must indicate that it wants a scrollable ResultSet at the time the Statement is created.

Verifying ResultSet type

If you suspect a driver may not actually support scrollable ResultSets, despite what it says in theDatabaseMetaData, you can verify the ResultSet type by calling getType(). Of course, if you're that paranoid, you might not trust the return value of getType(), either. Suffice it to say, if getType() lies about theResultSet returned, they really are out to get you.

If the underlying JDBC driver supports scrolling, a scrollableResultSet will be returned from that Statement, but it's best to figure out if the driver supports scrollability before asking for it. You can ask about scrolling via the DatabaseMetaData object, which can be obtained from any Connection, as described previously.

Once you have a DatabaseMetaData object, a call togetJDBCMajorVersion() will determine whether the driver supports at least the JDBC 2.0 specification. Of course, a driver could lie about its level of support for a given specification, so to play it particularly safe, call the supportsResultSetType() method with the desired ResultSet type. (It's a constant on the ResultSetclass; we'll talk about the values of each in just a second.)


Listing 1. Can you scroll?

int JDBCVersion = dbmd.getJDBCMajorVersion();

boolean srs = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE);

if (JDBCVersion > 2 || srs == true)

{

// scroll, baby, scroll!

}

Requesting a scrollable ResultSet

Assuming your driver says yes (if it doesn't, you need a new driver or database), you can request a scrollable ResultSet by passing two parameters to the Connection.createStatement() call, shown in Listing 2:


Listing2. I want to scroll!

Statement stmt = con.createStatement(

ResultSet.TYPE_SCROLL_INSENSITIVE,

ResultSet.CONCUR_READ_ONLY);

ResultSet scrollingRS = stmt.executeQuery("SELECT * FROM whatever");

You have to be particularly careful when calling createStatement() because its first and second parameters are both ints. (Curse the fact that we didn't get enumerated types until Java 5!) Any int value (including the wrong constant value) will work withcreateStatement().

The first parameter, indicating the "scrollability" desired in the ResultSet, can be one of three accepted values:

  • ResultSet.TYPE_FORWARD_ONLY: This is the default, firehose-style cursor that we know and love.
  • ResultSet.TYPE_SCROLL_INSENSITIVE: This ResultSet enables backward iteration as well as forward, but if the data in the database changes, the ResultSet won't reflect it. This scrollable ResultSet is probably the most commonly desired type.
  • ResultSet.TYPE_SCROLL_SENSITIVE: The ResultSet created will not only allow for bidirectional iteration, but will also give a "live" view of the data in the database as it changes.

The second parameter is discussed in the next tip, so hang on.

Directional scrolling

Once you've obtained a ResultSet from the Statement, scrolling backward through it is just a matter of calling previous(), which goes backward a row instead of forward, as next() would. Or you could call first() to go back to the beginning of theResultSet, or call last() to go to the end of the ResultSet, or ... well, you get the idea.

The relative() and absolute() methods can also be helpful: the first moves the specified number of rows (forward if the value is positive, backward if the value is negative), and the latter moves to the specified row in the ResultSet regardless of where the cursor is. Of course, the current row number is available via getRow().

If you plan on doing a lot of scrolling in a particular direction, you can help the ResultSet by specifying that direction, by callingsetFetchDirection(). (A ResultSet will work regardless of its scrolling direction but knowing beforehand allows it to optimize its data retrieval.)


2. Updateable ResultSets

JDBC doesn't just support bidirectional ResultSets, it also supports in-place updates to ResultSets. This means that rather than create a new SQL statement to change the values currently stored in the database, you can just modify the value held inside the ResultSet, and it will be automatically sent to the database for that column of that row.

Asking for an updateable ResultSet is similar to the process involved in asking for a scrollable ResultSet. In fact, it's where you'll use the second parameter to createStatement(). Instead of specifying ResultSet.CONCUR_READ_ONLY for the second parameter, send ResultSet.CONCUR_UPDATEABLE, as shown in Listing 3:


Listing 3. I'd like an updateable ResultSet, please

Statement stmt = con.createStatement(

ResultSet.TYPE_SCROLL_INSENSITIVE,

ResultSet.CONCUR_UPDATEABLE);

ResultSet scrollingRS = stmt.executeQuery("SELECT * FROM whatever");

Assuming your driver supports updateable cursors (that's another feature of the JDBC 2.0 specification, which most "real-world" databases will support), you can update any given value in a ResultSet by navigating to that row and calling one of theupdate...() methods on it (shown in Listing 6). Like the get...() methods on ResultSet, update...() is overloaded for the actual column type in the ResultSet. So to change the floating-point column named "PRICE", call updateFloat("PRICE"). Doing so only updates the value in the ResultSet, however. To push the value to the database backing it, call updateRow(). If the user changes his or her mind about changing the price, a call to cancelRowUpdates() will kill all pending updates.


Listing4. A better way

Statement stmt = con.createStatement(

ResultSet.TYPE_SCROLL_INSENSITIVE,

ResultSet.CONCUR_UPDATEABLE);

ResultSet scrollingRS =

stmt.executeQuery("SELECT * FROM lineitem WHERE id=1");

scrollingRS.first();

scrollingRS.udpateFloat("PRICE", 121.45f);

// ...

if (userSaidOK)

scrollingRS.updateRow();

else

scrollingRS.cancelRowUpdates();

JDBC 2.0 supports more than just updates. If the user wants to add a completely new row, rather than create a new Statementand execute an INSERT, just call moveToInsertRow(), call update...() for each column, then call insertRow() to complete the work. If a column value isn't specified, it's assumed to be an SQL NULL (which might trigger an SQLException if the database schema doesn't allow NULLs for that column).

Naturally, if the ResultSet supports updating a row, it must also support deleting one, via deleteRow().

Oh, and before I forget, all of this scrollability and updateability applies equally to PreparedStatement (by passing those parameters to the prepareStatement() method), which is infinitely preferable to a regular Statement due to the constant danger of SQL injection attacks.


3. Rowsets

If all this functionality has been in JDBC for the better part of a decade, why are most developers still stuck on forward-scrollingResultSets and disconnected access?

The main culprit is scalability. Keeping database connections to a minimum is key to supporting the massive numbers of users that the Internet can bring to a company's web site. Because scrolling and/or updating ResultSets usually requires an open network connection, many developers will not (or cannot) use them.

Fortunately, JDBC 3.0 introduced an alternative that lets you do many of the same things you would with a ResultSet, without necessarily needing to keep the database connection open.

In concept, a Rowset is essentially a ResultSet, but one which allows for either a connected or disconnected model. All you need to do is create a Rowset, point it at a ResultSet, and when it's done populating itself, use it as you would a ResultSet, shown in Listing 5:


Listing 5. Rowset replaces ResultSet

Statement stmt = con.createStatement(

ResultSet.TYPE_SCROLL_INSENSITIVE,

ResultSet.CONCUR_UPDATEABLE);

ResultSet scrollingRS = stmt.executeQuery("SELECT * FROM whatever");

if (wantsConnected)

JdbcRowSet rs = new JdbcRowSet(scrollingRS); // connected

else

CachedRowSet crs = new CachedRowSet(scrollingRS); disconnected

JDBC comes with five "implementations" (meaning extended interfaces) of the Rowset interface. JdbcRowSet is a connectedRowset implementation; the remaining four are disconnected:

  • CachedRowSet is just a disconnected Rowset.
  • WebRowSet is a subclass of CachedRowSet that knows how to transform its results to XML and back again.
  • JoinRowSet is a WebRowSet that also knows how to form the equivalent of an SQL JOIN without having to connect back to the database.
  • FilteredRowSet is a WebRowSet that also knows how to further filter the data handed back without having to connect back to the database.

Rowsets are full JavaBeans, meaning they support listener-style events, so any modifications to the Rowset can be caught, examined, and acted upon, if desired. In fact, Rowset can even manage the complete act against the database if it has itsUsername, Password, URL, and DatasourceName properties set (which means it will create a connection usingDriverManager.getConnection()) or its Datasource property set (which was probably obtained via JNDI). You would then specify the SQL to execute in the Command property, call execute(), and start working with the results — no further work required.

Rowset implementations are generally provided by the JDBC driver, so the actual name and/or package will depend on what JDBC driver you use. Rowset implementations have been a part of the standard distribution since Java 5, so you should be able to just create a ...RowsetImpl() and go. (In the unlikely event that your driver doesn't provide one, Sun offers a reference implementation; see Resources for the link.)


4. Batch updates

Despite their usefulness, Rowsets sometimes just don't meet all your needs, and you may need to fall back to writing straight SQL statements. In those situations, particularly when you're facing a slew of work, you might appreciate the ability to do batch updates, executing more than one SQL statement against the database as part of one network round-trip.

To determine whether the JDBC driver supports batch updates, a quick call to theDatabaseMetaData.supportsBatchUpdates() yields a boolean telling the story. Assuming batch updates are supported (indicated by anything non-SELECT), queue one up and release it in a blast, like in Listing 6:


Listing 6. Let the database have it!

conn.setAutoCommit(false);

PreparedStatement pstmt = conn.prepareStatement("INSERT INTO lineitems VALUES(?,?,?,?)");

pstmt.setInt(1, 1);

pstmt.setString(2, "52919-49278");

pstmt.setFloat(3, 49.99);

pstmt.setBoolean(4, true);

pstmt.addBatch();

// rinse, lather, repeat

int[] updateCount = pstmt.executeBatch();

conn.commit();

conn.setAutoCommit(true);

The call to setAutoCommit() is necessary because by default, the driver will try to commit every statement that it is fed. Other than that, the rest of the code is pretty straightforward: do the usual SQL thing with the Statement or PreparedStatement, but instead of calling execute(), invoke executeBatch(), which queues the call instead of sending it right away.

When the whole mess of statements is ready to go, fire them all at the database with executeBatch(), which returns an array of integer values, each of which holds the same result as if executeUpdate() had been used.

In the event that a statement in the batch fails, if the driver doesn't support batch updates, or if a statement in the batch returns aResultSet, the driver will throw a BatchUpdateException. In some cases, the driver may have tried to continue executing statements after an exception was thrown. The JDBC specification doesn't mandate particular behavior, so you are advised to experiment with your driver beforehand, so that you know exactly how it behaves. (But of course you'll be running unit tests, so you'll discover the error long before it becomes a problem, right?)

Wednesday, August 4, 2010

Asynchronous support in Servlet 3.0 spec

One of the significant enhancements made in JSR 315: Java Servlet 3.0, is support for asynchronous processing. With this support, a servlet no longer has to wait for a response from a resource such as a database before its thread can continue processing, that is, the thread is not blocked. Previous to Servlet 3.0, asynchronous support in the Java EE web container was provided in a proprietary way — either through APIs built on top of the Servlet 2.5 API or through non-Servlet APIs or implementations.


In modern web applications there are times when you need to asynchronously handle some part of the request, so that the web container can continue serving other requests in a seamless fashion. One example is a chat room application. In this type of application you want to enable long-lived client connections with a servlet. You don't want a server thread to be blocked for a long period of time serving a request from a single client. You want the servlet to process a request from the client and then free up the server thread as quickly as possible for other work. In other words, you want the request to be processed and a response generated asynchronously.


With the upcoming release of the Servlet 3.0 specification, standard asynchronous support has been added to the Servlet API. This Tech Tip introduces the asynchronous support that has been added to the Servlet API in Java Servlet 3.0 technology. It also includes a sample application that demonstrates those features.


Asynchronous Support Features


The primary features of the asynchronous support in Servlet 3.0 are as follows.


Annotation Attributes


Servlet 3.0 introduces the use of annotations as an alternative to deployment descriptors for servlet-related configuration in a web application. Two of these annotations are @WebServlet, which defines a servlet, and @WebFilter, which defines a servlet filter. Both of these annotations include an attribute, asyncSupported. Setting the asyncSupported attribute to true, declares that the servlet or servlet filter supports asynchronous processing. For example, the following annotation defines a servlet in a web application and declares that the servlet supports asynchronous processing:


@WebServlet(url="/foo" asyncSupported=true)

The asyncSupported attribute is needed to differentiate code written for synchronous processing from that written for use in an asynchronous context. In fact, for an application to use the asynchronous feature, the entire request processing chain must have the have this attribute set either through the annotation or in its deployment descriptor. An IllegalStateException will be thrown if an application tries to start an asynchronous operation and there is a servlet or servlet filter in the request processing chain that does not support asynchronous processing.


Servlet Request Methods


The support for asynchronous processing also includes new ServletRequest methods, such as startAsync(servletRequest, servletResponse), startAsync(), and getAsyncContext(). After you set the asyncSupported attribute in the request processing chain to support asynchronous processing, you call either the startAsync(servletRequest, servletResponse) or startAsync()method to make an asynchronous request. Here, for example, is a call that makes an asynchronous request:


AsyncContext aCtx = req.startAsync(req, res);

The difference between the two startAsync method signatures is that the startAsync() method implicitly uses the original request and response, while the startAsync(servletRequest, servletResponse) method uses the request and response objects passed in the method call. The request and response passed in the call can be wrapped by filters or other servlets earlier in the request processing chain. Notice that the startAsync method returns an AsyncContext object — see AsyncContext Class for more details. The AsyncContext object is initialized appropriately with the request and response objects depending on the method used. You must exercise caution when wrapping the response and calling the no arguments signature of the startAsync() method. You could lose the data if any of data is written to the wrapped response and not flushed to the underlying response stream.


There are a few more methods in the ServletRequest class that are part of the support for asynchronous processing. These include isAsyncSupported() and isAsyncStarted() You can use these convenience methods in an application to determine if asynchronous operations are supported or started on a request.


AsyncContext Class


The AsyncContext class is a new class in Servlet 3.0 that provides the execution context for an asynchronous operation. The class provides a variety of methods that you can use to get access to the underlying request and response objects. For example, you can use the AsyncContext.dispatch(), AsyncContext.dispatch(path), or AsyncContext.dispatch(servletContext, path) method to dispatch the request to the container. Using any of the dispatch methods, enables the processing to return to the container after the asynchronous operation that was started on the ServletRequest is completed — for instance, after waiting for a call to a web service to return. These methods dispatch the request back to the container so you can use frameworks such as JavaServer Pages (JSP) to generate the response.


The dispatch() method, that is, the method with no arguments, forwards the request back to the original URL. Also, if a call toAsyncContext.dispatch or RequestDispatcher.forward occurs after an asynchronous context has been initialized, the dispatch()method forwards the request to the path for the AsyncContext or RequestDispatcher-related requests.


The dispatch(path) method forwards the request to the path relative to the context of the request.


The dispatch(ServletContext, path) method forwards the request to the path relative to the specified context. For example, here is a call that forwards the request back to the container so that the JSP framework can generate the response.


ctx.dispatch("/render.jsp");

Another AsyncContext method, complete(), completes the asynchronous operation that was started on the request that was used to initialize this AsyncContext object. It closes the response that was used to initialize this AsyncContext object. You can call this method, for example, when the response generated by the asynchronous operation is complete. The container can also implicitly call this method if the application dispatches the request back to the container using the forward method with no subsequentstartAsync call on the request.


Asynchronous Listener Class


Servlet 3.0 also adds a new listener class for asynchronous processing, AsyncListener. You can use this class in an application to get notified when asynchronous processing is completed, if a timeout has occurred, an error has occurred, or a subsequent call to startAsync has occurred. The following code snippet creates a new AsyncListener object and uses it to get notified when an asynchronous processing operation is completed .


AsyncContext ac = req.startAsync();

req.addAsyncListener(new AsyncListener() {

public void onComplete(AsyncEvent event) throws IOException {

...

}

...

}

Notice that the parameter passed to the onComplete method is an AsyncEvent object. The AsyncEvent class is another new class provided as part of the Servlet 3.0 support for asynchronous processing. It represents an event that gets fired when the asynchronous operation initiated on a ServletRequest has completed, timed out, or produced an error.


A Simple Application That Uses the Asynchronous Support in Servlet 3.0


Now that you've seen the key features in the Servlet 3.0 support for asynchronous processing, let's look at a more complete example. The following shows the code for a simple web application. In the application, a servlet makes an asynchronous request to a web service, waits for the call to return, and then dispatches the request back to the container to render the result using JSP. Note that the complete code for servlet is not shown.


@WebServlet("/foo" asyncSupported=true)

public class MyServlet extends HttpServlet {

public void doGet(HttpServletRequest req, HttpServletResponse res) {

...

AsyncContext aCtx = request.startAsync(req, res);

ScheduledThreadPoolExecutor executor = new ThreadPoolExecutor(10);

executor.execute(new AsyncWebService(aCtx));

}

}


public class AsyncWebService implements Runnable {

AsyncContext ctx;

public AsyncWebService(AsyncContext ctx) {

this.ctx = ctx;

}

public void run() {

// Invoke web service and save result in request attribute

// Dispatch the request to render the result to a JSP.

ctx.dispatch("/render.jsp");

}

}

Tuesday, July 27, 2010

Client code accessing a webservice

Soap Based webservice (Jax-ws) can be accessed in two ways. one is getting the wsdl file of the service and generating all the necessary artifacts using tool like wsgen. other way is accessing a webservice using online wsdl file locaiton and creating a service from it. following code shows how to access a webservice without any need of wsdl file at the compilation time.

code from my prototype project. This takes xml file as input and transfers the xml to the webserice.

URL wsdlLocation = new URL("http://10.144.135.225:9080/CimrsWeb/ReportWebService?wsdl");
QName serviceQName =
new QName("http://webservices.cimrs.dss.gov/", "ReportWebService");
QName portQName = new QName("http://webservices.cimrs.dss.gov/", "ReportWebPort");
Service service = Service.create(wsdlLocation, serviceQName);

Dispatch dispatch =
service.createDispatch(portQName, Source.class,
Service.Mode.PAYLOAD);
InputStream requestStream= new FileInputStream("C://input.xml");
Source request1 = new StreamSource(requestStream);

Source response1 = dispatch.invoke(request1);

Transformer copier = TransformerFactory.newInstance().newTransformer();

copier.transform(response1, new StreamResult(System.out));

Wednesday, July 14, 2010

Jasper Reports with iReport Editor.


Reports Creation made simple in Java.

The report creation process has three main steps:

1. Creating a data source or a database connection used to fill the report.
2. Designing the report, including the layout of its elements and parameters to represent the data.
3. Runing the report, which includes compiling the JRXML source file in a Jasper file and filling in the data for export or onscreen display.


When you design and preview a report in iReport, iReport produces a Jasper file. This file is all you need in your Java application to generate and display the report (in addition to JasperReports, of course).

The report execution is performed by the JasperReports library, so you have to include all the required jars in your application. Which jars? If you do not have a problem shipping a lot of jars, you can include all the jars provided in JasperReports. However JasperReports includes many jars that you may not need, such as ones to create barcodes, the ones used to handle XML files (as long as you don't use an XML datasource), and ant.jar and servlet.jar, which are provided to compile the source code. Other optional jars are hsqldb.jar that is shipped to run the sample database and bsh-2.0b4.jar used to compile and run the reports using Beanshell. Other jars may be already included in your environment, for example Spring, Apache Commons Logging, and Mondrian (an OLAP database server), among others.

Here is the complete list of jars shipped with JasperReports 3.6.0 (the list is subject to change in future versions):

ant-1.7.1.jar
antlr-2.7.5.jar
barbecue-1.5-beta1.jar
barcode4j-2.0.jar
batik-anim.jar
batik-awt-util.jar
batik-bridge.jar
batik-css.jar
batik-dom.jar
batik-ext.jar
batik-gvt.jar
batik-parser.jar
batik-script.jar
batik-svg-dom.jar
batik-svggen.jar
batik-util.jar
batik-xml.jar
bcel-5.2.jar
bsh-2.0b4.jar
commons-beanutils-1.8.0.jar
commons-collections-2.1.1.jar
commons-digester-1.7.jar
commons-javaflow-20060411.jar
commons-logging-1.0.4.jar
groovy-all-1.5.5.jar
hibernate3.jar
hsqldb-1.8.0-10.jar
iText-2.1.0.jar
jasperreports-3.6.0.jar
jaxen-1.1.1.jar
jcommon-1.0.15.jar
jdt-compiler-3.1.1.jar
jfreechart-1.0.12.jar
jpa.jar
jxl-2.6.jar
log4j-1.2.15.jar
mondrian-3.1.1.12687.jar
png-encoder-1.5.jar
poi-3.2-FINAL-20081019.jar
rhino-1.7R1.jar
saaj-api-1.3.jar
servlet.jar
spring-beans-2.5.5.jar
spring-core-2.5.5.jar
xalan-2.6.0.jar
xercesImpl-2.7.0.jar
xml-apis-ext.jar
xml-apis.jar

Here is a simple application to create a PDF from a Jasper file using an empty data source. An empty data source is a data source that by default has a single record and for which you can define any field name to use in the report, but its value will always be null. It is a perfect data source to test a very simple report displaying just the label "Hello World!" For real applications, you will probably use a JDBC connection, a collection of JavaBeans, or a Hibernate session to provide data for the report. But for the aim of this tutorial, the empty data source is good enough.

import net.sf.jasperreports.engine.*; 
import net.sf.jasperreports.engine.export.*; 
import java.util.*;    
public class JasperTest {     
 public static void main(String[] args) {      
 String fileName = "test.jasper";    
 String outFileName = "test.pdf";   
 HashMap hm = new HashMap();     
    try {     
        // Fill the report using an empty data source  
           JasperPrint print = JasperFillManager.fillReport(fileName, hm, new JREmptyDataSource()); 
        // Create a PDF exporter    
         JRExporter exporter = new JRPdfExporter();
       // Configure the exporter (set output file name and print object)
          exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, outFileName);
          exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);       
       // Export the PDF file   
         exporter.exportReport();                     
 } catch (JRException e) {   
          e.printStackTrace();  
           System.exit(1);         
} catch (Exception e) {   
          e.printStackTrace(); 
            System.exit(1);  
       }     } }    

The most important line of code in this example is line 13. The class JasperFillManager provides several static methods to fill a Jasper file, using a data source, a connection, or even nothing. The result of the call to the method fillReport() is the special JasperPrint object which contains an in-memory representation of the report. This object can be previewed by using the JasperReports Viewer, a convenient Swing component to display the report on screen (it's the same component used by the iReport preview). As in this example, the JasperPrint object can also be passed to an exporter to generate a final document in a specific format.

On line 16, the JRPdfExporter is instantiated and later configured by setting the JasperPrint and the output file. The exportReport() method of the exporter does the rest, creating the file test.pdf.

In this sample we stored the result in a file. In other situations, such as in web applications, it is much more convenient to send the exported bytes directly to the browser. This can be done by setting the OUTPUT_STREAM parameter of the exporter to the output stream of the web application. There are many other export options, some of them common to all export formats (such as the range of pages to export), others specific of the exporter implementation.

Friday, July 2, 2010

Concurrency Control Issue- "Optimistic Update Access Intent"

In one of our project we used EJB’s and It is not working when migrated from Websphere Server 5.1 to Websphere server 7.0.

It started throwing deadlock exceptions when multiple users clicks the save button at the same time.

This is happening because two sessions going to the same functions and the function is under Transaction Attribute “Required”, which means the method should be under transactional context.

If a calling method is under transactional context then this method follows the same transaction, if is not under transactional context than websphere container intiates a new transaction. Here the problem is not with the transactional attribute. The problem is with “Concurrency Control” Issue. Both sessions trying to update the same table then they are getting locks on the table and after updating the tables they have to load the case from the database. So both are trying to read the database and while reading they are locking the table’s again (which is not required to lock the table while reading—we wanted a dirty read). This is happening because by default websphere server uses “Pessimistic Update” Access Intent on all Entitiy Beans. Pessimistic Update locks the table even for reading also by issuing “SELECT…..FOR UPDATE” Statement.

Changing Access Intent from “Pessimistic Update” to “Optimistic Update” resolved the issue. In Optimistic Update it doesn’t lock on table for reading and it issues simple “SELECT” statement.

Finally the deadlock issue is Resolved. Finding the issue was tough than the solution.

Here goes log of Dead Lock stack Trace.

*** MODULE NAME:(JDBC Thin Client) 2010-06-24 13:09:17.861

*** SERVICE NAME:(SYS$USERS) 2010-06-24 13:09:17.861

*** SESSION ID:(901.1366) 2010-06-24 13:09:17.861

DEADLOCK DETECTED ( ORA-00060 )

[Transaction Deadlock]

The following deadlock is not an ORACLE error. It is a

deadlock due to user error in the design of an application

or from issuing incorrect ad-hoc SQL. The following

information may aid in determining the deadlock:

Deadlock graph:

---------Blocker(s)-------- ---------Waiter(s)---------

Resource Name process session holds waits process session holds waits

TX-00060012-0003e77d 475 901 X 401 2127 X

TX-0002000f-000521da 401 2127 X 475 901 X

session 901: DID 0001-01DB-00000026 session 2127: DID 0001-0191-0000001C

session 2127: DID 0001-0191-0000001C session 901: DID 0001-01DB-00000026

Rows waited on:

Session 2127: obj - rowid = 000139A5 - AAATmlAAQAAAacCAAf

(dictionary objn - 80293, file - 16, block - 108290, slot - 31)

Session 901: obj - rowid = 000139A5 - AAATmlAAQAAAbBDAA3

(dictionary objn - 80293, file - 16, block - 110659, slot - 55)

Information on the OTHER waiting sessions:

Session 2127:

pid=401 serial=1922 audsid=10835401 user: 7626/ASAPS_WEB

O/S info: user: wasadm, term: unknown, ospid: 1234, machine: surya7.dss.state.

va.us

program: JDBC Thin Client

application name: JDBC Thin Client, hash value=2546894660

Current SQL Statement:

SELECT T1.AS_UAI_QUESTION_ID, T1.QUESTION_TXT, T1.QUESTION_DESC, T1.UAI_LOCATOR, T1.QUESTION_ORDER, T1.LST_UPDT_ID, T1.LST_UPDT_DT FROM OASIS.TAS_UAI_QUESTI

ON T1 WHERE T1.AS_UAI_QUESTION_ID = :1 FOR UPDATE

End of information on OTHER waiting sessions.

Current SQL statement for this session:

SELECT T1.AS_UAI_QUESTION_ID, T1.QUESTION_TXT, T1.QUESTION_DESC, T1.UAI_LOCATOR, T1.QUESTION_ORDER, T1.LST_UPDT_ID, T1.LST_UPDT_DT FROM OASIS.TAS_UAI_QUESTION

T1 WHERE T1.AS_UAI_QUESTION_ID = :1 FOR UPDATE