Red Hat

In Relation To CDI

In Relation To CDI

Seam 2.1 Podcast on JSF Central

Posted by    |       |    Tagged as CDI Seam

Kito Mann, editor of JSF Central, recorded a podcast with me a couple of weeks back. We deleved deep into the features of Seam 2.1, but also talked about the Public Review Draft of Web Beans (keep an eye on Gavin's blog for updates) and JSF2.

Check it out!

Web Beans teaser...

Posted by    |       |    Tagged as CDI

For everyone who's been waiting for news of Web Beans ... and for everyone who thought it would never happen ... the public draft is ready, and should be available later this week or early next. I've just started work on an extended article explaining Web Beans from the point of view of the developer, and hope to have that out in a couple of weeks. And Pete Muir, Shane Bryzak and David Allen have made a good start on the RI. Stay tuned...

Want an introduction to Seam?

Posted by    |       |    Tagged as CDI JBoss Tools Seam

Well, you're in luck!

I spoke at JBoss User Group in Denmark in late August, and they recorded both the Seam introductory talk I did:

[ Part 1 | Part 2 | Part 3 | Slides ]

and the Web Beans introductory talk:

[ Part 1 | Part 2 | Part 3 | Slides ]

And, if that isn't enough, you can watch a recording of the recent Introduction to Seam 2 webinar we recorded.

I didn't get a chance to address all the questions asked in the webinar as we ran out of time. So, here are all the questions asked, with answers. Before we start, many thanks to Dan Allen, Dan Hinojosa, Daniel Roth and Jay Balunas for helping me out with the answers :-)

Getting started

  • If I don't use Seam framework, which patterns should I use? I mean, what are the good practices for developing with Seam? Can we use DAOs, Mediators or something else? This is a big question - one we don't have time address here. In general, Seam allows you to design your app around your use cases, rather than artificially imposed patterns. There are quite a few good books out there on Seam - buy one :-)
  • Seam framework is a start point for new projects or can I use it together for new entities in an old project that is already in production? I wouldn't say it's a great idea to do this. If you want to use Seam, you'd probably merge your webapp into Seam, not the other way around.

Conversations

  • Can an atomic conversation span several sessions? I.e. the user can start a conversation in one session, postpond it, log in and continue? Can a conversation/process be continued by another user than the one initiated it or will the answer to these questions to be jBPM? As you say, a jBPM process is the way to have a conversation that lasts for longer than a session that can by multiple people. A conversation would typically be a task within the jBPM process.
  • So, when I do not specify flushMode=manual everything will be flushed automatically at conversation end? By default JPA flushes the persistence context at method boundaries. Manual flush mode means the persistence context will only be flushed when you call entityManager.flush().
  • I do not understand why a conversation can be longer than a transaction? For me the transaction is bound to a unit of work (like the conversation)... Don't forget that a transaction has a general meaning in english, and specific meaning. An atomic conversation represents a users transaction with the application, and can span multiple screens. What is being transacted is the persistence context, not the database. A system transaction (a database transaction) cannot be this long for a number of reasons - for example, the application wouldn't scale as you would hold read-write locks on the database tables for a long time. Thus, the idea is to flush the persistence context all at once, at the end of the use case, rather than in stages along the way that would lead to inconsistencies in the database.
  • How would you compare the conversation in seam to Spring web flow and the way they implement conversations there? My understanding of Spring webflow is that it is closer to Seam's pageflows (which defines a state graph for naviagtion), rather than Seam's conversation model (which uses ad-hoc navigations). But I'm no expert on Spring webflow.
  • Does Seam support anything like Spring Web Flow to define Webpage navigation? Yes, read about pageflow.

Components & Contexts

  • What is bijection? Injection = container initializes bean fields with contextual Stateful variables (from the contexts - cloud of variables) just before they are needed. Outjection = container copies the stateful variable back to the contexts. Bijection = Injection + outjection. This makes it safe for multiple stateful components with different lifecycles to temparaly hold references to other stateful components. Read more
  • Where and how does EJB 3 come in place with seam If you want to use EJB3 with Seam, then Seam will happily manage your EJBs for you, providing the full benefits of the Seam component model. If you don't want to use EJB3, then you don't have to; so why use EJB3? Well you might want to use some of it's ore enterprisy features like MDBs.

