I'm the creator of Hibernate, a popular object/relational persistence solution for Java, and Seam, an application framework for enterprise Java. I've also contributed to the Java Community Process standards as Red Hat representative for the EJB and JPA specifications and as spec lead of the CDI specification. At Red Hat, I'm currently working on Ceylon, a new programming language for Java and JavaScript VMs.
I now blog at the Ceylon blog.
I also post stuff on G+.
| Recent Entries |
|
30. Oct 2012
|
|
|
20. Mar 2012
|
|
|
26. Feb 2012
|
|
|
10. Jan 2012
|
|
|
12. Aug 2011
|
|
|
11. Aug 2011
|
|
|
06. Aug 2011
|
|
|
02. Aug 2011
|
|
|
01. Aug 2011
|
|
|
24. Jul 2011
|
|
|
22. Jul 2011
|
|
|
21. Jul 2011
|
|
|
20. Jul 2011
|
|
|
19. Jul 2011
|
|
|
17. Jul 2011
|
| Ceylon | (44) |
| Contexts and Dependency Injection | (44) |
| > Web Beans < | (41) |
| Seam News | (29) |
| Seam | (28) |
| Weld | (14) |
| Java EE 6 | (13) |
| Introduction to Ceylon | (12) |
| Hibernate | (6) |
| JavaServer Faces | (6) |
| JPA | (5) |
| JPA 2 | (5) |
| Web Beans Sneak Peek | (5) |
| Criteria Queries | (4) |
| Bean Validation | (3) |
| EE6 Wishlist | (3) |
| Portable Extensions | (3) |
| Seam Wiki | (3) |
| Web Frameworks | (3) |
| Interceptors | (2) |
| JBoss Tools | (2) |
| Payasos | (2) |
| XML Hell | (2) |
| Ceylon IDE | (1) |
| EJB | (1) |
| Granite DS | (1) |
| JDO | (1) |
| News | (1) |
| 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 |
Today, Red Hat submitted the final draft of JSR-299[1], which now goes under the moniker CDI (Contexts and Dependency Injection), along with the Reference Implementation and TCK. Check out the spec[1] and Javadoc.
This specification defines a powerful set of complementary services that help improve the structure of application code.
- A well-defined lifecycle for stateful objects bound to lifecycle contexts, where the set of contexts is extensible
- A sophisticated, typesafe dependency injection mechanism, including the ability to select dependencies at either development or deployment time, without verbose configuration
- Support for Java EE modularity and the Java EE component architecture - the modular structure of a Java EE application is taken into account when resolving dependencies between Java EE components
- Integration with the Unified Expression Language (EL), allowing any contextual object to be used directly within a JSF or JSP page
- The ability to decorate injected objects
- The ability to associate interceptors to objects via typesafe interceptor bindings
- An event notification model
- A web conversation context in addition to the three standard web contexts defined by the Java Servlets specification
- An SPI allowing portable extensions to integrate cleanly with the container
I would like to take this opportunity to thank the Expert Group and everyone else who contributed ideas and criticism to this specification. Folks outside the JCP probably can't really imagine the incredible investment of time and emotional energy that it takes to create a spec like this. I would really, really like to single out a couple of individual members of the EG for their great ideas and totally uncompensated work, but I guess there's no way to do that without leaving someone feeling unrecognized.
On a more personal note, I believe (and hope) that we've done right by the community, and created something beautiful.
Tomorrow we'll be releasing Weld 1.0.
I put a whole bunch of work into the Javadoc for CDI recently. You can see it here. There's a good overview of the spec in the package doc for javax.enterprise.inject.
Oh, I also did the Javadoc for javax.interceptor, but that's not available anywhere yet.
I just noticed that CDI makes it possible to write properties files in Java, instead of plain text. I'm not sure if this is useful, but it is cute.
We define our properties in a class. Of course, since the properties are going to be deployment-specific, we should declare the class @Alternative. (Unless it holds the default values, I suppose.)
@Alternative
class TestSettings {
@Produces @Named String adminUser = "admin";
@Produces @Named String adminPassword = "nimda";
@Produces @Named int maxRetries = 100;
}
Now, we can inject these properties. Into fields:
@Inject @Named int maxRetries;
Or even into constructors or methods:
@Inject
Connection(@Named("adminUser") String user,
@Named("adminPassword") String pass) {
...
}
To select the right settings class for a deployment, we list it in beans.xml:
<beans>
<alternatives>
<class>settings.TestSettings</class>
</alternatives>
</beans>
You could even write a really simple portable extension that would weave in the necessary @Alternative, @Produces and @Named annotations to the following class:
@Properties
class TestSettings {
String adminUser = "admin";
String adminPassword = "nimda";
int maxRetries = 100;
}
(If you want to know how to do this, go read up on the ProcessAnnotatedType event that is part of the CDI portable extension SPI.)
Well, I suppose it would be more typesafe to create a Settings interface with getter methods for all the properties, and inject that. Still, for an accidental
feature, this is kinda cool.
UPDATE: hrrrm ... this feature makes somewhat more sense, when you realize that TestSettings is also a perfect place to declare all your deployment specific resources.
In my previous little rant, I showed you how to use @Alternative and alternative stereotypes to easily change bean implementations based upon deployment scenario. But that's not the end of the story. There's two other things I would sometimes like to be able to change at deployment time:
- interceptors
- decorators
Let's consider security. Suppose I have an interceptor that implements method-level role-based security for beans in the business layer
.
@Secure @Interceptor
class SecurityInterceptor {
@Inject User user;
@AroundInvoke
Object checkRole(InvocationContext ctx) throws Exception {
String[] roles = ctx.getMethod().getAnnotation(Secure.class).value();
for (String role: role) {
if ( !user.getRoles().contains(role) ) throw new AuthorizationException(role);
}
return ctx.proceed();
}
}
I also have a separate data access layer, consisting of beans that implement the following interface:
public interface DataAccess<T, V> {
public V getId(T object);
public T load(V id);
public void save(T object);
public void delete(T object);
public Class<T> getDataType();
...
}
And I have a decorator that adds row-level security to my data access layer.
@Decorator
class DataSecurityDecorator<T, V> implements DataAccess<T, V> {
@Inject @Delegate DataAccess<T, V> delegate;
@Inject User user;
public void save(T object) {
authorize(SecureAction.SAVE, object);
delegate.save(object);
}
public void delete(T object) {
authorize(SecureAction.DELETE, object);
delegate.delete(object);
}
private void authorize(SecureAction action, T object) {
V id = delegate.getId(object);
Class<T> type = delegate.getDataType();
if ( !user.getPermissions().contains( new Permission(action, type, id) ) ) {
throw new AuthorizationException(action);
}
}
}
Well, that's all very well, but in my test environment I don't want these interceptors and decorators to be enabled. And that's why, by default, they aren't.
We need to expilicity enable the interceptor and decorator for all deployments that require security access controls by declaring them in beans.xml.
<beans>
<interceptors>
<class>org.mycompany.security.SecurityInterceptor</class>
</interceptors>
<decorators>
<class>org.mycompany.security.DataSecurityDecorator</class>
</decorators>
</beans>
Suppose we have an external resource, a database, let's say, that we want to be able to change depending upon the deployment environment. In CDI, we declare resources using a producer field declaration.
class CustomerDatabase {
static
@Resource(lookup="java:global/env/jdbc/CustomerDatasource")
@Produces @CustomerDatabase
Datasource customerDatabase;
}
The purpose of this field declaration is to associate the bean type Datasource and binding type @CustomerDatabase with the Java EE resource with the global JNDI name java:global/env/jdbc/CustomerDatasource.
Now we can easily inject our Datasource into any bean that needs it:
public class Bean {
private Datasource customerDatabase;
@Inject public Bean(@CustomerDatabase Datasource ds) {
customerDatabase = ds;
}
...
}
Now, this injected resource reference is already extremely configurable. The JNDI name is just a logical name. The actual datasource it points to can easily change depending upon the deployment. We certainly haven't hardcoded a JDBC URL, username and password! But let's say that's not enough. CDI lets you define alternative implementations of a bean.
class TestCustomerDatabase {
static
@Resource(lookup="java:global/env/jdbc/TestDatasource")
@Produces @Alternative @CustomerDatabase
Datasource testCustomerDatabase;
}
@Alternative @CustomerDatabase
class MockCustomerDatabase implements Datasource {
//operations of Datasource go here!
...
}
These classes both provide an alternative implementation of @CustomerDatabase Datasource. By default, CDI will ignore these beans, and keep using the original implementation, since it is the only implementation not declared @Alternative.
However, if we declare one of the alternatives in beans.xml, CDI will use that implementation instead:
<beans>
<alternatives>
<class>org.mycompany.resources.TestCustomerDatabase</class>
</alternatives>
</beans>
That's great, and straightforward, when we only have one or two beans that vary depending upon the deployment scenario. Well, I usually consider that to be the case in most applications. However, developers whose brains have been turned to mush by overexposure to the Spring framework think that they have hundreds of beans which might vary depending upon the deployment. That's how they justify writing great gobs of XML to explicitly list out all the classes in their application. We certainly don't want to follow them down that path!
Therefore, CDI provides the ability to define an annotation that represents a deployment scenario. These annotations are called alternative stereotypes. For example:
@Alternative @Stereotype
@Target(TYPE) @Retention(RUNTIME)
public @interface Mock {}
@Alternative @Stereotype
@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
public @interface Test {}
We can now use these annotations to indicate which of our beans belong to which deployment scenario:
class TestCustomerDatabase {
static
@Resource(lookup="java:global/env/jdbc/TestDatasource")
@Produces @Test @CustomerDatabase
Datasource testCustomerDatabase;
}
@Mock @CustomerDatabase
class MockCustomerDatabase implements Datasource {
//operations of Datasource go here!
...
}
Now, with just a single line of XML, we can collectively enable all @Test beans, or all @Mock beans.
<beans>
<alternatives>
<stereotype>org.mycompany.deployment.Test</stereotype>
</alternatives>
</beans>
Don't you think that's a better way?
| Showing 1 to 5 of 38 blog entries tagged 'Web Beans' |
|
|