Moving data from stateless session bean to file
I have a session bean which retrieves data from the database and formats it. In the near future it will need to call a utility (which wraps XML-RPC) to forward the data, but for now, I need to execute a command line script which takes a file as input (i.e. 'command -f filename'). I don't really like the idea of writing a file from a session bean (and would JBoss let me do this?), and I've been toying with opening a URL to a CGI script, but that seems overkill. So, what is the cleanest, simplest way to get this data into the file,开发者_开发百科 so that I can invoke the command?
Additional info:
- Our server is JBoss and it is not clustered.
- The data may be sizable, possibly containing 10,000 pieces of XML encoded data (this can be broken into smaller chunks if absolutely necessary).
TIA, Ilane
Here's a relatively simple approach to get your content into a file.
In your session bean, implement a business method that looks something like:
public Object getContent(String fileName, <Other Args>) {
// Get content
// write to a byte array
byte[] content = ......;
return new ByteArrayFile(content, fileName);
}
The method implementation should acquire the data (from the DB) and serialize it to a byte array which is then loaded (along with an optional file name) into an instance of ByteArrayFile and returned.
The ByteArrayFile is a serializable object which implements a readResolved method which will convert the byte array into a local file (using the provided name or a temp file) and returned to the caller as a java.io.File.
Here's a rough implementation of ByteArrayFile:
public class ByteArrayFile implements Serializable {
protected final byte[] content;
protected final String fileName;
/**
* Creates a new ByteArrayFile
* @param content The file content
*/
public ByteArrayFile(byte[] content) {
this(content, null);
}
/**
* Creates a new ByteArrayFile
* @param content The file content
* @param fileName The file name to deserialize as
*/
public ByteArrayFile(byte[] content, String fileName) {
super();
this.content = content;
this.fileName = fileName;
}
/**
* Returns this object as a resolved file when the object is deserialized.
* @return
* @throws ObjectStreamException
*/
protected Object readResolve() throws ObjectStreamException {
FileOutputStream fos = null;
try {
File f = fileName==null ? File.createTempFile(getClass().getSimpleName(), ".file") : new File(fileName);
if(!f.canWrite()) {
throw new Exception("Unable to write to designated file [" + fileName + "]", new Throwable());
}
fos = new FileOutputStream(f);
fos.write(content);
fos.close();
fos = null;
return f;
} catch (Exception e) {
throw new RuntimeException("Failed to readResolve", e);
} finally {
try { if(fos!=null) fos.close(); } catch (Exception e) {}
}
}
}
This is a simplified (i.e. not a remote EJB call) example to show creating a ByteArrayFile, serializing it and then reading it back as a File:
public static void main(String[] args) {
ByteArrayFile baf = new ByteArrayFile("Hello World".getBytes());
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(baf);
oos.flush();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
File file = (File)ois.readObject();
System.out.println("File:" + file.getAbsolutePath() + " Size:" + file.length());
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
The output was:
File:/tmp/ByteArrayFile2790187442947455193.file Size:11
In truth, your session bean can absolutely write a file directly. The strict EJB limitations are not enforced by JBoss and exist to provide portability guarantees which you may not care about. However, the benefit of the above approach is that a remote client can invoke the call remotely but acquire the file locally.
精彩评论