Open a File within an EJB - java

I know that it is in general not allowed to access local Files (with java.io) within an EJB: nevertheless, I have an EJB which has to open an Excel File and edit it using the apache.poi library. If I do something like this:
#Stateless
public class MyEJB {
public void editExcel(){
...
InputStream in = MyEJB.class.getClassLoader().getResourceAsStream("/xls/ExcelFile.xls");
final Workbook generatedExcel = new XLSTransformer().transformXLS(in, beans);
...
} }
The filesystem structure:
MyEar.ear
--my-ejb.jar
---com
-----company
-------ejbs
----------MyEJB.class
---xls
-----ExcelFile.xls
In this case I will get an Instance of ZipFile$ZipFileInputStream (private inner class of ZipFileInputStream) and XLSTransformer will throw an IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream"), as it expects an InputStream representing ExcelFile.xls and gets instead a stream representing the whole my-ejb.jar.
My questions: do you know how to solve this situation? What is the best practice for accessing file within EJBs?
Thanks a lot!

I also had to return a modified XLS template out of a EE container once. Though I always look at such resources not as a part of the WAR/EAR deployment but as a configurable entity managed by customers.
So, one simple solution might be to save your template in a configuration directory, and provide it's path & name trough JNDI to your application.
BUT
You might also use JNDI for representing a more complex datatype representing an excel file, so your EJB code stays free of direct file operations.
You may find some pointers (for JBoss JNDI AS) here: http://middlewaremagic.com/jboss/?p=1690

Related

What replaces FileResolver in the JasperReports API?

One of our software utilities uses a class that implements net.sf.jasperreports.engine.util.FileResolver to load report elements (like images for example) that reside at a path relative to the report or that are to be loaded via a proprietary file server protocol. As of the latest version, 6.6.0, I see that the plan is to remove the FileResolver class entirely. However, in the Javadocs, it only notes that the class will be removed. No details about a replacement are specified.
I am not expecting to be able to trade out the FileResolver with another class with a 1:1 substitution, but would really like to know what the report filler is now using to locate external report elements.
FileResolver was deprecated in favor of net.sf.jasperreports.repo.RepositoryService implementations.
There's a builtin implementation named net.sf.jasperreports.repo.FileRepositoryService which is roughly the equivalent of the deprecated net.sf.jasperreports.engine.util.SimpleFileResolver.
Repository services are registered as JasperReportsContext extensions.
That can be done either in a jasperreports_extension.properties file like this:
net.sf.jasperreports.extension.registry.factory.file.repository=net.sf.jasperreports.repo.FileRepositoryServiceExtensionsRegistryFactory
net.sf.jasperreports.extension.file.repository.root=/path/to/repository
net.sf.jasperreports.extension.registry.factory.persistence=net.sf.jasperreports.repo.FileRepositoryExtensionsRegistryFactory
Registering the extensions can also be done by programmatically creating a JasperReportsContext object and then using it to fill the reports:
SimpleJasperReportsContext context = new SimpleJasperReportsContext();
FileRepositoryService fileRepository = new FileRepositoryService(context, "/path/to/repository", false);
context.setExtensions(RepositoryService.class, Collections.singletonList(fileRepository));
context.setExtensions(PersistenceServiceFactory.class, Collections.singletonList(FileRepositoryPersistenceServiceFactory.getInstance()));
JasperPrint jasperPrint = JasperFillManager.getInstance(context).fill(jasperReport, params);
If you need to implement a custom repository service, you can take FileRepositoryService as a reference. You'll probably want to implement StreamRepositoryService and register PersistenceServices (as in FileRepositoryPersistenceServiceFactory).
If what you need to do is about resource paths relative to the report, you can also take a look at the JRFiller methods that take a JasperReportSource argument. Passing such an object is meant to automatically resolve report resource references as relative to the report (provided that the repository service implements resource lookup based on RepositoryContext).

Description on JMX fields and methods JBoss

