I'm the creator of Hibernate, a popular object/relational persistence solution for Java, and Seam, an application framework for enterprise Java. I'm also contributing to the Java Community Process standards as Red Hat representative for the EJB, JPA, JSF specifications and spec lead of the Web Beans specification. At Red Hat, I'm leading the effort to build a Unified development platform of programming model, frameworks and tooling.
|
Recent Entries |
|
18. Nov 2008
|
|||
|
17. Nov 2008
|
|||
|
12. Nov 2008
|
|||
|
10. Nov 2008
|
|||
|
09. Nov 2008
|
|||
|
03. Nov 2008
|
|||
|
21. Oct 2008
|
| Seam | (26) |
| Web Beans | (17) |
| Seam News | (7) |
| Web Beans Sneak Peek | (5) |
| EE6 Wishlist | (3) |
| Seam Wiki | (3) |
| Web Frameworks | (3) |
| > JBoss Tools < | (2) |
| Persistence | (1) |
| Photography | (1) |
| RichFaces | (1) |
|
Java Persistence with Hibernate
with Christian Bauer November 2006 Manning Publications 841 pages (English), PDF ebook |
|
Hibernate in Action
with Christian Bauer August 2004 Manning Publications 408 pages (English), PDF ebook |
I keep getting asked about the relationship between Seam and Web Beans. At a high level, the mission of the Seam project remains unchanged: to provide a fully integrated development platform for building rich Internet applications, based upon the Java EE environment. In Seam2, this platform consists of the following layers:
- the contextual lifecycle, configuration and dependency injection model that forms the essential
glue
that makes everything work together in a consistent way - a set of modules that integrate other technologies such as JSF, jBPM, Hibernate, Drools, Groovy, Wicket and GWT, or solve common concerns such as security, asynchronicity and rendering PDF, email, Excel, RSS
- tooling
The first layer is the part that is addressed by JSR-299. The spec defines a more elegant, more typesafe, more user-friendly, standard solution that is a huge improvement over Seam2 (and everything else out there). The value of this is more elegant, more typesafe, more loosely coupled application code. But for many people, the true value of Seam is that it provides a complete pre-built, pre-integrated stack of technologies, together with tool support. That's not the role of JSR-299.
So the goal of Seam3 is to take the second layer and port it to the Web Beans backbone. This will allow applications using the Web Beans programming model to take advantage of all the integrated technologies that make up Seam. A second immediate benefit is that Seam will integrate much more consistently and transparently with application servers that natively support Web Beans. Seam3 will probably be packaged in a more modular way than Seam2, allowing any Web Beans-based application to drop in
Seam security, jBPM integration, Drools integration, etc. And hopefully, Seam won't be the only project providing infrastructure based upon Web Beans.
Of course, we want to make it's easy for people with Seam2 applications to migrate to Web Beans. There's two possible approaches and I'm not sure exactly which path we will take. We could:
- reimplement the core of Seam as a layer over the Web Beans backbone, or
- simply allow Seam2 and Web Beans to run side-by-side, with advanced interoperability between Web Beans and Seam2 components.
The first option sounds like a lot more work, but I suspect it might be easier than you would think.
Here's another usecase for the injection point metadata API that we're considering adding to Web Beans. I've always thought it would be nice to be able to inject entity instances by role, instead of passing references around the system. (In Seam, you can use home objects to achieve this.)
Of course, we need a way to distinguish which instance of a particular entity type we're interested in. For each conversation, there are certain roles
. For example, in an user administration screen, there is the current user, and the user that is being administered.
In a Web Beans world, we would represent a role using an annotation. For example, we would refer to the @Administered User. What I would like to be able to do is associate an identifier with the role, at the beginning of a conversation, and then simply inject the entity with that identifier into any Web Bean that is invoked during that conversation. Of course, I could write a Web Bean with a producer method to do this:
@ConversationScoped
public class AdministeredUser {
private @PersistenceContext EntityManager em;
private String userId;
public void setUserId(String userId) {
this.userId = userId;
}
@Produces @Administered User getUser() {
return userId==null ? null : em.find(userId);
}
}
However, I don't really want to have to write a new Web Bean for every role! So let's generify this code. Instead of making @Administered a binding annotation, we'll use a generic binding type @Persistent, and use InjectionPoint to determine the role that was specified at the injection point:
@ConversationScoped
public class EntityRoles {
private @PersistenceContext EntityManager em;
private Map<Key, Object> idByRole = new HashMap<Key, Object>();
public void setId(Class entity, Annotation role, Object Id) {
idByRole.put(new Key(entity, role), id);
}
@Produces @Persistent Object getInstance(InjectionPoint ij) {
Object id = idByRole.get(new Key(ij.getType(), ij.getAnnotations()));
return id==null ? null : em.find(id);
}
}
(I'm leaving out the boring implementation of Key, and the binding annotation @Persistent.)
Now, the following code may be used to set the identifier, at the beginning of a conversation:
@Current EntityRoles er; ... er.setId(User.class, Administered.class, userId);
And the User may be injected as follows:
@Administered @Persistent User user
We probably also want to make it possible to refer to the User by a name in Unified EL, but for that we'll need to write a ELResolver (which is also too boring for this post).
In the comments thread for this post, Bill got me thinking again about a problem that's been bugging me for a while.
The problem is that there are certain kinds of dependent objects
(in the sense of the Web Beans @Dependent scope) that need to know
something about the object or injection point into which they are
injected in order to be able to do what they do. For example:
- the log category for a Logger depends upon the class of the object that owns it
- injection of a HTTP parameter or header value depends upon what parameter or header name was specified at the injection point
- injection of the result of an EL expression evaluation depends upon the expression that was specified at the injection point
The solution I've come up with is to allow injection of a special metadata object into any injected dependent object.
(Note that this functionality is specifically for @Dependent scope Web Beans - objects with normal scopes are shared between many clients and many injection points, so their behavior cannot depend upon anything relating to the client.)
Let's look at an example:
class LogFactory {
@Produces Logger createLogger(InjectionPoint injectionPoint) {
return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
}
This clever little producer method lets you inject a JDK Logger with the right log category. Instead of typing:
Logger log = Logger.getLogger(MyClass.class.getName());
You can write:
@Current Logger log;
which is shorter, and less vulnerable to refactoring problems.
Not convinced? OK then, let's see a second example...
To inject HTTP parameters, we need to define a binding type:
@BindingType
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @annotation HttpParam {
@NonBinding public String value();
}
We would use this binding type at injection points as follows:
@HttpParam("username") String username;
@HttpParam("password") String password;
The following producer method does the work:
class HttpParams
@Produces @HttpParam("")
String getParamValue(ServletRequest request, InjectionPoint ip) {
return request.getParameter(ip.getAnnotation(HttpParam.class).value());
}
}
I suppose this stuff is mainly useful for framework-type development, but it might also have other applications.
So how hard is it to add this feature to Web Beans? Not hard at all! The Web Beans specification would define the following API:
public interface InjectionPoint {
public Type getType();
public Set<Annotation> getBindingTypes();
public Object getInstance();
public Bean<?> getBean();
public Member getMember():
public <T extends Annotation> T getAnnotation(Class<T> annotation);
public Set<T extends Annotation> getAnnotations();
}
And the Web Bean manager would be required to provide a built-in Web Bean that implements this interface.
What do you think?
If there's one thing that we really want to get right as Web Beans goes from Public Draft to Proposed Final draft, it's integration with the Java EE platform. Up to this point, most of the work we've been doing as an EG was focused on nailing down the programming model, the semantics of the Web Beans services, and the behavior of the Web Bean manager. We've been writing the spec to assume that Web Beans implementations should be pluggable between different Java EE containers, because this is a direction that a lot of folks in the Java EE community believe that the EE platform should move in, and because we would like Web Beans to help show the way for other specifications such as EJB, JTA and perhaps even Servlets (note that JPA and JSF already support this).
Since the release of the Public Draft, our main focus has shifted to the integration problem. Web Beans generated a bunch of controversy when the draft was circulated to the EE platform expert group and proposed by Sun for inclusion in the Web Profile. That's not surprising - Web Beans solves some very important problems that lots of people have strong opinions on. I've also had a number of more technical discussions with the EE and EJB spec leads and with the EJB expert group. A number of concerns have emerged, which we're now attempting to address.
Let me share my take on these issues, and some directions we might pursue. But first...
...some history
In the days of EJB 1.x and 2.x, a major complaint against EJB was that the programming model was too restrictive. The specification imposed many annoying, distracting and unnecessary requirements upon developers. EJB 3.0 changed all that. Gone were the most of these annoying coding restrictions. In place of verbose XML deployment descriptors, EJB 3.0 was the first Java component model to be based around the use of annotations. In place of JNDI lookups was a simple dependency injection model, which ended up being generalized at the EE 5 platform level. I was a member of the EJB 3.0 expert group, and remain proud of what we accomplished.
However, the Java EE 5 dependency injection model was criticized from the outset. Many folks, including Rod Johnson of SpringSource, argued that the lack of support for injection of Java classes which were not EJBs was a fatal flaw. (At the time I did not agree, but I've changed my mind since.) On the other hand, I was dissatisfied with the lack of a contextual lifecycle model - though, in fairness, some other DI solutions of the time, including Spring, also lacked a contextual model. I was also unhappy with the mismatch between the JSF (XML-based, contextual) dependency injection model and the platform-level (annotation-based, non-contextual) model. This mismatch made it difficult to integrate EJB components with JSF.
Most of the changes introduced in EJB 3.0 and JPA 1.0 have stood the test of time remarkably well. The EE 5 dependency injection model has not. Contextual lifecycle management is now a standard feature of dependency injection solutions including Seam, Spring and Guice. Most importantly, Guice showed us the folly of using string-based names to identify implementations of an API. And Seam showed how to simplify application development by unifying dependency management in the web and EJB tiers.
Web Beans was initiated to address these problems. The original JSR proposal complained that:
-
EJB components are not aware of the web-tier request, session and application contexts and do not have access to state associated with those contexts. Nor may the lifecycle of a stateful EJB component be scoped to a web-tier context.
-
The JSF component model is not consistent with Java EE ... dependency injection...
The JSR promised to unif[y] the two component models and enabl[e] a considerable simplification to the programming model
.
A new dependency injection model was needed: a model that provided contextual lifecycle management to transactional EE components.
Is Web Beans a component model?
In the Web Beans Early Draft, we characterized Web Beans as a component model. The specification defined two things:
- a set of restrictions that a Java class or EJB session bean must satisfy in order to be a Web Bean (principally, but not only, that it must explicitly specify @Component or another deployment type), and
- the services that would then be available to the Web Bean.
I viewed this as a unifying component model: a unification that would solve a major problem that has existed since J2EE - that the Java EE web tier has a completely different component model (actually, component models plural) to the transactional tier. It promised to tear down the wall
between the two tiers, allowing transactional components to be aware of state related to the Web request. It promised a truly uniform programming model for components concerned with orchestration of the Web request, and components concerned with managing data access (at least when JSF was used).
This turned out to be the wrong approach. The strong feedback from the EE group was that Web Beans shouldn't define a new component model. The feedback from the EE spec leads at Sun was that the services defined by Web Beans should be available to all kinds of Java EE components - not just those which satisfied our definition of a Web Bean
.
At Sun's urging, we made two changes to the specification. The first was primarily a language change. We repositioned Web Beans as a set of services, provided by a Manager analogous to the JTA TransactionManager, instead of a component model
with a Container. But this also implied two more technical changes:
- we dramatically loosened the restrictions on what objects are Web Beans, so that every EJB session bean and every JavaBean is now a Web Bean, without any requirement for explicit declaration, and
- we provided a set of SPIs to allow objects which are not JavaBeans or EJB session beans to take advantage of the services provided by the Web Bean manager.
In particular, we provided injection into Servlets and message-driven beans (objects which by nature are not injectable) and an SPI that allowed other EE technologies and thirdparty frameworks to offer their components up for injection by Web Beans, and take advantage of the Web Beans services.
This was certainly the right thing to do, and the Web Beans specification is now more powerful and less intrusive. It still promises a more uniform programming model, but a side effect of these changes was that the model became even more generally useful, and even less specific to JSF and EJB. This isn't the first time I've seen something like that happen: the EJB 3.0 expert group also produced some technology (JPA, EE 5 dependency injection) that ended up being applied more generally than was originally envisaged.
Is Web Beans still a component model?
Unfortunately, some people are still not satisfied. A number of members of the platform expert group believe that the notion of a simple Web Bean still specifies a new component model. So what, exactly, is a simple Web Bean, and why do we need them?
A simple Web Bean is nothing new. It's just a Java class. You've already written hundreds or even thousands of simple Web Beans. Every JavaBean is a simple Web Bean. All we're trying to do is allow objects which were not specifically written as EJBs to be injectable and take advantage of the Web Beans services.
A simple Web Bean has the following advantages
over an EJB session bean:
- it does not need to be explicitly declared as an EJB using a component-defining annotation or XML
- its interfaces do not need to be explicitly declared using @Local or @LocalBean
- it can be final, or have final methods
- it has a more
natural
lifecycle and concurrency model - the normal lifecycle for a Java class, instead of theenhanced
lifecycle/concurrency semantics defined by EJB - if it's a stateful object, it does not require a @Remove method
- it can take advantage of constructor injection
You can use preexisting JavaBeans and many other Java classes as simple Web Beans. As a side effect, simple Web Beans reduce the mental gap
for new Java EE users who might be, initially, scared off by the unfamiliar EJB semantics - and the rather painful requirements to explicitly designate business interfaces and add empty @Remove methods - and let these new users get started with container-managed objects more easily.
On the other hand, unlike session beans, simple Web Beans, as currently defined:
- don't have method-level transaction demarcation or security
- can't have timeouts or asynchronous methods
- can't have remote interfaces or be web service endpoints
- don't have container-managed concurrency (locks)
- don't support instance-level passivation or pooling
Therefore, in my opinion (an opinion shared the current and previous EJB spec leads), simple Web Beans don't compete with EJB as a solution for the transactional tier of the application. In fact, simple Web Beans aren't really anything new - Java EE developers already use EJBs and JavaBeans side by side. Web Beans just makes their life a little easier.
But some folks disagree. For example, one expert is worried that by providing something called a simple
Web Bean, we're encouraging people to use them instead of EJB. The risk is that developers will be guided away from the use of non-simple
EJBs. This has become a real sticking point in the EE group, and threatens to derail the whole Web Beans effort.
Of course, we're trying to work through this. One possibility is that we could move the definition of a simple Web Bean to the EJB specification, as a new EJB component type. Another possibility is to simply drop simple Web Beans from the specification, and ask everyone to write all their objects as EJBs.
Personally, I can't imagine releasing Java EE 6 with a dependency injection solution that doesn't support JavaBeans. All the other solutions in the space support both JavaBeans and EJB. EE 5 missed this boat - I don't want EE 6 to repeat the mistake. And I think that this is a case where users want to make the decision about when to use EJB. They don't want us to force a decision down their throats.
Injection of other EE resource types
A second issue raised by the EE experts is that the Web Beans specification does not currently define support for injection of all the various Java EE resource types. Specifically, Web Beans does not explicitly define injection of JDBC datasources, connections, web service endpoints, remote EJBs or persistence contexts. Of course, you can still use the existing Java EE 5 @Resource and @PersistenceContext annotations to inject Java EE resources, but then you'll miss out on the advantages of the more flexible and more typesafe model defined by Web Beans.
Well, the true situation is that injection of EE resources (or anything else at all) is already supported by Web Beans, assuming that the Java EE container calls an appropriate Web Beans SPI at initialization time. But neither the EE specification nor the Web Beans specification requires it to do so. So this is an issue that should be easy to fix.
Pluggability
We put a fair amount of effort into defining the interaction between the EE container and the Web Bean manager, for the purpose of supporting pluggable Web Bean managers. However, nothing that is currently defined imposes any new requirement upon the EE container. Unfortunately, at this point, there remain a number of open issues in the specification that can only be resolved by either:
- dropping the requirement for pluggability or
- imposing new requirements upon the EE container.
(Search for Open issue
in the Public Draft if you're interested in knowing exactly what new requirements would be imposed upon the Java EE container.)
Either of these paths is technically feasible, but one of them is a lot more work and involves a lot more coordination between the various expert groups, some of which are already struggling to meet tight deadlines. If Web Beans is required in Java EE 6, it's not clear that pluggability is truly of great value to users. Does anyone really need to switch out their Web Bean manager?
I'd love to hear from the community whether pluggability is really worth pursuing.
Packages and naming
Quite a number of people hate the name Web Beans
, which they see as obscuring the generality of the model we've defined. I view the name as more of a catchy brand than a definition of what Web Beans does. Think of Microsoft and .net
. I don't mind changing the name, but nobody has yet suggested a great alternative. For one thing, I hate acronyms, and something descriptive like Java Dependency Injection wouldn't really capture all that Web Beans does.
Independently of this objection, quite a number of people think that it would be better to package our annotations by concern rather than putting them all in the package javax.webbeans. For example, the following package layout might make better sense:
- javax.dependency - DI-related annotations: binding types, deployment types, @Initializer, @Produces, etc.
- javax.contexts - scope-related annotations, Context interface
- javax.interceptor (which already exists) - interceptor and decorator related annotations
- javax.events - @Observes, event bus interfaces
I see repackaging as a great idea.
The good news
The good news is that there's very little debate about the actual technical details of the (Guice and Seam inspired) dependency injection model in Web Beans. The feedback I'm getting from spec reviewers is uniformly positive. This gives me a lot of confidence that the more political
issues are also solvable.
What do you think?
The issues I've discussed in this post are important to all members of the Java EE community and to the future direction of the Java EE platform. I don't believe that we should be making these decisions behind closed doors
, without the involvement of users. Please speak up and let us know what you want us to do. And please take the time to learn more about Web Beans.
The Web Beans (JSR-299) specification is now available for public review.
Web Beans defines a set of services for the Java EE environment that makes applications much easier to develop. Web Beans layers an enhanced lifecycle and interaction model over existing Java component types including JavaBeans and Enterprise Java Beans. As a complement to the traditional Java EE programming model, the Web Beans services provide:
- an improved lifecycle for stateful components, bound to well-defined contexts,
- a typesafe approach to dependency injection,
- interaction via an event notification facility, and
- a better approach to binding interceptors to components, along with a new kind of interceptor, called a decorator, that is more appropriate for use in solving business problems.
Web Beans is especially useful in the context of web applications, but is applicable to many different kinds of applications and may even be used in the Java SE context, in conjunction with an embeddable EJB Lite container, as defined in the EJB 3.1 specification.
The Web Beans public draft is available in PDF or HTML format at:
- http://docs.jboss.org/webbeans/spec/PDR/pdf/Web%20Beans%2020081029.pdf
- http://docs.jboss.org/webbeans/spec/PDR/html/
or from:
Please send feedback on the public draft to:
- jsr-299-comments@jcp.org
An even easier way to learn about Web Beans is the Introduction to Web Beans guide available in PDF or HTML format here:
- http://docs.jboss.org/webbeans/reference/1.0/en-US/pdf/guide.pdf
- http://docs.jboss.org/webbeans/reference/1.0/en-US/html/
The Web Beans Reference Implementation and Compatibility Test Suite are being developed at:
This is a great time to get involved!
| Showing 1 to 5 of 17 blog entries tagged 'Web Beans' |
|
|