Over the past few months (18+ months now) I have been working on a project that has become pretty involved, being a hybrid Java EE/OSGi app, with a lot of javascript and "trickery" involved.
One of the core goals of this project was to have a central "Core" app that would be the persistence layer, with the ability to create pluggable interfaces that could interact with this layer.
The "Core" layer also houses an Admin Console, which an admin uses to setup and administer these interfaces, so that they can communicate properly.
The legacy app of this involved a combination of Ruby On Rails to house the entire admin console and send information via JMS to the standalone interfaces that were each running in their own space.
When an interface was to be created, that involved not only writing the java code for the interface itself, but much code to be written in the ruby side of the app to support this, including the GUI that would be specific to the interface in question.
With the new architecture, we wanted to make sure that when interfaces are built, that they be completely self contained, so if there were updates needed, only the interface bundle itself would need to be deployed, not any of the surrounding parts.
A huge challenge to me was not only setting up the framework to handle the communications between these interfaces and the core app, but the GUI piece was proving to be an immense challenge.
Then came 'angular'.
I had been following it for a while. One of the guys on my team at Sun (Igor!) had went to work for Google, and I saw this library he was working on - and started messing around with it.
It is an *incredible* library for building client side apps.
Creating a resources bundle that housed the angular library and our custom libraries that the interface bundles could rely on (via manual registration of them via the OSGi HttpService), we were able to make the persistence of the interface data straight JSON objects (which the core app doesn't care about - only cares about saving the data itself), and have that pulled back and manipulated via angular binding.
I will be following up with some of the details of the work that was done, which could be a valuable reference.
I couldn't be happier with how this library has helped in this transition, and made it possible to build the beginnings of a rich SDK for interface developers to use.
Thursday, September 29, 2011
Monday, June 20, 2011
@ManagedBean inside OSGi bundle in GlassFish (3.1) - part 2
In previous post talked about utilizing javax.annotation.ManagedBean to create a ManagedBean in an OSGi bundle deployed in GlassFish.
A different (better) route would be to use CDI (Contexts and Dependency Injection) and utilize @Inject annotations instead of @Resource and @EJB for injecting the resources.
For this to work, there must be a 'beans.xml' file present. According to the docs:
To make this possible in our bundles, added a 'META-INF' directory to the 'src' dir, with an empty 'beans.xml' file underneath.
Then in our bnd definition file (which builds the OSGi bundle for us), we define the resource to be included in our bundle:
With this in place, we no longer need to reference the 'com.sun.ejb.containers, com.sun.ejb.spi.io' libraries in our 'Import-Package' entry (since we are not using the ManagedBean annotation directly).
We can now replace all the @EJB and @Resource calls to @Inject.
A different (better) route would be to use CDI (Contexts and Dependency Injection) and utilize @Inject annotations instead of @Resource and @EJB for injecting the resources.
For this to work, there must be a 'beans.xml' file present. According to the docs:
An application that uses CDI must have a file named beans.xml. The file can be completely empty (it has content only in certain limited situations), but it must be present.
To make this possible in our bundles, added a 'META-INF' directory to the 'src' dir, with an empty 'beans.xml' file underneath.
Then in our bnd definition file (which builds the OSGi bundle for us), we define the resource to be included in our bundle:
Include-Resource: META-INF/beans.xml=src/META-INF/beans.xml
With this in place, we no longer need to reference the 'com.sun.ejb.containers, com.sun.ejb.spi.io' libraries in our 'Import-Package' entry (since we are not using the ManagedBean annotation directly).
We can now replace all the @EJB and @Resource calls to @Inject.
@ManagedBean inside OSGi bundle in GlassFish (3.1)
Was struggling getting a @ManagedBean to be able compile correctly under GlassFish - needed to add the following packages to the Import-Package entry of the Manifest:
This allowed us to have a ManagedBean in the bundle.
For example - want to have a @Singleton class for some processing.
(this would be a javax.annotation.ManagedBean, not a Faces ManagedBean):
and for testing purposes - within the MDB:
com.sun.ejb.containers,com.sun.ejb.spi.io
This allowed us to have a ManagedBean in the bundle.
For example - want to have a @Singleton class for some processing.
@Singleton public class TestSingleton { public String testMySingleton() { return "This is a test from my singleton!"; } }
(this would be a javax.annotation.ManagedBean, not a Faces ManagedBean):
@ManagedBean public class SingBean { @EJB private TestSingleton testSingleton;
and for testing purposes - within the MDB:
@MessageDriven(mappedName = "jms/MyQueue", activationConfig = { @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") }) public class ExtIncMDB { @Resource SingBean myBean;
Coming back...
Haven't written to this blog in a while - getting caught up with getting the project I have been working on working, but with some of the issues we are finding and the solutions to those issues, I really need to document them for future reference.
I have also been getting deeper into iOS and Android development, and have figured out some cool things there to start documenting and keeping around.
So major posts coming regarding Java EE 6/OSGi hybrid apps, iOS and Android development (as well as anything else I want to blab about just to keep record).
If others can find some of the snippets to help like I did searching around - would be great.
I have also been getting deeper into iOS and Android development, and have figured out some cool things there to start documenting and keeping around.
So major posts coming regarding Java EE 6/OSGi hybrid apps, iOS and Android development (as well as anything else I want to blab about just to keep record).
If others can find some of the snippets to help like I did searching around - would be great.
Friday, August 20, 2010
mysql error: Got a packet bigger than 'max_allowed_packet' bytes
I had recently been working on a project where I was getting db dumps (using mysqldump) - and having issues importing the db back into a fresh install of mysql:
This finally worked in getting past the limitation I was hitting.
Maybe this will be a quick fix help to someone else running into this problem as well.
% mysql -u [username] -p [database] < sqlDump.sql Enter password: ERROR 1153 (08S01) at line 1191: Got a packet bigger than 'max_allowed_packet' bytesWhich seemed related to blobs containing larger pdf files mostly (in my case at least). In trying to figure out how to get past this - seeing the default size for 'max_allowed_packet' was too low - in the daemon side (mysqld):
mysql> select @@max_allowed_packet; +----------------------+ | @@max_allowed_packet | +----------------------+ | 1048576 | +----------------------+To fix this, I used the configuration files (optional) - located on my local system (OS X - Snow Leopard) at: /usr/local/mysql/support-files/my-xxx.cnf. I copied one of these (the 'my-small.cnf' specifically) to /etc/my.cnf, and edited the file to increase the default for the server to 64M:
# The MySQL server [mysqld] port = 3306 socket = /tmp/mysql.sock skip-locking key_buffer = 16K max_allowed_packet = 64M ...This will increase the limit (globally - since the file is located in /etc/my.cnf and not in ~/.my.cnf) for the server. This increased limit can then be seen here after a server restart (64*1024*1024):
mysql> select @@max_allowed_packet; +----------------------+ | @@max_allowed_packet | +----------------------+ | 67108864 | +----------------------+After trying to re-import my file, I found out I also needed to have this via the client as well while importing, since setting the above limit did not seem to solve my issue:
% mysql --max_allowed_packet=64M -u [username] -p [database] < sqlDump.sql
This finally worked in getting past the limitation I was hitting.
Maybe this will be a quick fix help to someone else running into this problem as well.
Blank lines in JSP output
I had posted some small entries on my old blog at Sun, and wanted to transfer some of those here for reference sake.
I was having an issue with jsp outputting blank lines at the top of output - and if the contentType being text/xml - causing parsing error being that the
Come to find out, this had been addressed in JSP2.1 - but was a bit hard to track down.
Adding the line:
to the top of your jsp will remove these, thus letting the XML feeds parse correctly.
Small fix - but has cured some headache in creating some feed proxies.
I was having an issue with jsp outputting blank lines at the top of output - and if the contentType being text/xml - causing parsing error being that the
<?xml...
directive not being the first line - causing the exception:'XML or text declaration not at start of entity'
Come to find out, this had been addressed in JSP2.1 - but was a bit hard to track down.
Adding the line:
<%@page trimDirectiveWhitespaces="true"%>
to the top of your jsp will remove these, thus letting the XML feeds parse correctly.
Small fix - but has cured some headache in creating some feed proxies.
Wednesday, August 18, 2010
OSGi, JavaMail, and the mailcap issue
When developing some of the components for our application, I have been seeing some issues with ClassLoaders when creating them as OSGi bundles.
One main case that had me curious for a while was using JavaMail inside an OSGi bundle, and having to send a multipart mail.
The issue was - JavaMail relies on JAF (the activation framework), which houses a file (mailcap) in it's META-INF directory. So, if these (the javamail and jaf) are stored in separate bundles, then javamail cannot access the configuration file to determine which MIME types it can handle, and thus throwing an UnsupportedDataTypeException:
An UnsupportedDataTypeException usually occurs because JAF cannot find the DataContentHandler (DCH) for a given MIME type by reading the mailcap.
Glassfish 3 actually bundles these together in one bundle (modules/mail.jar), but I was still having the issue described above.
So I went down the path trying to figure out what in the world I could do to get past this. You can't really export resources like you do packages in the manifest, so importing into my bnd file didn't work, and even trying to manually force new mailcaps (which seemed to work elsewhere) didn't work:
This is basically just pushing through exactly what is in the mailcap file directly. But - this didn't work either. Odd...
I then went as far as create a new instance of the specific handler that is being used, and testing the support for that DataFlavor:
And it shows it is supported:
Yet - when sending the message, same Exception. Ugh...
Finally, Sahoo (from the Glassfish team) gave me a suggestion of manipulating the ClassLoaders when I needed to to make the calls, saving the current ClassLoader so it can be put back into place.
In our bundle, we create the session and send the message in two different methods, so this had to be implemented twice, but finally - it worked!
This is now working fine. I was a bit leery about mucking with the ClassLoaders in here - which was an issue with using JRuby code inside OSGi bundles as well, but this seems to be OK in that we are temporarily changing and immediately changing back.
One main case that had me curious for a while was using JavaMail inside an OSGi bundle, and having to send a multipart mail.
The issue was - JavaMail relies on JAF (the activation framework), which houses a file (mailcap) in it's META-INF directory. So, if these (the javamail and jaf) are stored in separate bundles, then javamail cannot access the configuration file to determine which MIME types it can handle, and thus throwing an UnsupportedDataTypeException:
javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/alternative;
An UnsupportedDataTypeException usually occurs because JAF cannot find the DataContentHandler (DCH) for a given MIME type by reading the mailcap.
Glassfish 3 actually bundles these together in one bundle (modules/mail.jar), but I was still having the issue described above.
So I went down the path trying to figure out what in the world I could do to get past this. You can't really export resources like you do packages in the manifest, so importing into my bnd file didn't work, and even trying to manually force new mailcaps (which seemed to work elsewhere) didn't work:
MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap(); mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain"); mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html"); mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml"); mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed; x-java-fallback-entry=true"); mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822"); CommandMap.setDefaultCommandMap(mc);
This is basically just pushing through exactly what is in the mailcap file directly. But - this didn't work either. Odd...
I then went as far as create a new instance of the specific handler that is being used, and testing the support for that DataFlavor:
DataContentHandler dhmm = new com.sun.mail.handlers.multipart_mixed(); DataFlavor[] dtf = dhmm.getTransferDataFlavors(); for (DataFlavor tmpdf : dtf) { log.debug(" isSupported? " + tmpdf.getMimeType() + ":" + message.getDataHandler().isDataFlavorSupported(tmpdf)); }
And it shows it is supported:
isSupported? multipart/mixed:true
Yet - when sending the message, same Exception. Ugh...
Finally, Sahoo (from the Glassfish team) gave me a suggestion of manipulating the ClassLoaders when I needed to to make the calls, saving the current ClassLoader so it can be put back into place.
In our bundle, we create the session and send the message in two different methods, so this had to be implemented twice, but finally - it worked!
// There is an issue in the OSGi framework preventing the MailCap // from loading correctly. When getting the session here, // temporarily set the ClassLoader to the loader inside the bundle // that houses javax.mail. Reset at the end. ClassLoader tcl = Thread.currentThread().getContextClassLoader(); try { // Set the ClassLoader to the javax.mail bundle loader. Thread.currentThread().setContextClassLoader(javax.mail.Session.class.getClassLoader()); ... } finally { // Reset the ClassLoader where it should be. Thread.currentThread().setContextClassLoader(tcl); }
This is now working fine. I was a bit leery about mucking with the ClassLoaders in here - which was an issue with using JRuby code inside OSGi bundles as well, but this seems to be OK in that we are temporarily changing and immediately changing back.
Subscribe to:
Posts (Atom)