An EJB data control in Oracle ADF is a great feature to integrate our ADF application with a more traditional JEE technology stack, such as JMS, MDBs, singletons, timers etc. With a few simple clicks all of those wonderful technologies become part of the Fusion Application. But sometimes we may encounter problems which do not seem to be obvious in terms of how to solve them. In this post I would like to share some of my experience in integrating JEE world into the ADF application.
First advice is to ALWAYS create additional projects for every technology which is not a part of the Fusion Stack. For example, if you want to expose some Java class as a REST webservice, it is better to create another project with a wrapper class which gets proper annotations for REST (or SOAP) webservices you want to expose. This way you avoid mixing ADF and pure JEE features in one project which will increase the reusability and portability of your code. This is specially important for ViewController projects for which it's better not to mix with any other technology (apart from JSF based component libraries).
The second hint is more about the EJB data control mentioned in this post title. I have recently created an application in which I wanted to connect to a Twitter stream to catch and send the filtered twits further into the Oracle Event Processing instance as plain JMS messages. That was very easy to implement using a @Singleton annotation on the java class implemented with Twitter4J library. Another singleton EJB was responsible for listening for the OEP response output stream which would control the flight of the Parrot's AR Drone device (you will learn more about this particular PoC soon - stay tuned to the IMC posts!). As the drone is able to send back the video streaming from its front or bottom camera, I wanted to use that feature to automatically detect some QR codes around. It required to implement some specific interface to catch the video frames from my flying toy. But as soon as I added this required interface to the EJB, it started to behave strangely. Some attributed exposed to tune the drone flight parameters suddenly turned read-only (they had proper set- and get- accessors defined). In the WLS logs I could see the following entries:
[2015-03-20T11:33:10.035+01:00] [AdminServer] [ERROR]  [oracle.adf.model.adapter.dt] [tid: [ACTIVE].ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'] [userId:
] [ecid: b55d4ee3-9476-4747-accb-674c5447b9fd-0000004e,0] [APP: TwitterControlApp] [DSID: 0000Kkqj_ZMEwG1Wjtd9jo1L2zOh000002] ClassNotFound: java.awt.font.TextAttribute
] [ecid: b55d4ee3-9476-4747-accb-674c5447b9fd-0000004e,0] [APP: TwitterControlApp] [DSID: 0000Kkqj_ZMEwG1Wjtd9jo1L2zOh000002] ClassNotFound: java.awt.font.TextAttribute , ?
[2015-03-20T11:33:10.037+01:00] [AdminServer] [ERROR]  [oracle.adf.model.adapter] [tid: [ACTIVE].ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'] [userId:
Please pay attention to messages marked with red font. It was obvious that ADF runtime could not properly introspect the structure of this bean and that prevented it from build all metadata necessary for the data control to work. The previous error message (missing java.awt.font.TextAttribute class) was somehow a hint of what went wrong during the introspection. The reason was that the above mentioned interface included a method with a java.awt.BufferedImage parameter, which in turn could not be fully parsed with all its nested objects and structures. Although the method was not part of the EJB local interface, it was still public which by default made it a candidate to be included it into an data control during introspection. Hence the ADF runtime was failing at building the data control properly. The conclusion from this adventure is to ALWAYS try to build EJB wrappers around the real implementation classes and expose only those methods and functions which are really meant to be used in the ADF UI. Also it's a good advice to keep the data structures as simple as possible without references to third-party libraries, or even to Java's own stack, if it has complex data structures (like the AWT classes in my case).