IDEs and Tools

  • What is the state of Maven-based Seam development? Are there related plugins/archetypes? Seam publishes Maven poms which contain a transitive dependency tree for Seam. There aren't any archetypes yet, though there are plans afoot.
  • What operating systems is JBoss Studio available for? Linux, Mac and Windows
  • Does the Jboss Tools project, have all the features that are present in jboss developer studio? Yes, Jboss Tools has most of the tooling features that are as part of JBDS. I would say JBDS is more of a superset that includes JBoss Tools integrated with Eclipse, integrated runtime EAP (Enterprise Application Platform), + Spring IDE
  • Are there any tutorials to transform an old seam projects into to a jboss tools seam project? No, your best bet is to create a new project in JBDS, and then copy in your code and configuration files.
  • Is there a NetBeans plugin available that provides Seam support (like the Eclipse-based IDE)? Mostly yes. Whenever you create a seam project using seam-gen an nbproject folder is created for you and you can open your seam project in NetBeans. The reason that the answer is mostly is because NetBeans doesn't offer as many plugins as Eclipse or the upcoming IntelliJ for Seam. Groovy support for NetBeans is also still being developed for NetBeans so you may have some unpleasentness for a short while. Michael blogged about this a while ago.
  • I tried setting up seam in netbeans 6.0. The seam-gen plugin doesn't work. Why is it so? Here's the error generated. C:\jboss-seam\jboss-seam-2.0.2.SP1\seam-gen\build.xml:607: C:\modules\ext not found. You'll need to ask on the NetBeans forums about NetBeans support for Seam. Keep in mind that the seam-gen plugin for NetBeans was really designed for an older version of Seam and is currently being redesigned.
  • Are there any built in debugging tools to inspect the entities, what all is this tool capable of? Out of the box, Seam has a debug page that allows you to not only inspect your entities and the scope that they are in, you can view your POJO and EJB3 Action Beans, view their references and values and view any applicable stack traces. You just have to make sure you deploy in a dev profile and go to /debug.seam (or whatever your custom extension) is.

View layers

  • I noticed Seam 2.10 beta has provided first-class support for Wicket. Are there any plans to do the same with GWT? The provided example with remoting/GWT is not as extensive as the one for Wicket and I'm looking for better integration between the two. Yes, keep your eyes open for more GWT support over the next few months :-)
  • Is it possible to mix Wicket and JSF view layer in one project? Probably not, but I haven't tried. If you isolate the view mappings, it might work. Have a go, let us know how you get on at the forums.
  • I'm quite familiar with GWT. I read bout the RPC integration. However, how to use the other Seam more useful features such as scopes, validators, etc with GWT together? Currently the GWT support uses Seam remoting to interact - this allows you to access the Seam contexts as normal, but there is no Hibernate Validator support. Keep an eye out over the next few months for more on GWT.
  • Do you cooperate with ICEfaces to improve the integration of ICEfaces since I noticed that many JIRA for ICEfaces stay unfixed for a long time. Yes. Judy from the ICEfaces team maintains the Seam-ICEfaces integration in Seam (both in seam-gen and the icefaces example) - the open issues in the Seam JIRA can probably be closed off as out of date, as they originate from the pre-Judy days ;-) Currently, ICEfaces is rewriting many of the seam-gen templates to take better advantage of the partial page rendering in ICEfaces.

Testing

  • What about testing of seam applications? Selenium, JMeter, JSFUnit, other Seam works great with unit tests as everything is POJOs, and provides a testing framework for doing integration tests with a mock JSF lifecycle. We're currently adding JSFUnit and Selenium tests to our examples - both work great with Seam.

Application Server interoperability

  • Does Seam run with Oracle's OC4J? Yes, Seam runs on OC4J 11 and there are community reports of it working with OC4J 10.
  • Is it possible to use toplink instead of hibernate when using JBoss seam? What about OpenEJB? The biggest roadblock to using TopLink comfortably is that it does not support manual flushing of the persistence context like Hibernate. So it is more of an architectural limitation. You can currently use Seam with OC4J11.4g See Section 33.3 of the user guide for more information of using OC4J . As per OpenEJB, there has been experimentation done by Seam users around the world. The best bet is inquire a search engine to view some of the work that they have been doing or try it yourself. If you do try it yourself, please report to us so that we can spread the word about sing praises of your name.

