tag:blogger.com,1999:blog-79742094362651678332024-03-18T02:47:43.405-07:00David Blevins' BlogDavid Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.comBlogger18125tag:blogger.com,1999:blog-7974209436265167833.post-65122916137699632292013-03-22T13:39:00.000-07:002013-03-22T16:15:40.809-07:00Saving Java EE?<span style="color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px;">The recent InfoWorld article on TomEE possed the question </span><a href="http://www.infoworld.com/d/application-development/can-tomee-save-java-ee-214901" style="border: 0px; color: #4183c4; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin: 0px; padding: 0px; text-decoration: none;">"Can TomEE save Java EE?"</a><br />
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
I want to say explicitly, we don't think Java EE needs saving. It's doing great. Java EE 6 has gained huge traction with developers. Java EE 7 is the first EE spec to be <a href="http://jcp.org/en/jsr/detail?id=348" target="_blank">openly developed</a>. Something I'm talking about next week at <a href="http://www.devoxx.com/display/FR13/Java+EE+7+and+EJB+3.2%2C+what+made+it+and+what+got+the+axe" target="_blank">Devoxx France</a>. Times have never been better for Java EE developers.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
We do, however, want to change the old debates that have persisted over the last 10+ years.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
<strong style="border: 0px; margin: 0px; padding: 0px;">Tomcat vs Java EE is tired and old.</strong></div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
As Tomcat commands so much of the market, the fact that we as developers can't agree on something so basic is a big problem. We made TomEE to address the section of people who have typically <strong style="border: 0px; margin: 0px; padding: 0px;">not</strong> been happy with the existing choices and graviate towards Tomcat instead.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
As most these people using Tomcat <strong style="border: 0px; margin: 0px; padding: 0px;">do</strong> in fact use a number of Java EE technologies, the vision to reach them was pretty clear. Both Java EE and Tomcat needed to change.</div>
<ul style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin: 15px 0px; padding: 0px 0px 0px 30px;">
<li style="border: 0px; margin: 0px; padding: 0px;"><div style="border: 0px; margin-bottom: 15px; padding: 0px;">
In JavaEE-land, we (the <strong style="border: 0px; margin: 0px; padding: 0px;">JCP</strong>) created the Web Profile which is roughly <em style="border: 0px; margin: 0px; padding: 0px;">half</em> of the Full Profile. So, JavaEE shrunk, check.</div>
</li>
<li style="border: 0px; margin: 0px; padding: 0px;"><div style="border: 0px; margin-bottom: 15px; padding: 0px;">
Over at <strong style="border: 0px; margin: 0px; padding: 0px;">Apache</strong>, we took Tomcat and built it up to be a complete implementation of the Web Profile, got it certified and announced it as Apache TomEE. So, Tomcat grew.</div>
</li>
</ul>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
In a very real sense TomEE is a <strong style="border: 0px; margin: 0px; padding: 0px;">middle ground</strong>. It represents both "sides" giving an inch and making a compromise.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
As far as the Tomcat side of the compromises, we wanted to keep them as minimal as possible. We worked very hard to "go with the grain" of the Tomcat architecture, keep startup fast, keep memory low and overall keep it Tomcat.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
As a result TomEE works out of the box with Tomcat-aware tools like <b>Eclipse</b>, <b>NetBeans</b>, <b>Intellij</b>, <b>NewRelic</b>, <b>YourKit</b>, <b>JRebel</b> etc. etc. This is also why we're seeing Cloud providers like <b>Jelastic</b> and <b>ActiveState</b> expand their Tomcat support to include TomEE. As well even traditional ISPs that focus on Tomcat, such as <b>Metawerx</b> have expanded their Tomcat support to include TomEE.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-top: 15px; padding: 0px;">
Whether or not the "Tomcat vs JavaEE" debate changes, the reality is both Tomcat and Java EE <strong style="border: 0px; margin: 0px; padding: 0px;">have</strong> changed.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-top: 15px; padding: 0px;">
While we don't consider ourselves the "savior of JavaEE", you can freely consider us the savior of time; time saved arguing and reinventing wheels.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-top: 15px; padding: 0px;">
It is very much the time to move on.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-top: 15px; padding: 0px;">
<br /></div>
David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com108tag:blogger.com,1999:blog-7974209436265167833.post-63544949821654471322012-11-21T18:22:00.000-08:002012-11-21T18:22:33.539-08:00CDI, when to break out the EJBs<br />
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
I sometimes joke that CDI is basically EJB 4.0. While that's obviously not true there is a considerable amount of similarity and that does create a bit of confusion for people. Here is some general information on EJB and CDI as they relate to each together.</div>
<h2 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; cursor: text; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 24px; line-height: 1.4em; margin: 20px 0px 10px; padding: 0px; position: relative; text-align: left;">
<a class="anchor" href="https://gist.github.com/e76a286230112cd6d460#ejb--cdi" name="ejb--cdi" style="bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; line-height: 1.4em; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>EJB >= CDI</h2>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
Note that EJBs <strong style="line-height: 1.4em; margin: 0px; padding: 0px;">are</strong> CDI beans and therefore have all the benefits of CDI. The reverse is not true (yet). So definitely don't get into the habit of thinking "EJB vs CDI" as that logic really translates to "EJB+CDI vs CDI", which is an odd equation.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
In future versions of Java EE we'll be continuing to align them. What aligning means is allowing people to do what they already can do, just without the<code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateful</code>, <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateless</code> or <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Singleton</code> annotation at the top.</div>
<h2 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; cursor: text; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 24px; line-height: 1.4em; margin: 20px 0px 10px; padding: 0px; position: relative; text-align: left;">
<a class="anchor" href="https://gist.github.com/e76a286230112cd6d460#ejb-and-cdi-in-implementation-terms" name="ejb-and-cdi-in-implementation-terms" style="bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; line-height: 1.4em; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>EJB and CDI in Implementation Terms</h2>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
Ultimately, EJB and CDI share the same fundamental design of being proxied components. When you get a reference to an EJB or CDI bean, it isn't the real bean. Rather the object you are given is a fake (a proxy). When you invoke a method on this fake object, the call goes to the container who will send the call through interceptors, decorators, etc. as well as take care of any transaction or security checks. Once all that is done, the call finally goes to the real object and the result is passed back through the proxy to the caller.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
The difference only comes in how the object to be invoked is resolved. By "resolved" we simply mean, where and how the container looks for the real instance to invoke.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
In CDI the container looks in a "scope", which will basically be a hashmap that lives for a specific period of time (per request <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@RequestScoped</code>, per HTTP Session <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@SessionScoped</code>, per application <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@ApplicationScoped</code>, JSF Conversation <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@ConversationScoped</code>, or per your custom scope implementation).</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
In EJB the container looks also into a hashmap if the bean is of type <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateful</code>. An <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateful</code> bean can also use any of the above scope annotations causing it to live and die with all the other beans in the scope. In EJB <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateful</code> is essentially the "any scoped" bean. The <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateless</code> is basically an instance pool -- you get an instance from the pool for the duration of one invocation. The <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Singleton</code> is essentially <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@ApplicationScoped</code></div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
So in a fundamental level, anything you can do with an "EJB" bean you should be able to do with a "CDI" bean. Under the covers it's awfully hard to tell them apart. All the plumbing is the same with the exception of how instances are resolved.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
They aren't currently the same in terms of the services the container will offer when doing this proxying, but as I say we're working on it at the Java EE spec level.</div>
<h3 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(221, 221, 221); border-bottom-style: solid; border-bottom-width: 1px; cursor: text; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 18px; line-height: 1.4em; margin: 20px 0px 10px; padding: 0px; position: relative; text-align: left;">
<a class="anchor" href="https://gist.github.com/e76a286230112cd6d460#performance-note" name="performance-note" style="bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; line-height: 1.4em; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Performance note</h3>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
Disregard any "light" or "heavy" mental images you may have. That's all marketing. They have the same internal design for the most part. CDI instance resolution is perhaps a bit more complex because it is slightly more dynamic and contextual. EJB instance resolution is fairly static, dumb and simple by comparison.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
I can tell you from an implementation perspective in TomEE, there's about zero performance difference between invoking an EJB vs invoking a CDI bean.</div>
<h2 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-bottom-width: 1px; cursor: text; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 24px; line-height: 1.4em; margin: 20px 0px 10px; padding: 0px; position: relative; text-align: left;">
<a class="anchor" href="https://gist.github.com/e76a286230112cd6d460#default-to-pojos-then-cdi-then-ejb" name="default-to-pojos-then-cdi-then-ejb" style="bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; line-height: 1.4em; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Default to POJOs, then CDI, then EJB</h2>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
Of course don't use CDI or EJB when there is no benefit. Throw in CDI when you start to want injection, events, interceptors, decorators, lifecycle tracking and things like that. That's most the time.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
Beyond those basics, there are a number of useful container services you only have the option to use if you make your CDI bean also an EJB by adding<code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateful</code>, <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateless</code>, or <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Singleton</code> on it.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
Here's a short list of when I break out the EJBs.</div>
<h3 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(221, 221, 221); border-bottom-style: solid; border-bottom-width: 1px; cursor: text; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 18px; line-height: 1.4em; margin: 20px 0px 10px; padding: 0px; position: relative; text-align: left;">
<a class="anchor" href="https://gist.github.com/e76a286230112cd6d460#using-jax-ws" name="using-jax-ws" style="bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; line-height: 1.4em; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Using JAX-WS</h3>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
Exposing a JAX-WS <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@WebService</code>. I'm lazy. When the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@WebService</code> is also an EJB, you don't have to list it and map it as a servlet in the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">web.xml</code> file. That's work to me. Plus I get the option to use any of the other functionality mentioned below. So it's a no-brainer for me.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
Available to <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateless</code> and <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Singleton</code> only.</div>
<h3 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(221, 221, 221); border-bottom-style: solid; border-bottom-width: 1px; cursor: text; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 18px; line-height: 1.4em; margin: 20px 0px 10px; padding: 0px; position: relative; text-align: left;">
<a class="anchor" href="https://gist.github.com/e76a286230112cd6d460#using-jax-rs" name="using-jax-rs" style="bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; line-height: 1.4em; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Using JAX-RS</h3>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
Exposing a JAX-RS resource via <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Path</code>. I'm still lazy. When the RESTful service is also an EJB, again you get automatic discovery and don't have to add it to a JAX-RS <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">Application</code> subclass or anything like that. Plus I can expose the exact same bean as an <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@WebService</code> if I want to or use any of the great functionality mentioned below.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
Available to <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateless</code> and <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Singleton</code> only.</div>
<h3 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(221, 221, 221); border-bottom-style: solid; border-bottom-width: 1px; cursor: text; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 18px; line-height: 1.4em; margin: 20px 0px 10px; padding: 0px; position: relative; text-align: left;">
<a class="anchor" href="https://gist.github.com/e76a286230112cd6d460#startup-logic" name="startup-logic" style="bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; line-height: 1.4em; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Startup logic</h3>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
Load on startup via <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Startup</code>. There is currently no equivalent to this in CDI. Somehow we missed adding something like an <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">AfterStartup</code> event in the container lifecycle. Had we done this, you simply could have had an <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@ApplicationScoped</code> bean that listened for it and that would be effectively the same as an <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Singleton</code> with <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Startup</code>. It's on the list for CDI 1.1.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
Available to <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Singleton</code> only.</div>
<h3 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(221, 221, 221); border-bottom-style: solid; border-bottom-width: 1px; cursor: text; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 18px; line-height: 1.4em; margin: 20px 0px 10px; padding: 0px; position: relative; text-align: left;">
<a class="anchor" href="https://gist.github.com/e76a286230112cd6d460#working-in-parallel" name="working-in-parallel" style="bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; line-height: 1.4em; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Working in Parallel</h3>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
<code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Asynchronous</code> method invocation. Starting threads is a no-no in any server-side environment. Having too many threads is a serious performance killer. This annotation allows you to parallelize things you do using the container's thread pool. This is awesome.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
Available to <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateful</code>, <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateless</code> and <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Singleton</code>.</div>
<h3 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(221, 221, 221); border-bottom-style: solid; border-bottom-width: 1px; cursor: text; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 18px; line-height: 1.4em; margin: 20px 0px 10px; padding: 0px; position: relative; text-align: left;">
<a class="anchor" href="https://gist.github.com/e76a286230112cd6d460#scheduling-work" name="scheduling-work" style="bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; line-height: 1.4em; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Scheduling work</h3>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
<code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Schedule</code> or <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">ScheduleExpression</code> is basically a cron or <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">Quartz</code> functionality. Also very awesome. Most containers just use Quartz under the covers for this. Most people don't know, however, that scheduling work in Java EE is transactional! If you update a database then schedule some work and one of them fails, both will automatically cleaned up. If the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">EntityManager</code> persist call fails or there is a problem flushing, there is no need to un-schedule the work. Yay, transactions.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
Available to <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateless</code> and <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Singleton</code> only.</div>
<h3 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(221, 221, 221); border-bottom-style: solid; border-bottom-width: 1px; cursor: text; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 18px; line-height: 1.4em; margin: 20px 0px 10px; padding: 0px; position: relative; text-align: left;">
<a class="anchor" href="https://gist.github.com/e76a286230112cd6d460#using-entitymanagers-in-a-jta-transaction" name="using-entitymanagers-in-a-jta-transaction" style="bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; line-height: 1.4em; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Using EntityManagers in a JTA transaction</h3>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
The above note on transactions of course requires you to use a <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">JTA</code> managed <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">EntityManager</code>. You can use them with plain "CDI", but without the container-managed transactions it can get really monotonous duplicating the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">UserTransaction</code> commit/rollback logic.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
Available to all Java EE components including CDI, JSF <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@ManagedBean</code>, <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@WebServlet</code>, <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@WebListener</code>, <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@WebFilter</code>, etc. The<code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@TransactionAttribute</code> annotation, however, is available to <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateful</code>, <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateless</code> and <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Singleton</code> only.</div>
<h3 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(221, 221, 221); border-bottom-style: solid; border-bottom-width: 1px; cursor: text; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 18px; line-height: 1.4em; margin: 20px 0px 10px; padding: 0px; position: relative; text-align: left;">
<a class="anchor" href="https://gist.github.com/e76a286230112cd6d460#keeping-jta-managed-entitymanager" name="keeping-jta-managed-entitymanager" style="bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; line-height: 1.4em; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Keeping JTA managed <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: inherit; font-weight: normal; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">EntityManager</code></h3>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
The <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">EXTENDED</code> managed <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">EntityManager</code> allows you to keep an <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">EntityManager</code> open between <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">JTA</code> transactions and not lose the cached data. Good feature for the right time and place. Use responsibly :)</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; margin-top: 15px; padding: 0px; text-align: left;">
Available to <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stateful</code> only.</div>
<h3 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(221, 221, 221); border-bottom-style: solid; border-bottom-width: 1px; cursor: text; font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 18px; line-height: 1.4em; margin: 20px 0px 10px; padding: 0px; position: relative; text-align: left;">
<a class="anchor" href="https://gist.github.com/e76a286230112cd6d460#easy-synchronization" name="easy-synchronization" style="bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; line-height: 1.4em; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Easy synchronization</h3>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-bottom: 15px; padding: 0px; text-align: left;">
When you need synchronization, the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Lock(READ)</code> and <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Lock(WRITE)</code> annotations are pretty excellent. It allows you to get concurrent access management for free. Skip all the ReentrantReadWriteLock plumbing. In the same bucket is <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@AccessTimeout</code>, which allows you to say how long a thread should wait to get access to the bean instance before giving up.</div>
<div style="font-family: helvetica, arial, freesans, clean, sans-serif; font-size: 14.44444465637207px; line-height: 1.4em; margin-top: 15px; padding: 0px; text-align: left;">
Available to <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 12px; line-height: 1.4em; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Singleton</code> beans only.</div>
David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com339tag:blogger.com,1999:blog-7974209436265167833.post-91919843988242228442012-11-15T07:24:00.002-08:002012-11-15T07:35:57.734-08:00Meta-Annotations<br />
<h1 style="-webkit-font-smoothing: antialiased; border: 0px; cursor: text; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 28px; margin: 0px 0px 10px; padding: 0px; position: relative;">
Meta-Annotations</h1>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; padding: 0px;">
<a href="https://github.com/dblevins/metatypes/" target="_blank">Meta-Annotations</a> are an experiment in annotation inheritance, abstraction and encapsulation with a Java SE mindset</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
A meta-annotation is any annotation class annotated with @Metatype. The other annotations used on the meta-annotation become part of its definition. If any of those annotations happen to also be meta-annotations, they are unrolled as well and their annotations become part of the definition.</div>
<h2 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-width: 0px 0px 1px; cursor: text; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 24px; margin: 20px 0px 10px; padding: 0px; position: relative;">
<a class="anchor" href="https://github.com/dblevins/metatypes/#metatype" name="metatype" style="border: 0px; bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>@Metatype</h2>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; padding: 0px;">
The recursion that is the meta-annotation concept only happens when an annotation is marked as a <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@javax.annotation.Metatype</code>.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
When <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Metatype</code> is seen the basic contract is "carry the surrounding annotations forward". When a class, method or other target uses an annotation annotated with <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Metatype</code> the annotations on that annotation are "unrolled" or carried forward and effectively placed on that class, method or other target as if they were explicitly declared.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
If any of the annotations that are carried forward also are annotated with <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Metatype</code> the recursion continues. The result is a simple algorithm or design pattern that provides inheritance or reuse in a way that is not specific to any domain, API, or specification.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
APIs and specifications can choose to formally adopt annotation reuse in this fashion, but the core concept and implementations of<code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Metatype</code> do not need to be expanded to support these APIs or specifications.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
The simple elegance of this not being domain specific is that it could be used to combine several annotations from different specifications into one reusable annotation. Say JAX-RS <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@PathParam("id")</code> with Bean Validation <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@NotNull</code> to create a new annotation called <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@ValidId</code>.</div>
<h2 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-width: 0px 0px 1px; cursor: text; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 24px; margin: 20px 0px 10px; padding: 0px; position: relative;">
<a class="anchor" href="https://github.com/dblevins/metatypes/#creating-meta-annotations" name="creating-meta-annotations" style="border: 0px; bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Creating Meta-Annotations</h2>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; padding: 0px;">
If the annotation in question can be applied to <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">ElementType.ANNOTATION_TYPE</code> or <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">ElementType.TYPE</code>, creating a meta-annotation version of it is quite easy.</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); color: #333333; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><code style="background-color: transparent; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: none; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px; padding: 0px;">@TransactionManagement(TransactionManagementType.CONTAINER)
@Metatype
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ContainerManagedTransactions {
}
</code></pre>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
When the annotation in question cannot be applied to <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">ElementType.ANNOTATION_TYPE</code> or <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">ElementType.TYPE</code>, things get interesting. This is where meta-annotations depart from things like <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Stereotype</code>. The goal of meta-annotations is to be completely generic and not specific to any one domain or API. A such, you cannot really require all existing APIs change to allow for meta-annotations. The goal is that meta-annotations can be used generically and do not need to be "designed" into an API.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
To allow annotations that apply to <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">FIELD</code>, <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">METHOD</code>, <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">PARAMETER</code>, <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">CONSTRUCTOR</code>, <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">LOCAL_VARIABLE</code>, or <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">PACKAGE</code>, as well as any other location where annotations may be applied in the future a compromise is made.</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); color: #333333; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><code style="background-color: transparent; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: none; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px; padding: 0px;">import javax.ejb.Schedule;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Metatype
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Daily {
public static class $ {
@Daily
@Schedule(second = "0", minute = "0", hour = "0", month = "*", dayOfWeek = "*", year = "*")
public void method() {
}
}
}
</code></pre>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
An inner class named <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">$</code>. This is enough to bind together the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Daily</code> and <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Schedule</code> in the context to which they both apply.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
Ugly but effective. Alternate proposals welcome.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
The above is considered the public API portion of the meta-annotation concept.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
The concept itself is born out of standards based systems like EJB and CDI where annotation processing is invisible to the application itself. In those settings the above is enough and no additional APIs would be needed to support meta-annotations in standard APIs.</div>
<h1 style="-webkit-font-smoothing: antialiased; border: 0px; cursor: text; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 28px; margin: 20px 0px 10px; padding: 0px; position: relative;">
<a class="anchor" href="https://github.com/dblevins/metatypes/#under-the-covers" name="under-the-covers" style="border: 0px; bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Under the covers</h1>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; padding: 0px;">
The "guts" of this particular implementation is designed to look and feel as much like the reflection API as possible. Obviously, with VM level control, you could do much better. A clean Java SE API might be just what is needed and its very possible that meta-annotations should really be a Java SE concept.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
Here's a glimpse as to how things can look under the covers:</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); color: #333333; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><code style="background-color: transparent; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: none; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px; padding: 0px;">final java.lang.reflect.AnnotatedElement annotated = new org.metatype.MetaAnnotatedClass(Triangle.class);
assertNotNull(annotated);
assertTrue(annotated.isAnnotationPresent(Color.class));
assertTrue(annotated.getAnnotation(Color.class) != null);
assertTrue(!contains(Color.class, annotated.getDeclaredAnnotations()));
assertTrue(contains(Color.class, annotated.getAnnotations()));
assertEquals("red", annotated.getAnnotation(Color.class).value());
assertTrue(annotated.isAnnotationPresent(Red.class));
assertTrue(annotated.getAnnotation(Red.class) != null);
assertTrue(!contains(Red.class, annotated.getDeclaredAnnotations()));
assertTrue(contains(Red.class, annotated.getAnnotations()));
assertTrue(annotated.isAnnotationPresent(Crimson.class));
assertTrue(annotated.getAnnotation(Crimson.class) != null);
assertTrue(contains(Crimson.class, annotated.getDeclaredAnnotations()));
assertTrue(contains(Crimson.class, annotated.getAnnotations()));
</code></pre>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
The application classes would look like so:</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); color: #333333; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><code style="background-color: transparent; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: none; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px; padding: 0px;">@Crimson
// -> @Red -> @Color
public static class Triangle {
}
@Metatype
@Color("red")
// one level deep
@Target(value = {TYPE})
@Retention(value = RUNTIME)
public static @interface Red {
}
@Metatype
@Red
// two levels deep
@Target(value = {TYPE})
@Retention(value = RUNTIME)
public static @interface Crimson {
}
</code></pre>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
<span style="font-size: 28px;"><br />Best Practices</span></div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; padding: 0px;">
It is recommended to have an <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">api</code> package or some other package where "approved' annotations are defined and to prohibit usage of the non-meta versions of those annotations. All the real configuration will then be centralized in the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">api</code> package and changes to the values of those annotations will be localized to that package and automatically be reflected throughout the application.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
An interesting side-effect of this approach is that if the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">api</code> package where the meta-annotation definitions exist is kept in a separate jar as well, then one can effectively change the configuration of an entire application by simply replacing the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">api</code> jar.</div>
<h1 style="-webkit-font-smoothing: antialiased; border: 0px; cursor: text; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 28px; margin: 20px 0px 10px; padding: 0px; position: relative;">
<a class="anchor" href="https://github.com/dblevins/metatypes/#future-concepts" name="future-concepts" style="border: 0px; bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>Future concepts</h1>
<h2 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-width: 0px 0px 1px; cursor: text; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 24px; margin: 20px 0px 10px; padding: 0px; position: relative;">
<a class="anchor" href="https://github.com/dblevins/metatypes/#xml-overriding" name="xml-overriding" style="border: 0px; bottom: 0px; color: #4183c4; cursor: pointer; display: block; left: 0px; margin: 0px 0px 0px -30px; padding: 0px 0px 0px 30px; position: absolute; text-decoration: initial; top: 0px;"></a>XML Overriding</h2>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; padding: 0px;">
The unrolling of meta-annotations happens under the covers. In that same vein, so could the concept of overriding.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
The above <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Red</code> annotation might theoretically be overridden via xml as follows:<br />
<br />
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><code style="background-color: transparent; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: none; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px; padding: 0px;"><org.superbiz.api.Red>
<org.superbiz.api.Color value="dark red"/>
</org.superbiz.api.Red></code></pre>
</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
Or take more complex meta-annotation definition like the following:</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); color: #333333; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><code style="background-color: transparent; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: none; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px; padding: 0px;">package org.superbiz.corn.meta.api;
import javax.ejb.Schedule;
import javax.ejb.Schedules;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Metatype
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PlantingTime {
public static interface $ {
@PlantingTime
@Schedules({
@Schedule(month = "5", dayOfMonth = "20-Last", minute = "0", hour = "8"),
@Schedule(month = "6", dayOfMonth = "1-10", minute = "0", hour = "8")
})
public void method();
}
}
</code></pre>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
This might theoretically be overridden as:<br />
<br />
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><code style="background-color: transparent; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: none; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px; padding: 0px;"><org.superbiz.corn.meta.api.PlantingTime>
<javax.ejb.Schedules>
<value>
<javax.ejb.Schedule month="5" dayOfMonth="15-Last" minute="30" hour="5"/>
<javax.ejb.Schedule month="6" dayOfMonth="1-15" minute="30" hour="5"/>
</value>
</javax.ejb.Schedules>
</org.superbiz.corn.meta.api.PlantingTime></code></pre>
<br />
<span style="font-size: 24px;">Merging or Aggregating definitions</span></div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; padding: 0px;">
Certain annotations take lists and are designed to be multiples. In the current definition of meta-annotations, the following is illegal.</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); color: #333333; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><code style="background-color: transparent; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: none; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px; padding: 0px;">@RolesAllowed({"Administrator", "SuperUser"})
@Metatype
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Admins {
}
@RolesAllowed({"Employee", "User"})
@Metatype
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Users {
}
public static class MyBean {
@Admin
@User
public void doSomething() {
// ...
}
}
</code></pre>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
Here the @Admin and @User annotation each resolve to @RolesAllowed. Since only one @RolesAllowed annotation is allowed on the method per the Java language specification, this results in an error.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
The intention is clear however and aggregating metadata together in this way is natural.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
A theoretical way to support something like this is with an annotation to describe that this aggregation is intended and desired. Note the addition of the theoretical <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Merge</code> annotation.</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); color: #333333; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><code style="background-color: transparent; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: none; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px; padding: 0px;">@RolesAllowed({"Administrator", "SuperUser"})
@Metatype
@Merge
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Admins {
}
@RolesAllowed({"Employee", "User"})
@Metatype
@Merge
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Users {
}
public static class MyBean {
@Admin
@User
public void doSomething() {
// ...
}
}
</code></pre>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
A new <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@RolesAllowed</code> annotation would be created containing the list <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">{"Administrator", "SuperUser", "Employee", "User"}</code> and that would represent the final <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@RolesAllowed</code> usage for the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">doSomething()</code> method.</div>
<div>
<br /></div>David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com123tag:blogger.com,1999:blog-7974209436265167833.post-74263480942958420902011-09-30T21:19:00.000-07:002011-09-30T21:19:39.509-07:00JavaOne 2011 scheduleJavaOne is next week and as usual I will be there. I'm a bit busier than usual this year, but as always I'm more than happy to get together with anyone. In fact it's my favorite part of JavaOne, so please do <a href="mailto:david.blevins@gmail.com">reach out</a>.<br />
<br />
Here's my speaking schedule:<br />
<br />
<br />
<div class="p2">Session ID: 23166</div><div class="p2">Session Title: Meet the Experts: EJB 3.2 Expert Group</div><div class="p2">Venue / Room: Hilton San Francisco - Imperial Ballroom A</div><div class="p2">Date and Time: 10/3/11, 21:00 - 21:45</div><div class="p1"><br />
</div><div class="p2">Session ID: 25244</div><div class="p2">Session Title: EJB with Meta-annotations</div><div class="p2">Venue / Room: Parc 55 - Powell I/II-</div><div class="p2">Date and Time: 10/4/11, 17:30 - 18:15</div><div class="p1"><br />
</div><div class="p2">Session ID: 23423</div><div class="p2">Session Title: The Road to Java EE 7: Is It All About the Cloud?</div><div class="p2">Venue / Room: Hilton San Francisco - Imperial Ballroom A</div><div class="p2">Date and Time: 10/5/11, 11:30 - 12:30</div><div class="p1"><br />
</div><div class="p2">Session ID: 25209</div><div class="p2">Session Title: Fun with EJB 3.1 and OpenEJB</div><div class="p2">Venue / Room: Hilton San Francisco - Golden Gate 3/4/5</div><div class="p2">Date and Time: 10/5/11, 13:00 - 14:00</div><div class="p1"><br />
</div><div class="p2">Session ID: 19941</div><div class="p2">Session Title: CDI Today and Tomorrow</div><div class="p2">Venue / Room: Hilton San Francisco - Imperial Ballroom A</div><div class="p2">Date and Time: 10/6/11, 12:30 - 13:30</div><div class="p1"><br />
</div><div class="p2">Session ID: 23680</div><div class="p2">Session Title: Apache TomEE Java EE 6 Web Profile</div><div class="p2">Venue / Room: Hilton San Francisco - Golden Gate 3/4/5</div><div class="p2">Date and Time: 10/6/11, 11:00 - 12:00</div><div class="p1"><br />
</div>David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com28tag:blogger.com,1999:blog-7974209436265167833.post-57196082746740536252011-04-07T22:38:00.001-07:002011-04-08T08:59:15.694-07:00Final is my favorite Java keywordFinal is my favorite keyword and modifier in Java. For fields, love it even more than private. Think about it, you don't even need <i>private</i><b> </b>on your field if it's final. Not with a truly non-mutable data type at least, so collections and things of that nature excluded of course.<br />
<div><div><br />
</div><div>In fact I wish <i>final</i> was the default modifier for all my fields, variables, and parameters. You should have to announce your intention to overwrite an already initialized object reference. After years, I find it is a rarity.</div><div><br />
</div><div>There is nothing worse that digging through a large 500 line function and not being able to see what is changed and where. Even more frustrating when you go to extract a method from said too-large codeblock and cannot do so easily because of the sprawled out variable declarations and initializations and the occasional "I like this variable name so I'll reuse the reference" laziness. </div><div><br />
</div><div>The trouble is it looks so terrible when used properly, which should be almost everywhere! It looks pretty satisfying on fields, but over all parameters and variables it gets to be a little much. It can actually make it harder to find the non-final object references. And if you find one, was it intentional or just overlooked? Change it and find out I guess.</div><div><br />
</div><div>That is why one of my biggest wishes for the Java language is that <i>final</i> be the default and there to be a <i>mutable</i> or similar keyword for the handful of times you need it. It would be an excellent aid to readers of your code, "watch out this thing is going to change." Compilers could even check to see if you have flagged something <i>mutable</i> and aren't actually mutating it. That should be a compile error for variables and parameters, perhaps not for fields though.</div><div><br />
</div><div>Obviously we can't exactly do that ... not so directly.</div><div><br />
</div><div>We have some advantages now we didn't have when Java was created. Annotations. When Java was created there had to be long and deliberate thinking as to what the defaults should be. Everyone would have to live with them and they'd last forever. These days, however, a simple annotation or two on a Java source file could serve as a clean way to change such defaults in an obvious and documented way that can make the code in question far easier to read. It would be syntactic sugar of course and that annotation and the defaults it specifies would compile away just as imports do.</div><div><br />
</div></div><div>A small bit of sugar with big payoff in ease and readability.</div>David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com30tag:blogger.com,1999:blog-7974209436265167833.post-67168471544279856142011-03-18T20:08:00.000-07:002011-04-08T09:34:41.874-07:00Reflection API gripesjava.lang.Method and java.lang.Constructor are strikingly close in concept. For all intents and purposes Constructors are little more than syntactic sugar. Yet there is no API acknowledgement of many their similarities.<br />
<br />
Yes, they share some common interfaces and the same super class, but when you peal away the methods that are not accounted for by interfaces and superclasses, here's what you get:<br />
<br />
<b>java.lang.reflect.Constructor</b><br />
<blockquote>public T newInstance(Object ... initargs)<br />
public Annotation[][] getParameterAnnotations()<br />
public Class[] getExceptionTypes()<br />
public Class[] getParameterTypes()<br />
public String toGenericString()<br />
public Type[] getGenericExceptionTypes()<br />
public Type[] getGenericParameterTypes()<br />
public boolean isVarArgs()</blockquote><b>java.lang.reflect.Method</b><br />
<blockquote>public Object getDefaultValue()<br />
public Object invoke(Object obj, Object... args)<br />
public Class getReturnType()<br />
public boolean isBridge()<br />
public Type getGenericReturnType()<br />
public Annotation[][] getParameterAnnotations()<br />
public Class[] getExceptionTypes()<br />
public Class[] getParameterTypes()<br />
public String toGenericString()<br />
public Type[] getGenericExceptionTypes()<br />
public Type[] getGenericParameterTypes()<br />
public boolean isVarArgs()</blockquote>Of the methods, few are actually truly unique to that class type. Those would be the following methods<br />
<br />
<b>java.lang.reflect.Constructor</b><br />
<blockquote>public T newInstance(Object ... initargs)</blockquote><b>java.lang.reflect.Method</b><br />
<blockquote>public Object getDefaultValue()<br />
public Object invoke(Object obj, Object... args)<br />
public Class getReturnType()<br />
public boolean isBridge()<br />
public Type getGenericReturnType()</blockquote>A far smaller number, especially for Constructor. The remaining methods shared, but not accounted for in any superclass or interface, are:<br />
<br />
<b>Identical</b><br />
<blockquote>public Annotation[][] getParameterAnnotations()<br />
public Class[] getExceptionTypes()<br />
public Class[] getParameterTypes()<br />
public String toGenericString()<br />
public Type[] getGenericExceptionTypes()<br />
public Type[] getGenericParameterTypes()<br />
public boolean isVarArgs()</blockquote>These methods are just begging for an interface. Perhaps <b>ParameterizedMember</b> would be a good name?<br />
<br />
Granted most Java development doesn't involve the reflection api, but those of us that do use it would really appreciate being thrown a bone. Especially with the growing amount of code and APIs that involve annotations. An interface similar to AnnotatedElement that can contain this critical getParameterAnnotations method would just be wonderful.<br />
<br />
I'm quite certain there must have been some kind of debate. Likely one that ended in, "it's not really that important." Would love to hear from anyone involved.<br />
<br />
I personally can't think of any downside to allowing us developers who deal with the guts of supporting annotation based APIs to get a little polymorphism in this are of the reflection API.<br />
<br />
A bottle of my favorite rum to whomever can get this into Java 7.David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com26tag:blogger.com,1999:blog-7974209436265167833.post-68797649846838338792010-10-01T15:58:00.000-07:002013-02-07T03:56:11.514-08:00EJB.next Connector/Bean API : JAX-RS and beyond<span style="background-color: white; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px;">It isn't commonly known that MessageDrivenBeans (MDBs) are not directly tied to the Java Message Service (JMS). In fact, they are tied to the Java EE Connector Architecture. It's even less commonly known that MDBs are not necessarily asynchronous. It's really the Connector that drives the communication style.</span><br />
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
Overall, it is a very cool model that does allow for some pretty impressive and standard extension to any compliant Java EE platform. It is, however, incredibly underused. With a few changes to the model, it could be made to support even things like JAX-RS. Let's break it down.</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
The touchpoints between the Connector and the MDB are the <strong style="border: 0px; margin: 0px; padding: 0px;">ActivationSpec/ActivationConfig</strong> and the <strong style="border: 0px; margin: 0px; padding: 0px;">MessageListener</strong> interface. Using a fictitious "Email" Connector idea, let's see how this looks.</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
<strong style="border: 0px; margin: 0px; padding: 0px;">EmailConsumer (MessageListener) interface</strong>*</div>
<div class="highlight" style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin: 0px; padding: 0px;">
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><span class="kn" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">package</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">org</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">.</span><span class="na" style="border: 0px; color: teal; margin: 0px; padding: 0px;">superemail</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">.</span><span class="na" style="border: 0px; color: teal; margin: 0px; padding: 0px;">connector</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">;</span>
<span class="c1" style="border: 0px; color: #999988; font-style: italic; margin: 0px; padding: 0px;">// other imports...</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">interface</span> <span class="nc" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">EmailConsumer</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kt" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">void</span> <span class="nf" style="border: 0px; color: #990000; font-weight: bold; margin: 0px; padding: 0px;">receiveEmail</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="n" style="border: 0px; margin: 0px; padding: 0px;">Properties</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">headers</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">,</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">String</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">body</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">);</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
</pre>
</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
<strong style="border: 0px; margin: 0px; padding: 0px;">EmailAccountInfo (ActivationSpec) class</strong></div>
<div class="highlight" style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin: 0px; padding: 0px;">
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><span class="kn" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">package</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">org</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">.</span><span class="na" style="border: 0px; color: teal; margin: 0px; padding: 0px;">superemail</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">.</span><span class="na" style="border: 0px; color: teal; margin: 0px; padding: 0px;">connector</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">;</span>
<span class="cm" style="border: 0px; color: #999988; font-style: italic; margin: 0px; padding: 0px;">/**</span>
<span class="cm" style="border: 0px; color: #999988; font-style: italic; margin: 0px; padding: 0px;"> * This class is basically an old-style JavaBean with get/set for each property</span>
<span class="cm" style="border: 0px; color: #999988; font-style: italic; margin: 0px; padding: 0px;"> */</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">class</span> <span class="nc" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">EmailAccountInfo</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">implements</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">javax</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">.</span><span class="na" style="border: 0px; color: teal; margin: 0px; padding: 0px;">resource</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">.</span><span class="na" style="border: 0px; color: teal; margin: 0px; padding: 0px;">spi</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">.</span><span class="na" style="border: 0px; color: teal; margin: 0px; padding: 0px;">ActivationSpec</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">private</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">String</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">address</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">;</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">String</span> <span class="nf" style="border: 0px; color: #990000; font-weight: bold; margin: 0px; padding: 0px;">getAddress</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">()</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="k" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">return</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">address</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">;</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kt" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">void</span> <span class="nf" style="border: 0px; color: #990000; font-weight: bold; margin: 0px; padding: 0px;">setAddress</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="n" style="border: 0px; margin: 0px; padding: 0px;">String</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">address</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">)</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="k" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">this</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">.</span><span class="na" style="border: 0px; color: teal; margin: 0px; padding: 0px;">address</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">=</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">address</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">;</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kt" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">void</span> <span class="nf" style="border: 0px; color: #990000; font-weight: bold; margin: 0px; padding: 0px;">validate</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">()</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">throws</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">InvalidPropertyException</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
</pre>
</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
That's it for the Connector (aside from the Connector itself). I have left out a little detail on the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">ActivationSpec</code>, we'll cover that later.</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
Now for the MDB's side of things. The MDB needs to implement the Connector's <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">EmailConsumer</code> interface and configure the Connector's<code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">EmailAccountInfo</code> JavaBean which is done via the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">activation-config</code> tag of the ejb-jar.xml or via <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@ActivationConfigProperty</code>annotations in the <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@MessageDriven</code> declaration.</div>
<div class="highlight" style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin: 0px; padding: 0px;">
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@MessageDriven</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="n" style="border: 0px; margin: 0px; padding: 0px;">activationConfig</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">=</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span><span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@ActivationConfigProperty</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span>
<span class="n" style="border: 0px; margin: 0px; padding: 0px;">propertyName</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">=</span> <span class="s" style="border: 0px; color: #dd1144; margin: 0px; padding: 0px;">"address"</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">,</span>
<span class="n" style="border: 0px; margin: 0px; padding: 0px;">propertyValue</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">=</span> <span class="s" style="border: 0px; color: #dd1144; margin: 0px; padding: 0px;">"dblevins@apache.org"</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">)</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">})</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">class</span> <span class="nc" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">EmailBean</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">implements</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">EmailConsumer</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@PostConstruct</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kt" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">void</span> <span class="nf" style="border: 0px; color: #990000; font-weight: bold; margin: 0px; padding: 0px;">init</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">()</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kt" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">void</span> <span class="nf" style="border: 0px; color: #990000; font-weight: bold; margin: 0px; padding: 0px;">receiveEmail</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="n" style="border: 0px; margin: 0px; padding: 0px;">Properties</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">headers</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">,</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">String</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">body</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">)</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="c1" style="border: 0px; color: #999988; font-style: italic; margin: 0px; padding: 0px;">// do your thing!</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
</pre>
</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
<strong style="border: 0px; margin: 0px; padding: 0px;">Done</strong>. Those are the basics. The Connector supplies a <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">MessageListener</code> interface and an <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">ActivationConfig</code> JavaBean, the MDB implements the interface and configures the JavaBean via the loosely-typed <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@ActivationConfigProperty</code>.</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
There are a few things that prevent this model from reaching its true potential:</div>
<ul style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin: 15px 0px; padding: 0px 0px 0px 30px;">
<li style="border: 0px; margin: 0px; padding: 0px;">Metadata is loosely typed in the bean code</li>
<li style="border: 0px; margin: 0px; padding: 0px;">Only class-level metadata is allowed, not method-level</li>
<li style="border: 0px; margin: 0px; padding: 0px;">Requiring an interface can limit expressiveness</li>
</ul>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
Let's see how life might look if we <strong style="border: 0px; margin: 0px; padding: 0px;">eliminate the JavaBean</strong> and allow the Connector to <strong style="border: 0px; margin: 0px; padding: 0px;">instead supply an annotation</strong>.</div>
<div class="highlight" style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin: 0px; padding: 0px;">
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><span class="kn" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">package</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">org</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">.</span><span class="na" style="border: 0px; color: teal; margin: 0px; padding: 0px;">superemail</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">.</span><span class="na" style="border: 0px; color: teal; margin: 0px; padding: 0px;">connector</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">;</span>
<span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@Target</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="n" style="border: 0px; margin: 0px; padding: 0px;">TYPE</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">)</span>
<span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@Retention</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="n" style="border: 0px; margin: 0px; padding: 0px;">RUNTIME</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">)</span>
<span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@javax.resource.annotation.ActivationSpec</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@interface</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">EmailAccountInfo</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="n" style="border: 0px; margin: 0px; padding: 0px;">String</span> <span class="nf" style="border: 0px; color: #990000; font-weight: bold; margin: 0px; padding: 0px;">address</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">();</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
</pre>
</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
<em style="border: 0px; margin: 0px; padding: 0px;">Side Note: The original javax.resource.spi.ActivationSpec interface has a 'validate()' method on it to validate the JavaBean. A clear update to that part of the API would be to instead use the Bean Validation API.</em></div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
Which gives us a bean that might look like this:</div>
<div class="highlight" style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin: 0px; padding: 0px;">
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@MessageDriven</span>
<span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@EmailAccountInfo</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="n" style="border: 0px; margin: 0px; padding: 0px;">address</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">=</span> <span class="s" style="border: 0px; color: #dd1144; margin: 0px; padding: 0px;">"dblevins@apache.org"</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">)</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">static</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">class</span> <span class="nc" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">EmailBean</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">implements</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">EmailConsumer</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@PostConstruct</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kt" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">void</span> <span class="nf" style="border: 0px; color: #990000; font-weight: bold; margin: 0px; padding: 0px;">init</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">()</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kt" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">void</span> <span class="nf" style="border: 0px; color: #990000; font-weight: bold; margin: 0px; padding: 0px;">receiveEmail</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="n" style="border: 0px; margin: 0px; padding: 0px;">Properties</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">headers</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">,</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">String</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">body</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">)</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="c1" style="border: 0px; color: #999988; font-style: italic; margin: 0px; padding: 0px;">// do your thing!</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
</pre>
</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
Now we're getting somewhere!</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
Ok, let's get rid of that message listener interface and image our Email Connector uses a very JAX-RS inspired API for consuming emails. If you know a little JAX-RS you'll see where I'm going with this.</div>
<div class="highlight" style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin: 0px; padding: 0px;">
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@MessageDriven</span>
<span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@EmailAccountInfo</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="n" style="border: 0px; margin: 0px; padding: 0px;">address</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">=</span> <span class="s" style="border: 0px; color: #dd1144; margin: 0px; padding: 0px;">"dblevins@apache.org"</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">)</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">static</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">class</span> <span class="nc" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">EmailBean</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@PostConstruct</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kt" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">void</span> <span class="nf" style="border: 0px; color: #990000; font-weight: bold; margin: 0px; padding: 0px;">init</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">()</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
<span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@Deliver</span> <span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@Header</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="s" style="border: 0px; color: #dd1144; margin: 0px; padding: 0px;">"Subject: {subject}"</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">)</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kt" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">void</span> <span class="nf" style="border: 0px; color: #990000; font-weight: bold; margin: 0px; padding: 0px;">receiveEmail</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@HeaderParam</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="s" style="border: 0px; color: #dd1144; margin: 0px; padding: 0px;">"subject"</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">)</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">String</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">subject</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">,</span> <span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@Body</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">String</span> <span class="n" style="border: 0px; margin: 0px; padding: 0px;">body</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">)</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="c1" style="border: 0px; color: #999988; font-style: italic; margin: 0px; padding: 0px;">// do your thing!</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
</pre>
</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
Pretty neat, huh?</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
<em style="border: 0px; margin: 0px; padding: 0px;">Side note: For the rare few of you that speak Connector implementation, instead of giving your Resource Adapter a MessageEndpoint that is a proxy that only implements the MessageListener interface and the standard MessageEndpoint interface, the Container would instead give you an @LocalBean proxy that also implements MessageEndpoint. If you're thinking that an API like that would be great to use... imagine with the above changes you could <strong style="border: 0px; margin: 0px; padding: 0px;">make</strong> that API ... and use it in <strong style="border: 0px; margin: 0px; padding: 0px;">any</strong> compliant Java EE platform. Maybe even submit your own JSR if you came up with something great.</em></div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
Truthfully speaking, it's the Connector who controls the lifecycle of the bean (MDB). The Connector API already allows for the Connector to say to the Container, "create me a bean" and "destroy this bean". So really, we don't need <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@MessageDriven</code> anymore. Instead we can do this:</div>
<div class="highlight" style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin: 0px; padding: 0px;">
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 13px; line-height: 19px; margin-bottom: 15px; margin-top: 15px; overflow: auto; padding: 6px 10px;"><span class="kn" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">import</span> <span class="nn" style="border: 0px; color: #555555; margin: 0px; padding: 0px;">javax.annotation.ManagedBean</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">;</span>
<span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@ManagedBean</span>
<span class="nd" style="border: 0px; margin: 0px; padding: 0px;">@EmailAccountInfo</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">(</span><span class="n" style="border: 0px; margin: 0px; padding: 0px;">address</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">=</span> <span class="s" style="border: 0px; color: #dd1144; margin: 0px; padding: 0px;">"dblevins@apache.org"</span><span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">)</span>
<span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">public</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">static</span> <span class="kd" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">class</span> <span class="nc" style="border: 0px; color: #445588; font-weight: bold; margin: 0px; padding: 0px;">EmailBean</span> <span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">{</span>
<span class="c1" style="border: 0px; color: #999988; font-style: italic; margin: 0px; padding: 0px;">// ....</span>
<span class="o" style="border: 0px; font-weight: bold; margin: 0px; padding: 0px;">}</span>
</pre>
</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
That's a little more modern and perhaps a bit clearer.</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
At this point, we have a generic API to hook arbitrary "Connectors" up to arbitrary "Beans" that are managed by a container. Were this the case when JAX-RS was created, they wouldn't have had to put so much effort into duplicating all the services that people who have managed beans expect: injection of resources, lifecycle callbacks, interceptors.</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
<strong style="border: 0px; margin: 0px; padding: 0px;">Summary:</strong> A few improvements to the expressiveness of the metadata passed between a Bean and its Connector could kick the MDB/Connector model into the mainstream as was the intention of the API from the beginning. New specifications could be created based on this model and be introduced <strong style="border: 0px; margin: 0px; padding: 0px;">incrementally</strong> as they are developed and needed.</div>
<div style="background-color: white; border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 15px; padding: 0px;">
The impact of fully opening up the Bean metadata to the Connector is quite deep and wide and likely not something that will scream at you immediately. Ask yourself, could something like the new EJB 3.1 <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Schedule</code> API have been done with a Connector/Bean model like this? To some extent probably it could. Certainly there already existed a few Quartz Connectors out there prior to the introduction of <code style="background-color: #f8f8f8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(234, 234, 234); font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap;">@Schedule</code>.</div>
<div style="background-color: white; border: 0px; margin-top: 15px; padding: 0px;">
<div style="color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px;">
Take a moment to daydream. What kind of Connectors could you create with this model?</div>
<br />
<span style="color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><b>UPDATE - Feb 7th, 2013</b></span></span><br />
<span style="color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<span style="color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif;"><span style="font-size: 14px; line-height: 22px;">Save this proposal. </span></span><span style="color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px;">Without more voices it will be <b>delayed</b> till Java EE 8. Let's not wait 4 years! <b>Take action</b> and celebrate the Java Community Process openness by showing your support for including this in Java EE 7. Act now.</span><br />
<span style="color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px;"><br /></span>
<span style="color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif;"><span style="font-size: 14px; line-height: 22px;">VOTE AND COMMENT HERE <a href="http://java.net/jira/browse/EJB_SPEC-60">http://java.net/jira/browse/EJB_SPEC-60</a></span></span><br />
<span style="color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif;"><span style="font-size: 14px; line-height: 22px;"><br /></span></span>
<br />
<br />
<div style="color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px;">
<br /></div>
</div>
David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com337tag:blogger.com,1999:blog-7974209436265167833.post-1127767970494707702010-09-24T13:55:00.000-07:002010-10-01T17:06:07.326-07:00Interceptor Advisor Pattern<p>
Your standard CDI/EJB Interceptor example uses a logger as an around advice. Generally this gives you an interceptor that looks like so:
</p><pre>
@Log
public class LoggingInterceptor {
private java.util.logging.Logger logger =
java.util.logging.Logger.getLogger("theLogger");
@AroundInvoke
public Object intercept(InvocationContext context) throws Exception {
logger.info("" + context.getMethod().getName());
return context.proceed();
}
}
</pre><p>As of the Interceptors 1.1 spec, you can bind that to a bean via creating our own javax.interceptor.InterceptorBinding annotation. In our example, we've created one called <i>@Log</i>:
</p><pre>
@InterceptorBinding
@Target(value = {ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}
</pre><p>
Now we just apply that to the bean as follows.
</p><pre>
@Log
public class FooBean {
public void somethingCommon(){
//...
}
public void somethingImportant() {
//...
}
public void somethingNoteworthy() {
//...
}
}
</pre><p>
Great! Now we are done. Every time that bean is invoked, the LoggerInterceptor will issue a log message on info level. Aren't interceptors wonderful! End of story, right? Not quite.
</p><p>
Fundamentally, our example is still very contrived. Who wants to log everything on the same level?
</p><p>
Here is a little <b>pattern</b> that you can use to better advise your LoggerInterceptor around advice. First, we create a couple new annotations for log levels: @Fine and @Info
</p><pre>
@Target(value = {ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Fine {
}
@Target(value = {ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Info {
}
</pre><p>
Then we apply those to the bean...
</p><pre>
@Log
public class FooBean {
public void somethingCommon(){
//...
}
@Info
public void somethingImportant() {
//...
}
@Fine
public void somethingNoteworthy() {
//...
}
}
</pre><p>
Now we alter our LoggerInterceptor to check for our new annotations and alter its behavior.
</p><pre>
@Log
public class LoggingInterceptor {
private java.util.logging.Logger logger =
java.util.logging.Logger.getLogger("theLogger");
@AroundInvoke
public Object intercept(InvocationContext context) throws Exception {
final Method method = context.getMethod();
if (method.isAnnotationPresent(Info.class)) {
return info(context);
} else if (method.isAnnotationPresent(Fine.class)) {
return fine(context);
} else {
return finest(context);
}
}
public Object info(InvocationContext context) throws Exception {
logger.info("" + context.getMethod().getName());
return context.proceed();
}
public Object fine(InvocationContext context) throws Exception {
logger.finest("" + context.getMethod().getName());
return context.proceed();
}
public Object finest(InvocationContext context) throws Exception {
logger.finest("" + context.getMethod().getName());
return context.proceed();
}
}
</pre><p>
<b>Done!</b> Now we have a pattern to advise our interceptor!
</p><p>
This will totally work today. But this pattern is so simple and elegant what if we could support it right inside the container? Imagine how cool it would be if we could just do this in our interceptor and the container would just figure it out.
</p><pre>
@Log
public class LoggingInterceptor {
private java.util.logging.Logger logger =
java.util.logging.Logger.getLogger("theLogger");
@Info
public Object info(InvocationContext context) throws Exception {
logger.info("" + context.getMethod().getName());
return context.proceed();
}
@Fine
public Object fine(InvocationContext context) throws Exception {
logger.finest("" + context.getMethod().getName());
return context.proceed();
}
@AroundInvoke
public Object finest(InvocationContext context) throws Exception {
logger.finest("" + context.getMethod().getName());
return context.proceed();
}
}
</pre><p>
Definitely something I plan to propose for the next round of specifications....
</p><p>
As always, comments welcome.
</p>David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com25tag:blogger.com,1999:blog-7974209436265167833.post-40554897678411531472010-09-21T16:22:00.000-07:002010-10-01T17:06:26.684-07:00EJB.next Interceptor Improvements - Method signatures<p>
Interceptors are great, but some parts of them are odd when applied practically. For as fundamentally reflective as interceptors are, it isn't possible to pass all interceptable calls through a single method, like so:
</p><pre>
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.PostActivate;
import javax.ejb.PrePassivate;
import javax.interceptor.AroundInvoke;
import javax.interceptor.AroundTimeout;
import javax.interceptor.InvocationContext;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
public class StatsInterceptor {
@PostConstruct
@PreDestroy
@PrePassivate
@PostActivate
@AroundInvoke
@AroundTimeout
public Object intercept(InvocationContext context) throws Exception {
final long start = System.nanoTime();
try {
return context.proceed();
} finally {
final long nanos = System.nanoTime() - start;
final long millis = MILLISECONDS.convert(nanos, NANOSECONDS);
System.out.println("invoke time "+ millis +" milleseconds");
}
}
}
</pre><p>
This looks very nice, but currently is <b>not legal</b>. The spec currently requires different formats for callback-based interception vs business-method-based interception. This sounds like a nice safe and conservative rule, but is it benefiting users? Not really. Let's see what we have to do to our interceptor to make it compliant.
<p/><p>
First, callback intercept methods are not allowed to return anything and must have a <b>void</b> return type. The logic here is that since callbacks have no return value, interceptors should know this. So fine, let's work around that and just make a new method:
</p><pre>
@PostConstruct
@PreDestroy
@PrePassivate
@PostActivate
@AroundInvoke
public void callback(InvocationContext context) throws Exception {
intercept(context);
}
</pre><p>
Second, callback intercept methods are <b>not allowed to throw any exceptions</b>. Again the rationale is that callbacks aren't allowed to throw checked exceptions, so interceptors should be aware of that as well. The trick is we can't simply remove the 'throws Exception' clause without doing any extra work. The <b>InvocationContext.proceed() method throws java.lang.Exception</b> but we can't, so we are forced to take responsibility for it. If we just catch and ignore the exception all hell will break loose, so instead we should at least wrap it as a RuntimeException.
</p><pre>
@PostConstruct
@PreDestroy
@PrePassivate
@PostActivate
@AroundTimeout
public void callback(InvocationContext context) {
try {
intercept(context);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
</pre><p>
We've just made a mistake. Did you see it? If there are several interceptors in the chain and all of them wrap the exception like this, when an actual exception is thrown it will end up wrapped N times -- once per interceptor -- before finally reaching the container. Instead, we should at least check if the exception needs wrapping and hope that other interceptors do the same:
</p><pre>
@PostConstruct
@PreDestroy
@PrePassivate
@PostActivate
@AroundTimeout
public void callback(InvocationContext context) {
try {
intercept(context);
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else{
throw new RuntimeException(e);
}
}
}
</pre><p>
Now we're done. Summary: all of the above is boilerplate code you need in any well implemented callback-based interceptor.
</p><p>
What have we achieved? Not much.
</p><p>
In terms of user code, it doesn't help you any to have these restrictions. If you wanted special logic for callback-based interceptor methods you can easily put that annotation on a separate method.
</p><p>
In terms of container code, there's little gain as well. Ultimately, most containers use reflection to kick off the interceptor chain. The java.lang.reflect.Method.invoke() method returns Object and throws InvocationTargetException. Restricting users from returning Object and throwing Exception have no real impact on the container code. It's a callback. Ultimately all exceptions, checked or not, go into the log file and no further and return values are simply ignored.
</p><p>
<b>Summary:</b> The restriction on returning void and throwing Exception should be lifted. For backwards compatibility we can just say this former requirement is now optional and allow interceptor signatures of 'Object <method>(InvocationContext c) throws Exception' even if what is being intercepted is a callback.
</p>David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com18tag:blogger.com,1999:blog-7974209436265167833.post-39576247287117633542010-07-16T14:18:00.000-07:002010-10-01T17:06:57.402-07:00@ApplicationException is evil... sort of<p>
Historically EJB has frowned on RuntimeExceptions. Throwing them results in your transaction getting rolled back and your bean instance being immediately destroyed. You're welcome to try your transaction again ... just as long as you weren't keeping your data in your @Stateful session bean, cause, you know, the container just destroyed that... hope you didn't need it to retry your commit.
</p>
<p>
In EJB 3.0 the @ApplicationException type was added so that beans could throw RuntimeExceptions and not have their beans destroyed and have the choice to rollback any transaction in progress. Great! Only... how do you really use this for built-in exception types? XML you say? Yuk!
</p>
<pre>
<ejb-jar>
<assembly-descriptor>
<application-exception>java.lang.RuntimeExceptions</application-exception>
</assembly-descriptor>
</ejb-jar>
</pre>
<p>
And is the above even a good idea? Definitely not! With something like that you're just asking for trouble. The bad part is that it effectively shuts off transaction exception handling for all beans in the entire application. Currently, though, this is your only option.
</p>
<p>
The problem is it is hard to use this annotation responsibly. It's often too bold and too difficult to take the hard line that a specific exception type is always fine to throw. It is completely lacking in pragmatism. There is no ability for developers to make a more refined choice.
</p>
<p>
Bottom line, it should be possible to specify how you would like a RuntimeException handled for a specific <b>bean</b> or <b>method</b>. Imagine @ApplicationException where modified like so:
</p>
<pre>
@java.lang.annotation.Target({TYPE, METHOD})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
public static @interface ApplicationException {
Class value();
boolean rollback() default false;
}
</pre>
Now, we can do things a little more refined:
<pre>
@LocalBean
public static class OrangeBean {
@ApplicationException(RuntimeException.class)
public void doSomething() {
}
public void doSomethingElse() {
}
}
</pre>
<p>
In the above, the OrangeBean doSomething method would be allowed to throw a RuntimeException without a transaction rollback or the bean instance being destroyed.
</p>
<p>
As well, the annotation could be placed on the class level. Say we have an @Stateful bean that wraps an EXTENDED PersistenceContext so that business logic could more easily be done elsewhere, perhaps by an @Stateless bean that uses Bean-Managed Transactions and wishes to batch process several transactions against the EXTENDED persistence context in a loop:
</p>
<pre>
@Stateful
@ApplicationException(javax.persistence.PersistenceException.class)
@TransactionAttribute(MANDATORY)
public static class EntityManagerWrapper implements EntityManager {
@PersistenceContext(type = EXTENDED)
private EntityManager delegate;
@Override
public void persist(Object o) {
delegate.persist(o);
}
@Override
public <T> T merge(T t) {
return delegate.merge(t);
}
@Override
public void remove(Object o) {
delegate.remove(o);
}
@Override
public <T> T find(Class<T> tClass, Object o) {
return delegate.find(tClass, o);
}
//... and so on
}
</pre>
<p>
The EntityManager API does not throw checked exceptions, only derivatives of javax.persistence.PersistenceException which is itself a RuntimeException. To wrap an EntityManager the bean also need the ability to throw javax.persistence.PersistenceException without causing its destruction and transaction rollback. In that vein, the bean is marked @TransactionAttribute(MANDATORY) so it isn't possible to use the bean without already having a transaction in progress, making it clear that transaction management is not it's responsibility.
</p>
<p>
In another example, say we would like to create a bean that wishes not be destroyed when a RuntimeException is thrown, but it would still like the transactions it starts (via @TransactionAttribute(REQUIRES_NEW)) to be rolled back should a RuntimeException occur.
</p>
<pre>
@Stateful
@TransactionAttribute(REQUIRES_NEW)
@ApplicationException(value = RuntimeException.class, rollback = true)
public static class YellowBean {
public void doSomething() {
}
public void doSomethingElse() {
}
}
</pre>
<p>
Naturally, to make this API work with more than one exception type per method or bean, we would of course need a new @ApplicationExceptions (note the plural) to group several @ApplicationException annotations -- for those that are not annotation-aware, you cannot use the same annotation twice on a type, method, field or any member.
</p>
<pre>
@java.lang.annotation.Target({TYPE, METHOD})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
public static @interface ApplicationExceptions {
ApplicationException[] value() default {};
}
</pre>
With that it would be possible to do all of the above for a few different exception types:
<pre>
@Stateful
public static class RedBean {
@ApplicationExceptions({
@ApplicationException(NumberFormatException.class),
@ApplicationException(ArrayIndexOutOfBoundsException.class),
@ApplicationException(value = RuntimeException.class, rollback = true)
})
public void doSomething() {
}
public void doSomethingElse() {
}
}
</pre>
<p>
In the above the NumberFormatException and ArrayIndexOutOfBoundsException are considered OK and will not cause instance destruction or transaction rollback, however the '@ApplicationException(value = RuntimeException.class, rollback = true)' acts as a default clause of sorts and says all other RuntimeExceptions do not cause instance destruction, but <b>do</b> cause transaction rollback.
</p>
<p>
<b>Conclusion</b>: Being able to be more specific with @ApplicationException would be a great improvement. I definitely plan to propose it in EJB.next. If you like the idea, please leave a comment as numbers do greatly increase the likelihood of it being added. Other ideas on how to achieve a similar result more then welcome!
</p>David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com86tag:blogger.com,1999:blog-7974209436265167833.post-49392769744513212822010-06-18T18:32:00.000-07:002010-10-01T17:07:24.149-07:00EJB annotations and StereotypingCertainly for the EJB-related annotations, I would love to see @Stateless, @Stateful, @Singleton and @MessageDriven be used for stereotyping as well as all the other class level annotations for transactions, security, locking, timeouts and scheduling.
<p/>
Great security example:
<pre>
@RolesAllowed({"SuperUser", "AccountAdmin", "SystemAdmin"})
@Stereotype
@Target(METHOD)
@Retention(RUNTIME)
public @interface Admins {}
</pre>
In one swoop all the security rolls become controlled in one spot and there's no need to go changing a million usages to modify the roll names.
<p/>
Here's a couple great scheduling examples:
<pre>
@Schedule(second=”0”, minute=”0”, hour=”0”, month=”*”, dayOfWeek=”*”, year=”*”)
@Stereotype
@Target(METHOD)
@Retention(RUNTIME)
public @interface Daily {}
</pre>
<pre>
@Schedule(second=”0”, minute=”0”, hour=”0”, month=”*”, dayOfMonth=”15,Last”, year=”*”)
@Stereotype
@Target(METHOD)
@Retention(RUNTIME)
public @interface BiMonthly {}
</pre>
The list goes on and on.
A much fuller example:
<pre>
@Stereotype
@Singleton
@TransactionManagement(CONTAINER)
@TransactionAttribute(REQUIRED)
@ConcurrencyManagement(CONTAINER)
@Lock(READ)
@RolesAllowed({"SuperUser", "AccountAdmin", "SystemAdmin"})
@Interceptors({LoggingInterceptor.class, StatisticsInterceptor.class})
@Target(TYPE)
@Retention(RUNTIME)
public @interface SuperBean {}
</pre>
And to use all that, just:
<pre>
@SuperBean
public class MyBean {
public void doSomething() {
}
}
</pre>David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com61tag:blogger.com,1999:blog-7974209436265167833.post-5615154266944429622010-06-18T15:46:00.000-07:002010-10-01T17:08:30.471-07:00Annotation Scanning StandardWe (the industry) need to get something in place for Java EE 7 to get scanning under control at a platform level. The metadata-complete concept of each individual spec is less helpful given the growing number of specifications that can have class-level "discoverable" annotations.
<p/>
The rules we have for scanning for ejbs in a webapp are quite unintuitive. And how they relate to the scanning of the new Java EE 6 level annotations are unintuitive to the point that how they are handled, I bet, is rather vendor specific:
<p/>
<li/>@DataSourceDefinition(s)
<li/>@ManagedBean
<p/>
The cost of scanning a jar is constant in that it doesn't matter how many annotations you might be looking for or what spec they come from. If each individual spec continues to add spec-specific descriptor support for specifying which jars to scan, we're going to wind up with a rather big mess.
<p/>
We should lock this down with a clean and simple file to control which jars.
<p/>
Something as simple as the following would be a massive improvement.
<p/>
META-INF/scanning.xml
<pre>
<scanning>
<jars>
<jar>foo.jar</jar>
<jar>bar.jar</jar>
</jars>
<packages>
<package>org.foo.widgets</package>
<package>com.bar.components</package>
</packages>
</scanning>
</pre>
I'd love it to have regex support, but even without it there's a big improvement.David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com29tag:blogger.com,1999:blog-7974209436265167833.post-44744039488999827402010-06-12T18:06:00.000-07:002010-10-01T17:09:27.904-07:00If Software is pizza, EJB is the House SpecialIf you can stand terrible food metaphors and have ever been exposed to EJB positively or negatively, keep reading....
<p/>
I don't know about you, but I love the simplicity of a good pepperoni pizza now and then. Imagine asking for a plain Pepperoni pizza and being told your only option was to get the House Special and to pick off all the onions, black olives, green pepper and whatever else comes on top. Any person with options would simply go to another pizza shop. Well, that's EJB. Something I hope we can change in EJB 4.0.
<p/>
To setup the metaphor a bit more, let's say the dough and cheese is the component itself and the proxy to the component. The toppings are the various QOSs (qualities of service) such as transaction management, interceptors, concurrency management, cron-like scheduling, asynchronous method calls, and other goodness. Each bean type such as Stateful, Stateless, Singleton and Message Driven are certain styles of pizza with a fixed set of toppings; say Meat Lovers, Vegetarian, or Hawaiian. The toppings of each style of pizza have been selected carefully to compliment each other perfectly and guarantee good results.
<p/>
Currently though, if you want to start with a plain pizza and add only the toppings you want or need, you cannot do it with EJB. If you want pepperoni, you need to pick a style of pizza that has pepperoni as a topping and deal with the other toppings that come with it, wanted or not. EJB is somewhat flexible and there are usually ways to neutralize some features that amounts to picking off the toppings you don't like, but it's not the same as if they weren't ever there and you are still going to get an odd tasting and odd looking pizza.
<p/>
Say you don't really want the transaction management topping. You try to pick off the topping by selecting SUPPORTS as your default transaction attribute so if a transaction is there, your bean participates in it, if not, it still does it's work regardless. All is fine until your bean throws a runtime exception and the container decides to rollback the current transaction on your behalf. Say you instead choose to try and pick off the transactional topping by making your bean use bean-managed transactions. Things work fine except now all transactions are suspended by the container so that the bean cannot mess with the state of what was the current transaction. What you really wanted was your bean to not be transactionally aware in the first place.
<p/>
Unfortunately if you want one of the other toppings like container managed concurrency, cron-like scheduling, or asynchronous method calls, you have to learn to like the transaction management topping, period.
<p/>
There will always be a need for specific pizza styles with pre-selected toppings -- who doesn't love a good Greek pizza or a Hawaiian now and then. The EJB spec does that well with its perfectly selected bean types, each sprinkled with the select set of QOSs deemed appropriate for that specific bean type. That said, it really should be possible to start with a plain cheese pizza and just add the toppings you want.
<p/>
Forget the dough and cheese. EJB should be about the toppings.
<p/>
Ideally, every QOS the EJB spec has to offer would be an option that can be applied to a plain component. Imagine if there was a "plain cheese pizza" bean type that would by default have no QOSs at all and for all intense purposes be a true POJO. There's nothing to learn or study to code it or use it. It's just a POJO created by the container. Then one day you decide you'd like it to be transaction aware. At that point you annotate it with @TransactionManagement and then go read the self contained "transaction management" section of the spec to see what is now expected of you and the users of the bean.
<p/>
It may be that certain QOSs cannot be combined, which is in fact the case at times. The concept of a container managed persistence context (i.e. a field like "@PersistenceContext EntityManager myEntityManager") cannot be combined with the new @ConcurrencyManagement annotation because EntityManagers themselves are not guaranteed to be capable of concurrency. As a result EJB Singletons are not allowed to use container managed persistence contexts. That may work for some, but maybe you want a Singleton that uses a container managed persistence contexts and do not need concurrency anyway. Such a thing would be possible if you were able to choose the QOSs for your bean regardless of its lifecycle.
<p/>
It's time to break up the big specs and let people build their own pizzas.David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com23tag:blogger.com,1999:blog-7974209436265167833.post-19791374922706737712010-03-02T15:01:00.001-08:002010-03-02T15:27:20.337-08:00Man-page based Bash CompletionHacked up this little function which you can use to get generic bash completion on any command based on the man page.
<script src="http://gist.github.com/320089.js"></script>
You just need to source this file. Here's what it looks like when executed
<pre>mingus:~ 03:16:45
$ wget --c[TAB]
--ca-certificate=file --certificate=file --convert-links
--ca-directory=directory --connect-timeout=seconds --cut-dirs=number
--certificate-type=type --continue
</pre>
Theoretically you could take this a step further and complete the values of the options as well. Many of the options say "--foo=file", "--foo file", "--bar host", etc.. You could parse out this "file" or "host" keyword and switch the completion style accordingly.
If you 'apt-get install bash-completion' you'll get a ton of completion functions which specialize in host, file, and directory completion. Shouldn't be too hard to wire them in. If anyone gets the urge to do it, definitely share your results. The above code is stored in gist.github.com, so fork away!David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com10tag:blogger.com,1999:blog-7974209436265167833.post-80051780979750598152009-12-28T06:41:00.000-08:002010-10-01T17:10:01.848-07:00EJB 3.1 goes final<div><p></div>The <a href="http://jcp.org/en/jsr/summary?id=318">EJB 3.1</a> and <a href="http://jcp.org/en/jsr/summary?id=316">Java EE 6</a> specifications finally closed this month and are up for download. On a personal level, I'd like to say that EJB 3.1 has been the most productive I've been on a specification, thanks in no small way to the truly amazing group we had. For many of us it is a labor of love.
</p><div><p>
First a major thanks to <a href="http://blogs.sun.com/kensaks">Ken Saks</a>. Ken, for a first-time spec lead you did an outstanding job and handled group input like a pro. It's difficult when in a position of authority to both have an opinion and collect the opinions of others. Where one sits in that continuum defines them as a spec lead, sets the tone for the group, and shapes the spec itself. You struck a balance that was just right. You started conversations with proposals that weren't too firm, yet were clear in the goal. As well you actively encouraged the most input from the group without letting conversations drag on too long with no clear conclusion. Hat's off to you, Ken.
</p><div><p>
</div>As well the deepest appreciation to my fellow Expert Group members. There were many, but a special thanks to <a href="http://www.rahmannet.net/">Reza Rahman</a>, <a href="http://www.sybase.com/">Evan Ireland</a>, <a href="http://www.ibm.com/">Soloman Barghouthi</a>, <a href="http://www.jboss.org/">Carlo de Wolf</a>, <a href="http://relation.to/Bloggers/Gavin">Gavin King</a>, <a href="http://www.easybeans.net/">Florent Benoit</a>, <a href="http://blog.adam-bien.com/">Adam Bien</a>, and <a href="http://www.java.net/blog/guruwons">Kim Wonseok</a>. It was an absolute pleasure working with you guys over the last two years. The specification wouldn't have turned out nearly as well without you. It truly was a great group. Let me leave my professionalism aside for a moment and simply say, you all rock.
</p><div><p>
</div>In reference to the specification itself there are areas to which I feel more personally attached. The EJBs in .wars functionalty and of course the Embedded EJB Container API the highest among them. If you like them, please let me know. They have been a labor of love for me for quite some time. I have high hopes for these in regards to the lightweight EJB front and hope that people find great use in them. The Embedded EJB Container API in particular I see as just the beginning and I'm excited to see what innovations we can bring in EJB.next once more vendors have had the chance to implement it.
</p><div><p>
</div>Other areas I find particularly exciting are @Schedule, @Singleton and @Asynchronous. These were a challenge and took a considerable amount of the group's time. @Schedule for the challenge in creating an API that is expressive yet simple. @Singleton for the locking and startup ordering. @Asynchronous for the utter simplicity of it that it was hard to know when to stop. In all of the above, I hope we found that magical line that gives enough functionality without cutting us off from adding more bits in the future. Time will tell.
</p><div><p>
</div>Of course thanks to all the people who provided feedback to the group directly or indirectly through their projects. I know I collected a good amount of spec feedback from the OpenEJB users as did other EG members from their users/customers. This perhaps the most valuable and least thanked group. So on behalf of myself and I'm sure all of the other EG members a whole hearted thanks. You have our deepest gratitude.
</p><div><p>
</div>With that I raise a glass to EJB 3.1! I look forward to working with everyone again in EJB.next! Salud!</div><div></p></div>David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com10tag:blogger.com,1999:blog-7974209436265167833.post-73828491550817464492009-08-17T13:54:00.000-07:002010-10-01T17:10:35.306-07:00Pattern: InvocationContext Propagation<div>Another good name for this pattern might be ThreadLocal Encapsulation.
</div><p/>
<div>This pattern is a real ThreadLocal killer as it is a way to track state over several calls without widespread ThreadLocal usage.
</div><p/><div>
</div><p/><div>Internally in OpenEJB we have managed to boil all our ThreadLocal usage down to this sort of "one to rule them all" approach. When attempting to describe it to a user I started using the javax.interceptor.InvocationContext as an example. The result was an ejb3 design pattern that is too cool not to share.
</div><p/><div>
</div><div>Add the following Interceptor as a global interceptor at the beginning of the interceptor stack.<div>
<script src="http://gist.github.com/287755.js?file=InvocationContextPropagator.java"></script>
The Interceptor uses a private ThreadLocal to propagate invocation state by linking the InvocationContext objects together. The result is that you can do an infinite amount of state tracking as well as write some pretty impressive diagnostic tools.</div><p/><div>Anyone downstream of this interceptor can make a call like this to get access the an infinite amout of state up the stack.<script src="http://gist.github.com/287755.js?file=gistfile2.java"></script>
You can move specific state forward for quick access.<script src="http://gist.github.com/287755.js?file=gistfile3.java"></script>
You can also look infinitely back the invocation chain for state set in a previous InvocationContext.<script src="http://gist.github.com/287755.js?file=gistfile4.java"></script>
Or perhaps more elegantly as a recursive method.<script src="http://gist.github.com/287755.js?file=gistfile5.java"></script>
A JavaDoc'ed and ASL licensed version here: <a href="http://gist.github.com/168153">http://gist.github.com/168153</a>
</div></div>David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com22tag:blogger.com,1999:blog-7974209436265167833.post-82445190171186426472008-04-15T23:09:00.001-07:002010-10-01T17:11:17.961-07:00OpenEJB RevivalAfter a year and a half of internal development and six months of betas, the 3.0 codebase has matured and solidified into the OpenEJB I've always dreamt of.<p>OpenEJB 3.0 achieves much of the original vision OpenEJB set out to accomplish eight years ago. With a Tomcat integration that allows Tomcat users to still enjoy the Tomcat they know and love yet take advantage of many Java EE features for both Servlets and EJBs and an ultra lightweight, embeddable EJB container for simple, plugin-free, unit testing that's impressively fast, remarkably easy to use and far more complete than any mock container out there, OpenEJB 3.0 offers a unique and powerful one-two punch that will be hard to beat.</p><p>OpenEJB has always gone in a different direction than the other EJB implementations, often to it's disadvantage. The idea of lightweight, embeddable and testable EJB was not something people were prepared to accept until recently. This left the project typically lacking in the resources required to keep up with the specs and took OpenEJB off the table for a good number of people. After the launch of EJB 3.0, however, people were finally ready to get on board with a lightweight and embeddable EJB implementation.</p><p>We launched our EJB 3.0 effort, OpenEJB 3.0, in early 2006 and went on a caffeine-charged coding bender for so long and so intensely that about half way in I had to give up drinking coffee completely. For me, it was very personal. Not just a fight for survival, but a fight
two win. OpenEJB had always been a project of great promise, but seemed to never have all the right pieces at the right time. I had been working on the project for six years and it was time to go all in and win or go home. We achieved Java EE 5 certification as part of Geronimo in June 2007 and have been applying copious amounts of polish ever since. We're still the only open source EJB implementation to be included in a Java EE 5 certified platform aside from the RI itself.</p><p>The coming EJB 3.1 specification promises to be an even bigger boom. Several OpenEJB-born concepts are major focuses of EJB 3.1 specification such as the Collapsed EAR (ejbs and servlets side-by-side in the same archive and classloader) and embeddable EJB container for testing and Java SE environments. Similarly, the EJB 3.1 Lite profile describes OpenEJB to a tee and the EJB + Servlet profile maps directly to Tomcat with added OpenEJB.</p><p>If you're a Tomcat user, checkout OpenEJB 3.0. If you'd like an easy way to test your EJBs regardless of what platform you use, checkout OpenEJB 3.0; we natively support the full Glassfish descriptors, Geronimo of course, some of the WebLogic descriptors, and are happy to add more. If you've looked at OpenEJB in the past, especially OpenEJB 2.x, look again ... you'll be very surprised.</p>David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com167tag:blogger.com,1999:blog-7974209436265167833.post-49443672132387265942008-04-12T21:59:00.000-07:002010-10-01T17:11:39.253-07:00OpenEJB 3.0 Final ReleasedAfter a month of release candidates, fixing TCK issues, and other release polish... OpenEJB 3.0 is finally released!
This release includes several improvements and refinements over the very successful 3.0 beta 2 release. Dependency injection has had a major boost with support for Java Generics and Enums. A dozen new validations makes it even harder to do something "wrong". JPA users will find it nearly impossible to misconfigure the jta-data-source and non-jta-data-source. More robust EJB references allow for circular and lazy references to ejbs in other ears. Deep levels of annotation inheritance are completely respected, allowing for greater design control and less duplicate code.
Release notes: <a href="http://www.apache.org/dist/openejb/3.0/RELEASE-NOTES.txt">http://www.apache.org/dist/openejb/3.0/RELEASE-NOTES.txt</a>
Download: <a href="http://openejb.apache.org/openejb-30.html">http://openejb.apache.org/openejb-30.html</a>David Blevinshttp://www.blogger.com/profile/16084891987160395485noreply@blogger.com35