How to access the file system from an EJB 3?
Asked Answered
B

4

26

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?

Brachio answered 31/8, 2009 at 14:13 Comment(1)
You don't have to have a BLOB in the database. SQL Server 2008 supports filestream storage that essentially dumps the file into a folder on the DB server but exposes it through the database. blogs.msdn.com/rdoherty/archive/2007/10/12/…Remmer
M
10

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.

Marjana answered 31/8, 2009 at 14:24 Comment(2)
Is this the recommended way of writing files from a EJB? Will the file be available to every node in a cluster (I think JNDI indeed is clustered so probably yes)? Last reading to (or writing from) JNDI is transactional?Thorpe
"you are disallowed " - you are not longer disallowed to access the filesystem and it was NEVER the intend that this only applied to the EJB specification. Whoever wrote that at the time was deluded that EJB would be the foundation of all of Java EE and therefor pretty much equalled Java EE.Menorah
M
10

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.

Margerymarget answered 31/8, 2009 at 14:26 Comment(5)
+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.Nucleon
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.Marjana
+1 I think it just depends on the requirements. BTW I have sent many CVs ;)Nucleon
@Marjana designing for a future you don't need today or tomorrow is also a bad practice. I've seen people completely overcomplicating their design to be "flexible in the future", but all that supposed flexibility wasn't used once after a life-span of 10 years. All this time it deed slow all kinds of tasks down. As always, use common sense.Sigismondo
Frequently these complicated now for future techniques end up not even being a good fit in the future, and are never used in favor of a huge rewrite anyways.Insertion
P
5

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.

Precautionary answered 31/8, 2009 at 16:23 Comment(0)
R
1

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.

Redevelop answered 31/8, 2009 at 21:5 Comment(2)
Caching files locally via a Singleton/timer is another example of an operation that's pretty much always safe.Sigismondo
"Unless [...] you should not attempt to access the filesystem from EJBs" - there is absolutely no specific reason why this should only hold for EJBs. One should be cautious when doing IO from every type of bean, not just beans that happen to be EJB beans.Menorah

© 2022 - 2024 — McMap. All rights reserved.