Security

  • Why seam asks twice for authentication? This is discussed in the documentation.
  • Will Seam 2.1 provide easy support for SSO (Single-Sign-On) using products where the JAAS context (Subject, Principals) is already available when the application starts? Work on SSO is currently underway. We decided to get Seam 2.1.0 out there asap, rather than wait for it do be done, so Seam 2.1.2 will support SSO.

The future

  • What are your thoughts on EJB3.1 lite and its interactions with Web beans? EJB 3.1 brings a number of exciting developments, among them a much simpler deployment model - being able to deploy EJBs in your WAR. WB will integrate with EJB 3.1 lite just as it does with normal EJB containers (assuming it is also executed in a web beans container. EJB 3.1 lite and Web Beans should be a good match.
  • What is the long term for Seam when Web Beans is out? Is there that much of a difference that the two will proceed together or will Seam become maintenance only and all new features will be in Web Beans. We anticipated this FAQ ;-)
  • Will both models be supported in Seam 3? The type safety and the string based approach? Seam 3 will be have WB as its core. WB is a type safe component model and framework. If there is a large community pressure to support the classic, Seam 2, core we will look into it (we anticipate pressure here from developers that prefer dynamic languages). This issue is Seam 3 (rather than Web Beans) specific.
  • When will you start developing seam based upon web beans (i.e. version 3), will 2.1 be the last major version before 3? The current plan is to release Seam 2.1.0 then quickly follow up with Seam 2.1.1 and 2.1.2. After that work will begin on Seam 3 - think early Spring. As always, plans may change ;-)
  • I am starting a new seam project that will release into production within 3 months. Can I safely start with Seam 2.1 with confidence that the beta cycle will be complete by year's end? yes ;-) The Seam 2.1.0.GA release will be available in the next month or so. There will be follow on releases that focus on specific improvements 2.1.1 (increased performance) and 2.1.2 (SSO support). These should be drop in replacements for 2.1.0.

Other

  • I can see that message in the Validation example is hardcoded. How do you I18N this example? You can easily internationalize the message - just use the Seam message bundle @Length(min=3, max=1000, message="#{messages['validate.length'}") String description;
  • Does Seam provide an easy way to handle web session timeouts? I have had to create a solution for checking on the session and redirecting users to the start page when session times out. I'd like to use Seam to handle web session timeout instead of creating my own solution... Take a look at Christan's solution. Also you can observe the org.jboss.seam.preDestroyContext.Session event.
  • What are the more significant changes or enhancements between Sean 1.x and 2? Take a look at Norman's announcement
  • Is the hot deploy feature specific to JBoss AS or Seam ? The hot deployment of action components is a feature that is specifically handled by Seam and available in exploded WAR deployments. Don't confuse it with the hot deployment of the application itself, which falls in the realm of the application server. To enable hot deployment of components, Seam uses a standard Java classloader type (URLClassLoader) to load certain components. When Seam detects a newer version of one of these component in the exploded WAR directory, the set of action components are dumped and rescanned. This feature falls under Seam's management of components (its contextual container).
  • Does the Seam Messaging Component support the creation of message topics on demand? Seam just provides an easy way to access JMS, so this depends on your underlying JMS provider.
  • What is the one major feature that makes seam 2.0 better than JSF or Visual JSF? There will always be varying opinions as to what that one feature is for them. For me it's not having to create a JSF Managed Bean that acts as dummy adapter that merely that fowards request to business-logic bean (EJB3 or POJO) and wasting a lot of development time.
  • Can you integrate Seam with an Action framework? There is no integration to Struts or Stripes nor do I think there would be since action frameworks don't focus on having a stateful component architecture. But, while JSF isn't an action based framework, Seam can act as an action framework - take a look Seam's page actions for more information . In fact, the more you use seam actions, the less you'd likely want to go back to the Action framework days.
  • Can we see an example of how Seam integrates with BPM and Rules? Take a look at the dvdstore example in the Seam download for BPM. Take a look at the drools example for the Drools integration.

Seam Podcast up on DZone

Posted by    |       |    Tagged as CDI JBoss Tools Seam

DZone just posted an interview with me about Seam.

We spoke for a few minutes about Seam, and some of the features of Seam 2. Then we moved on to talk about the upcoming Seam 2.1, how it will support other view layers, and where JSF is going. Finally we spent a few minutes talking about Web Beans, and what it will mean for Seam users.

