views:

878

answers:

4

Hello,

I would like to know how can I access the file system from an EJB 3 bean?

I searched the Internet on the subject and haven't found a good answer.

Some suggest using the java.io/java.nio even though the specification prohibits this usage. Most application servers seem to allow the access to this API anyway.

Another idea would be to use an JCA connector to access the file system or a LDAP directory.

What I want to do this to avoid the use of BLOB in the database when a simple file would be a much better solution in terms of performance and used resources.

How would you solve this problem?

+2  A: 

The reason that you are disallowed from file system access in EJBs is that you have no control over how your application runs within a (Java EE) Container. For example, your application may be run across a cluster of servers, in which case saving some object to a directory on one server is likely to be of little use. (You may have a network file-system of course, so the restriction may not apply).

One option may be to use the JNDI implementation which comes with your Container. You will likely be able to save a raw byte[] array at some JNDI location, so you could always save down the serialized form of the object:

ByteArrayOutputStream baos= new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(myObj);

//Now save into JNDI
new InitialContext().bind("path/to/myobject", baos.toByteArray());

This can be looked up later and re-converted into your object:

byte[] bs = (byte[]) new InitialContext().lookup("path/to/myobject");
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bs));
MyObj myObj = (MyObj) ois.readObject();

Alternatively you could use the java.beans persistent XML (i.e. XMLDecoder, XMLEncoder) to encode your instance as an XML string an save that into JNDI.

oxbow_lakes
+2  A: 

If you know you will never cluster your application (or that you will be able to network-map the drive) then just use java.io.*.

Be sure to introduce proper configuration regarding the root location of your files storage.

flybywire
+1 This answer is just *common sense*. If the file is filled by another program (that doesn't conform EJB) there is no faster and *clear* way to do it.
ATorras
By writing an application that does not adhere to the Java EE spec, you cannot be sure that it is portable and maintainable. For example, in 12 months time you may have left this project behind with a large surprise for the poor person given the task of clustering your app. Or porting it to a different container.
oxbow_lakes
*"If you know you will never cluster your application"* - if you find that you can see into the future, you may think that there's a more lucrative career beckoning in the gambling industry.
oxbow_lakes
+1 I think it just depends on the requirements. BTW I have sent many CVs ;)
ATorras
+1  A: 

Encapsulate your access to file data. Then you could use any of the methods outlined above. Even use a database. Measure the performance of your system. If it meets requirements then you are done. If not your file access is localised in one place and you can substitute a different solution. Same benefit if the software has to be ported to another container and/or has to be maintained by someone else.

Conor
+1 for encapsulating
flybywire
A: 

Plain file access is not transactional in nature. Unless you build in support for transactional operations (I'm clueless on how - this is the job of a resource manager), you will have to worry about transactional semantics of the operation that you are performing. If you do build in transaction support, there is very little you would have gained in performance (some of the loss in performance in databases, is due to all the bookkeeping done by the resource manager). And don't forget transaction management's close cousin - concurrency. Unless you start writing into a new file for every request, concurrency issues will more or less bite you.

You will find a lot more information in the Sun Blueprint's FAQ on EJB restrictions.

Unless you are in the clear with a good technical justification, you should not attempt to access the filesystem from EJBs. A very good example, would be a logging (not auditing) framework - there is relatively less harm in accessing the file system to write log files, given that logging does not have to be a transaction operation i.e. you dont need to rollback writes to a logfile; not that it is acceptable to have partial writes.

Vineet Reynolds