How can we add description on the fields and operations exposed for JMX?
JBoss version : JBoss EAP 5.1.2
We have a Service bean as
#Service
#Management(MyConfigMgnt.class)
public class MyConfigService implements MyConfigLocal, MyConfigMgnt {
public void setMyValue(String MyValue){}
public String getMyValue(){}
}
These methods are declared in the MyConfigMgnt interface.
This is visible in the jboss jmx console as
and for the field it is shown as
How do we add relevant and proper information on the fields and the MBean.
Thanks
There's 2 ways of doing this.
Re-implement your service as a DynamicMBean which is slightly more complicated but allows for the definition of attribute and operation meta-data. (i.e. MyConfigMgnt extends DynamicMBean)
An easier way (but possibly not future-proof) is to use an XMBean descriptor. XMBeans are a proprietary JBoss JMX extension where meta-data is defined in an external XML resource. It would require no actual changes to the source code except the addition of the XMBean resource location which looks something like this:
#Service(objectName = XMBeanService.OBJECT_NAME, xmbean = "resource:META-INF/service-xmbean.xml")
If you have a very large number of attributes and operations, the XMBean XML descriptor can be arduous to write, but twiddle has a helper command which will generate a template specific to your existing simple MBean, so you can save the output, fill in the details and go from there.

Multiple config block in java properties file

I need to define multiple configuration blocks in a single .properties file in Spring. Currently I am having multiple .properties file like below:
one.properties:
publishing.channel=ftp
ftp.user=user1
ftp.password=pass1
ftp.host=abc.xyz.com
ftp.port=21
two.properties
publishing.channel=ftp
ftp.user=user2
ftp.password=pass2
ftp.host=def.xyz.com
ftp.port=21
What I now require is defining only one .properties file and add all the configuration blocks in it like so:
publishing.channel=ftp
ftp.user=user1
ftp.password=pass1
ftp.host=abc.xyz.com
ftp.port=21
then another one
publishing.channel=ftp
ftp.user=user2
ftp.password=pass2
ftp.host=cdf.xyz.com
ftp.port=21
it could be http too
publishing.channel=http
http.user=user2
http.password=pass2
http.host=cdf.xyz.com
Problem is when I put multiple property blocks like this, I cannot differentiate in code as my bean methods (e.g. getHost()) will only fetch the last declared one in the properties file. I do not want to create many variables like host1, host2, host3 and so on as it would need to be modified in case there is another block of properties added. How can I make it generic?
Thanks in advance.
You can use PropertiesConfiguration from Apache Commons Configuration and then access all the values of same key and add your logic to get the required value.
Use getStringArray(key) method or getList(key) method to access all values.

Copying multiple files from various sources to various destinations via Spring Integration

I am presented with the following use case.
I am receiving a Message<Foo> object on my input channel, where Foo object has 2 properties
public class Foo {
...
public String getSourcePathString();
public String getTargetPathString();
...
}
sourcePathString is a String which denotes where the source file is located, while targetPathString is a place where the file should be copied to.
Now, I do know how to use file:outbound-channel-adapter to copy the file to a custom target location via FileNameGenerator, however, I am not sure how I can provide the location where to read the file from in file:inbound-channel-adapter and how to activate the reading when the message is received only.
What I have so far is a custom service activator where I perform copying in my own bean, however, I'd like to try and use Spring Integration for it.
So, is there a way to implement triggerable file copying in Spring Integration with already present components?
You cannot currently change the input directory dynamically on the inbound channel adapter.
The upcoming 4.2 release has dynamic pollers which would allow this.
However, it seems the adapter is not really suitable for your use case - it is a polled adapter, whereas you want to fetch the file on demand.
You could minimize your user code by configuring a FileReadingMessageSource, set the directory and call receive() to get the file.

xstream: only parsing child element

I have following xml
<root>
<child-1>
</child-1>
<child-2>
<subchild-21>
</subchild-22>
</child-2>
</root>
My requirement is such that I only want to parse child-2. I am unaware of root and child-1.
Is it possible with xstream because I couldn't find a way to ignore root.
There are several ways to go, depending on your requirements.
If you know the name of the class to parse (child-2 here), you could look for the <child-2> and </child-2> entry in the XML, copy them along with the content in-between to a new temporary XML file (you can create temporary files using createTempFile() from the standard File class). This is the way I would suggest.
If you want to take out the child-2 instance without knowing its name, but you know the names of the surrounding classes, you could mock their classes, that is create classes of the same name, but without their specific content. In your example there is no content (might have been ignored at export time), but it's important to have the same member data in the mock classes for the import to succeed. (unless you use ignoreUnknownElements() as stated by Philipi Willemann)
Of course, if you're the one creating the XML, you should be able to export only the child-2 instance in the first place.
If you know the root name you can create a simple class has an attribute of the class you have mapped to child-2:
#XStreamAlias("root")
class Root {
#XStreamAlias("child-2")
private Child2 child;
//get and set
}
Then when you are processing the XML you can set XStream to ignore unknown elements with xstream.ignoreUnknownElements();

Categories