The site has both a transcript, and the audio.

Hibernate and Seam meeting in Tuscany

Posted by    |       |    Tagged as CDI Seam

Last week we had the good fortune of having a Hibernate and Seam team meeting.

Despite of the following pictures, the week was really productive and we got all to meet up and put faces to new and old people. I also got a bunch of working pictures but they are boring ;)

The topics of discussions were broad but mostly about road map's and action items for Seam and Hibernate, WebBeans and related tooling. You will start seeing the results of these talks on the forums and in upcoming release in the near future.

Now onto the fun part...

The actual meeting were in Tuscany, Italy near a city named Chiusi.

We rented a farmhouse which had a great view over a sunflower field.

And it had a great pool too.

I unfortunately could not get to Tuscany before Wednesday so I missed out on the Hibernate meeting, so I only managed to get a few shots of the Seam meetings.

We got all the Seam related JBoss employees there, but we had also invited a couple of external contributors.

One of those who made it despite being in the middle of most holidays were Dan Allen:

Apparently Dan is a professional diver, but that did not stop Rich Sharples:

nor Jay Balunas:

Nothing like taking a swim after having discussed tech!

Dinner were mostly done by Shane, The Australian Chef and Seam security Wizard in beginning of the week; but because of my late arrival I missed out on it and only attended a Shane breakfast:

And i'm sure Gavin, Jay, Norman, Emmanuel, Marek, Christian, Steve, Rich, Ales, Samuel, Rodney, Hardy, Gail, Chris, Anthony and Dan all would like to say thanks to Shane for the great food and just as big a thanks to Pete for doing all the arrangements - it was definitely the best location ever for a team meet up I've been at.

Now back to work...

Why we need a real Web Profile

Posted by    |       |    Tagged as CDI Java EE

Recently the EE6 co-lead, Roberto Chinnici, blogged about the state of profiles in EE6, and requested feedback on which direction the group should take. This was also posted to InfoQ and TSS. Essentially we have a choice between two options:

  1. Rubberstamp Tomcat
  2. Provide a complete framework for web development.

The first option offers nothing new that doesn't already exist today. Right now you can download Tomcat and, unless you are still developing with just Servlets and JSPs, install the many different frameworks you need to build a modern web application. You are then left to discover the magic version combination that doesn't have dependency conflicts or integration issues.

What we really need is a standardized solution which addresses the three most common needs of modern web applications:

  • A data persistence framework
  • A component framework
  • A rich presentation framework

The full Java EE platform has good solutions for all of these aspects today, and more work is being done to improve them (e.g Web Beans, ability to deploy EJBs in a war, etc). However, the full EE platform also contains many other standards, most of which are focused towards EIS (like CORBA, RMI, JMS, JCA, etc). EIS is, of course, not necessary for a significant portion of web applications. So, the central idea behind option 2, is to deliver a version of the platform that is truly focused towards web development.

Not only can we omit specifications that don't serve the above goals, we can also improve the ones that do to better meet our new-found focus. A good example of this, is EJB-Lite, which only requires support for local session components and JPA.

Taking all of this into account we end up with what I view is the ideal combination, which I have strongly advocated on the EG:


Data Persistence

  • JPA 2.0
  • JTA 1.1

Component Framework

  • EJB Lite 3.1
  • Web Beans 1.0

Rich Presentation

  • JSF 2.0
  • Servlet 3.0 (and friends, jsp, el, jstl etc)

I should also mention that non-standard frameworks would of course still be usable on this profile. As an example, Web Beans will offer an SPI so that any web framework can take advantage of the improved/simplified component integration layer, should it choose to.

However, I think the goal should be to provide a good out-of-the-box solution for web development, and a tomcat profile definitely falls short.

The Web Beans Manifesto

Posted by    |       |    Tagged as CDI

The theme of Web Beans is:

  • Loose coupling with strong typing!

/Loose coupling/ comes in a variety of guises:

  • deployment time polymorphism
  • runtime polymorphism
  • lifecyle independence
  • decoupling of technical concerns
  • decoupling of event producers from event consumers

Loose coupling makes a system more /dynamic/. The system can respond to change in a well-defined manner. In the past, frameworks that attempted to provide the facilities listed above invariably did it by sacrificing type safety. For example, many frameworks use XML deployment descriptors, or string-based identifiers to wire components together and define their lifecycle. Other frameworks use some kind of string-based expression language to bind interceptors to components (the most disgusting example of this is the use of regexes in AOP pointcut expressions).

