22 Aralık 2010 Çarşamba

using blob field with jpa and web services

In the project, client side has to store local machine specific data in the cenral database and this field has to be binary large object (blob).. Jpa with hibernate is used as orm tool..Unfortunately, according to http://opensource.atlassian.com/projects/hibernate/browse/JPA-8 jpa does not support java.sql.Blob.. Indeed, the following error shows up when i tried to do so:
// bean
import java.sql.Blob;
import javax.persistence.Lob;

class MyClass{
@Lob
@Column(name = "FLD_BLOB")
private Blob myBlob;
...
}

// the error when deployed on Glassfish (jaxws is used for web services)
javax.xml.ws.WebServiceException: Unable to create JAXBContext ...
Caused by: java.security.PrivilegedActionException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
java.sql.Blob is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at java.sql.Blob
at public java.sql.Blob
...
java.sql.Blob does not have a no-arg default constructor.
...
java.sql.Blob is an interface, and JAXB can't handle interfaces.
...

So, use byte [] instead of java.sql.Blob

Web service using the bean with blob field is succesfully deployed and in the wsdl, the blob field is like this:
< xs:element name= " myBlob " type= " xs:base64Binary " minoccurs= " 0 " >
Moreover, when client side stubs are generated, the field is again generated as byte []..

Testing the blob field:
I used the code at http://www.java-tips.org/java-se-tips/java.io/reading-a-file-into-a-byte-array.html in order to prepare test data from a file and the following lines to write back the read bytes into a file to test correctness:

FileOutputStream fos = new FileOutputStream( "blobDataReadFromDB.png");
fos.write(myBean.getMyBlob());

The test data is a 5.4 MB-mp3.

Two test cases are considered.
In the first test case, the web services are treated as applications and tested without deployment. The blob field is successfully persisted and retrieved from database in this case..
In the second test case, web services are deployed and then tested.. The blob data is persisted successfully, but, the following error shows up when trying to retreive the data: (the underlying database is postgresql..)
ERROR org.hibernate.util.JDBCExceptionReporter - Large Objects may not be used in auto-commit mode.
...
sun-org.hibernate.exception.GenericJDBCException: could not execute query at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
....
Caused by: org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.
at org.postgresql.largeobject.LargeObjectManager.open(LargeObjectManager.java:200)

Here is someone in a similar situation: https://forum.hibernate.org/viewtopic.php?f=1&t=994742&start=0 The following answer in this link, worked for me:

You might need to put your DB operations into a transaction:
session.beginTransaction();
...
session.getTransaction().commit();

Normally, retrieve operations do not require a transaction since they leave the database unchanged.. You only use transactions for create, update and delete operations since they change database state.. However, retrieval of blob field require transaction as well, maybe due to paging..

I also used and tested the blob field through a bpel process.. Again, persistence and retrieval is successful..

Hiç yorum yok:

Yorum Gönder