Web Beans lets components interact in a loosley coupled way without /ever/ resorting to XML or String-based identifiers. The only time component /names/ are used is for binding Web Beans components to a non-typesafe language such as Unified EL.

  1. deployment time polymorphism is provided via typesafe /binding annotations/ and /component types/
  2. runtime polymorphism is provided via typesafe binding annotations on /producer methods/
  3. lifecycle independence is a feature of the /contextual component model/
  4. technical concerns are decoupled by interceptors bound via typesafe /interceptor binding annotations/
  5. event producers and event consumers are decoupled via a typesafe /event object/ and event binding annotations

You don't see string-based identifiers in Web Beans code, not because the framwork is hiding them from you using clever defaulting rules (configuration by convention, as the Ruby folks say, or configuration by exception, as we used to say in the EJB3 expert group), but because there are simply no strings there to begin with!

This provides obvious benefits in that /any/ IDE can provide autocompletion, validation and refactoring without the need for special tooling. But it also provides a less-immediately-obvious benefit. It turns out that when you start thinking of identifying components, events or interceptors via annotations instead of names, you have an opportunity to lift the semantic level of your code.

Web Beans encourages you develop reusable annotations that model concepts, for example,

  • @Asynchronous,
  • @Mock,
  • @Secure,
  • @Action or
  • @Updated,

instead of non-reusable compound names like

  • asyncPaymentProcessor,
  • mockPaymentProcessor,
  • SecurityInterceptor,
  • LoginAction or
  • DocumentUpdatedEvent.

When I look at Java code today, and I see these kind of compound names, it reminds me of old-fashioned naming conventions for variables in dynamic languages, which embed the type of the variable in the variable name, for example str_username. These naming conventions were a clear workaround for the fact that the language had no primitives for expressing typing information.

Compare the following observer methods:

void onDocumentUpdate(@Observes DocumentUpdatedEvent event) { ... }
void onDocumentUpdate(@Observes @Updated Document doc) { ... }

Both are correct, but the second approach is more Web-Beansy. The @Updated binding annotation models a reusable notion. We can use it for other events:

void onDocumentUpdate(@Observes @Updated Order order) { ... }

And notice how much more /literate/ this code is.

Or compare the following implementations of Login:

public 
@SessionScoped
@Component 
@Interceptors(SecurityInterceptor.class)
class Login { ... }
public
@SessionScoped
@Secure
@Component 
class Login { ... }

The second form is more Web-Beansy - the code is more decoupled and more literate.

The nirvana of this kind of literate programming is a new feature of Web Beans called /stereotypes/. A stereotype lets you encapsulate scope, interceptor bindings, component type, etc, into a single package that models a /role/ in the application architecture. For example, instead of defining:

public 
@RequestScoped
@Named
@Secure
@Transactional
@Component
class LoginAction extends BaseAction { ... }

We could create a stereotype:

@RequestScoped
@Named
@Secure
@Transactional
@Component
@Stereotype(requiredTypes=BaseAction.class)
@Target(TYPE)
@Retention(RUNTIME)
public @interface Action {}

And reuse it for all our actions:

public @Action class LoginAction extends BaseAction { ... }
public @Action class UpdateDocumentAction extends BaseAction { ... }

Another example is a stereotype for singletons. Of course, we /could/ write:

public 
@ApplicationScoped 
@Component 
class ReferenceData { ... }
public 
@ApplicationScoped 
@Mock 
class DummyReferenceData extends ReferenceData { ... }

But I would prefer:

@ApplicationScoped
@Component
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface Singleton {}
public 
@Singleton 
class ReferenceData { ... }
public 
@Mock 
@Singleton 
class DummyReferenceData extends ReferenceData { ... }

Well, this stereotype did not save much typing. But on the other hand, it tells us more about the ReferenceData class. The code is more literate and understandable. Even better, it's /much/ easier for me to find all singletons in my code, or to add an interceptor to singletons. It also makes it easier to ensure that certain patterns are followed consistently in a large project.

JSR-299 Web Beans Early Draft

Posted by    |       |    Tagged as CDI

The first early draft[1] is now available! Please send comments to jsr-299-comments(AT)jcp.org. We really /do/ pay attention to community feedback, so if you take the time, it won't be wasted!

(The JCP site is currently experiencing technical difficulties, so we're making the spec available for download here, temporarily.)

I would like to give a huge thanks to everyone on the expert group who helped get us this far. I know it's inelegant to single out individuals, but since it is rare to see people (especially individual JCP members) recognized for their contributions to spec groups, I'm going to do it anyway. Extra special thanks to:

  • Bob Lee
  • Linda DeMichiel
  • Jacob Hookom
  • Adam Winer
  • Michael Youngstrom
  • Richard Kennard
  • Conny Lundgren
  • Roger Kitain
  • Chris Maki

Let us know what you think!

Attachments

  1. Web Beans EDR.pdf

Web Beans Sneak Peek Part V: Interceptors and events

Posted by    |       |    Tagged as CDI Java EE

/This is the fifth installment of a series of articles describing the current status of the Web Beans specification. Please read the first, second, third and fourth installments first./

One of the themes of Web Beans is loose coupling. We've already seen three means of achieving loose coupling:

  • component types enable /deployment time/ polymorphism
  • producer methods enable /runtime/ polymorphism
  • contextual lifecycle management decouples component lifecycles

These techniques serve to enable loose coupling of client and server. The client is no longer tightly bound to an implementation of an API, nor is it required to manage the lifecycle of the server object. This approach lets /stateful objects interact as if they were services/.

Web Beans provides two extra important facilities that further the goal of loose coupling:

  • interceptors decouple technical concerns from business logic
  • event notifications decouple event producers from event consumers

Let's explore these features.

Interceptors

Web Beans re-uses the basic interceptor architecture of EJB 3.0, extending the functionality in two directions:

  • any Web Bean may have interceptors, not just session beans
  • Web Beans features a more sophisticated annotation-based approach to binding interceptors to components

Suppose we want to declare that some of our components are transactional. The first thing we need is an /interceptor binding annotation/ to specify exactly which components we're interested in:

@InterceptorBindingType
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface Transactional {}

Now we can easily specify that our ShoppingCart is a transactional object:

@Transactional @Component
public class ShoppingCart { ... }

Or, if we prefer, we can specify that just one method is transactional:

@Component
public class ShoppingCart {
    @Transactional public void checkout() { ... }
}

That's great, but somewhere along the line we're going to have to actually implement the interceptor that provides this transaction management aspect. All we need to do is create a standard EJB interceptor, and annotate it @Interceptor and @Transactional.

@Transactional @Interceptor
public class TransactionInterceptor {
    @AroundInvoke public Object manageTransaction(InvocationContext ctx) { ... }
}

Finally, we need to /enable/ our interceptor in web-beans.xml.

<interceptors>
    <interceptor>to.relation.in.TransactionInterceptor</interceptor>
</interceptors>

Whoah! Why the angle bracket stew?

Well, the XML declaration solves two problems:

  • it enables us to specify a total ordering for all the interceptors in our system, ensuring deterministic behavior
  • it lets us enable or disable interceptor classes at deployment time

For example, we could specify that our security interceptor runs before our TransactionInterceptor. And we can turn them both off in our test environment.

Interceptor bindings with members

Suppose we want to add some extra information to our @Transactional annotation:

@InterceptorBindingType
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface Transactional {
    boolean requiresNew() default false;
}

Web Beans will use the value of requiresNew to choose between two different interceptors, TransactionInterceptor and RequiresNewTransactionInterceptor.

@Transactional(requiresNew=true) @Interceptor
public class RequiresNewTransactionInterceptor {
    @AroundInvoke public Object manageTransaction(InvocationContext ctx) { ... }
}

Now we can use RequiresNewTransactionInterceptor like this:

@Transactional(requiresNew=true) @Component
public class ShoppingCart { ... }

But what if we only have one interceptor and we want the container to ignore the value of requiresNew when binding interceptors? We can use the @NonBinding annotation:

@InterceptorBindingType
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface Secure {
    @NonBinding String[] rolesAllowed() default {};
}

Multiple interceptor binding annotations

Usually we use combinations of interceptor bindings types to bind multiple interceptors to a component. For example, the following declaration would be used to bind TransactionInterceptor and SecurityInterceptor to the same component:

@Secure(rolesAllowed="admin") @Transactional @Component
public class ShoppingCart { ... }

However, in very complex cases, an interceptor itself may specify some combination of interceptor binding types:

@Transactional @Secure @Interceptor
public class TransactionalSecureInterceptor { ... }

Then this interceptor could be bound to the checkout() method using any one of the following combinations:

@Component
public class ShoppingCart {
    @Transactional @Secure public void checkout() { ... }
}
@Secure @Component
public class ShoppingCart {
    @Transactional public void checkout() { ... }
}
@Transactionl @Component
public class ShoppingCart {
    @Secure public void checkout() { ... }
}
@Transactional @Secure @Component
public class ShoppingCart {
    public void checkout() { ... }
}

Binding an interceptor to /everything/

What if we want an interceptor for /every/ component? Easy, just declare the interceptor without any interceptor binding type!

@Interceptor
public class UberInterceptor { ... }

Interceptor binding type inheritance

One of the awful, embarrassing, mistakes of the Java language is the lack of support for annotation inheritance. Really, annotations should have reuse built in, to allow this kind of thing to work:

public @interface Action extends Transactional, Secure { ... }

Well, fortunately, Web Beans works around this missing feature of Java:

@Transactional @Secure
@InterceptorBindingType
@Target(TYPE)
@Retention(RUNTIME)
public @interface Action { ... }

And now any component annotated @Action will be bound to both TransactionInterceptor and SecurityInterceptor. (And even TransactionalSecureInterceptor, if it exists.)

Events

/Please note that the following section describes functionality that is still under active discussion in the Web Beans expert group!/

The Web Beans event notification facility allows components to interact in a totally decoupled manner. Event /producers/ raise events that are then delivered to event /observers/. This basic schema might sound similar to the observer/observable pattern, but there are a couple of twists:

  • not only are event producers decoupled from observers; observers are completely decoupled from producers
  • observers can specify a combination of selectors to narrow the set of event notifications they will receive
  • observers can be notified immediately, or can specify that delivery of the event should be delayed until the end of the current transaction

Event observers

An /observer method/ is a method of any Web Bean with a parameter annotated @Observes.

public void onAnyDocumentEvent(@Observes Document document) { ... }

The annotated parameter is called the /event parameter/. Observer methods may also specify selectors, which are called /event binding types/. An event binding type is just an annotation:

@EventBindingType
@Target({PARAMETER, FIELD})
@Retention(RUNTIME)
public @interface Updated { ... }

We specify the selector by annotating the event parameter:

public void afterDocumentUpdate(@Observes @Updated Document document) { ... }

The observer method may have additional parameters, which are injected, according to the usual Web Beans semantics:

public void afterDocumentUpdate(@Observes @Updated Document document, @Current User user) { ... }

Event producers

The event producer may obtain an /event notifier/ by injection:

@In @Notifier Event<Document> documentEvent;

The @Notifier annotation implicitly defines a Web Beans component with scope @Dependent and component type @Standard.

A producer raises events by calling the one and only method of the Event interface:

documentEvent.raise(document);

To specify a selector, the producer may either pass an instance of the event binding type to the raise():

documentEvent.raise(document, new Updated(){});

Of may specify the selector at the injection point:

@In @Notifier @Updated Event<Document> documentUpdatedEvent;

Event bindings with members

An event binding type may have annotation members:

@EventBindingType
@Target({PARAMETER, FIELD})
@Retention(RUNTIME)
public @interface Role {
    RoleType value();
}

The member value is used to narrow the messages delivered to the observer:

public void adminLoggedIn(@Observes @Role(ADMIN) LoggedIn event) { ... }

And can be specified by the event producer either statically:

@In @Notifier @Role(ADMIN) Event<LoggedIn> LoggedInEvent;

Or dynamically:

documentEvent.raise( document, new Role() { public void value() { return user.getRole(); } } );

Multiple event bindings

Event binding types can be combined, for example:

@In @Notifier @Blog Event<Document> blogEvent;
...
if (document.isBlog()) blogEvent.raise(document, new Updated(){});

In this case, any of the following observer methods would be notified:

public void afterBlogUpdate(@Observes @Updated @Blog Document document) { ... }
public void afterDocumentUpdate(@Observes @Updated Document document) { ... }
public void onAnyBlogEvent(@Observes @Bog Document document) { ... }
public void onAnyDocumentEvent(@Observes Document document) { ... }

Transactional observers

Transactional observers receive their event notifications during the before or after completion phase of the transaction in which the event was raised. For example, the following observer method needs to refresh a query result set that is cached in the application context, but only when transactions that update the Category tree succeed:

public void refreshCategoryTree(@AfterTransactionSuccess @Observes CategoryUpdateEvent event) { ... }

There are three kinds of transactional observers:

  • @AfterTransactionSuccess observers are called during the after completion phase of the transaction, but only if the transaction completes successfully
  • @AfterTransactionCompletion observers are called during the after completion phase of the transaction
  • @BeforeTransactionCompletion observers are called during the before completion phase of the transaction

Transactional observers are very important in a stateful component model, because state is often held for longer than a single atomic transaction.

Response to Matt Corey

Posted by    |       |    Tagged as CDI

I would like to thank Matt Corey for his commentary on Web Beans, and respond to several points.

Web Beans is not just about the web, as many people have already commented (including Gavin)... while I don't necessarily need it to be brought to JSE, I believe a name change is in order...

I'm inclined to think that the concrete issue of the target platform is more important. Both platforms already feature strong branding and Web Beans is just a piece of the platform, not a platform by itself. On the other hand, if SE developers feel that this technology is useful to them, then we (the Web Beans group) are going to have to go back to Sun and the JCP and discuss how their needs can be accommodated.

If Web Beans becomes a generic Dependency Injection mechanism, then we would be left with at least three distinct DI systems in JEE -- the Web Beans DI, the @EJB/@Resource DI from JEE 5, and the Managed Bean mechanism from JSF... something will need to be done to address this (please don't say 'Unified DI', a la 'Unified EL' :) )...

This is certainly a problem we're thinking about. But we need guidance from the EE expert group on how to proceed with this. In theory we could provide facilities that would allow @EJB and @Resource to be implemented on top of Web Beans, if that was the decision of the EE expert group.

The @In annotation clearly comes from Seam, but there might be something more appropriate here -- in Seam, there is also an @Out annotation, representing 'outjection'... So far, Gavin hasn't given us a hint of whether this will be around in Web Beans, but if not, then I think @In should become something like @Inject, @Bean, @Component, etc

We kicked @Out out of the spec, after much discussion. @Out is really convenient in the Seam/JSF world of named variables. It doesn't make so much sense in the world of Guice/Web Beans where much more static checking is possible. And it's possible to achieve a very similar effect using resolver methods.

I'm open to suggestions for renaming @In, I've considered @DependsUpon, @Uses, @Contextual and @Injected.

The Guice influence appears to have replaced the String-based naming in Seam (i.e. -- @Name("myBean") ) with annotations (@MyBean)... while this requires a little more code, it seems to be a good call -- it should help prevent things like typo's in the Strings causing NullPointerExceptions at Runtime...

Right, this is something that Guice did beautifully. The Guice approach is elegant, typesafe and completely natural - so much better than the approaches of Spring or of JSF (Seam built upon the JSF approach).

However, injection by name is still possible in Web Beans, since @Named is defined as a binding annotation. You can do:

@In @Named("currentOrder") Order order;

(If you really want to.)

The various Component Types could be hugely useful for having multiple configurations for a single application, but I would like to see more ways of defining your components -- for example, I like to be able to keep my system configurations in the app server itself, so when I deploy an EAR from test to staging to production, I can simply copy an EAR that has passed QA -- if I have to change the web-beans.xml file, I can't do this (unless there is perhaps a default that you could configure in your server)

One way you could do this is to just not include the archive containing your @Staging components when you deploy to production. If high-precedence components are not in the classpath at deployment time, they won't be deployed.

I love the scopes, but Gavin mentions that the @ConversionScoped will be available from JSF managed beans, while request, session and application will be available from Servlets -- what about JSF makes it the only thing that is appropriate for the conversation scope? Any reason it couldn't be available to Servlets-based frameworks like Struts, etc.?

No reason at all. But here we're drifting into questions like:

  • what functionality should be defined by the Web Beans specification?
  • what functionality can be provided by the application or third-party frameworks?

The Web Beans spec has an extensible context model. In particular, this means that if you want to define your own Context object for the @ConversationScoped scope, that works for any servlet request, you can do it.

So far all I can say is "Great work guys!"... oh, and keep the previews coming!

Thanks for the feedback Matt, appreciated :-)

back to top