-
After Confitura 2011
Posted on June 13th, 2011 No commentsConfitura 2011 went past very quickly, it was a great conference and a great occasion to meet with the polish Java community on the SPOINA after-party.
During the conference I had the opportunity to present two talks.
The first, done together with Tomek Szymański was an introduction to cloud computing using Amazon Web Services. We’ve explained how the basic services that Amazon offers (servers, load balancing, databases, queueing) work, and then did a live demo transforming a traditional hosted-server+JMS+JPA application into a version which uses EC2+SQS+SimpleDB. During the presentation we simulated heavy load on our application and started a couple of servers using the EC2 API to show that it scales nicely.
The full code of the (pretty simple) application used in the presentation is available here: https://github.com/softwaremill/aws-demo, and the slides (in polish) are here: http://t.co/nCDan5R.
The second presentation was about CDI Portable Extensions. First I did an introduction to CDI and then explained the idea behind Portable Extensions. The main part of the presentation was a live demo, where I showed how to create two extensions:
- dynamic alternatives – the extension was adding and removing the
@Alternativeannotation at run-time basing on some configuration file, allowing the application to dynamically choose an implementation of the bean that should be used - dynamically creating beans which check if methods on a secure bean (secured with an interceptor) can be invoked (allowing the programmer to inject
CanAccess<MyBean>)
Again, the full code of the demo extensions is available on GitHub: https://github.com/adamw/portable-extensions-demo and the slides (in polish) here: http://slidesha.re/lvx3hh.
And finally, a huge “thank you” to all of the conference organizers (Łukasz Lenart, Bartek Zdanowski, Tomek Szymański, Michał Margiel, Paweł Wrzeszcz, Sebastian Pietrowski and Jacek Laskowski), volunteers, sponsors and participants for putting together a great event!
Adam
- dynamic alternatives – the extension was adding and removing the
-
DI in Scala: Cake Pattern pros & cons
Posted on April 29th, 2011 28 commentsI’ve been looking at alternatives for java-style DI and DI containers which would use pure Scala; a promising candidate is the Cake Pattern (see my earlier blog post for information on how the Cake Pattern works). FP enthusiast also claim that they don’t need any DI frameworks, as higher-order functions are enough.
Recently Debasish Ghosh also blogged on a similar subject. I think his article is a very good introduction into the subject.
Below are some problems I encountered with the Cake Pattern. (Higher-order functions are coming up in the next post.) If you have solutions to any of them, let me know!
Parametrizing the system with a component implementation
First of all, it is not possible to parametrize a system with a component implementation. Supposing I have three components:
DatabaseComponent,UserRepositoryComponent,UserAuthenticatorComponentwith implementations, the top-level environment/entry point of the system would be created as follows:val env = new MysqlDatabaseComponentImpl with UserRepositoryComponent with UserAuthenticatorComponent
Now to create a testing environment with a mock database, I would have to do:
val env = new MockDatabaseComponentImpl with UserRepositoryComponent with UserAuthenticatorComponent
Note how much of the code is the same. This isn’t a problem with 3 components, but if there are 20? All of them but one have to be repeated just to change the implementation of one component. This clearly leads to quite a lot of code duplication.
Component configuration
Quite often a component needs to be configured. Let’s say I have a
UserAuthenticatorComponentwhich depends onUserRepositoryComponent. However, the authenticator component has an abstract valencryptionMethod, used to configure the encryption algorithm. How can I configure the component? There are two ways. The abstract val can be concretized when defining the env, e.g.:val env = new MysqlDatabaseComponentImpl with UserRepositoryComponent with UserAuthenticatorComponent { val encryptionMethod = EncryptionMethods.MD5 }But what if I want to re-use a configured component? An obvious answer is to extend the
UserAuthenticatorComponenttrait. However if that component has any dependencies (which, in the Cake Pattern, are expressed using self-types), they need to be repeated, as self-types are not inherited. So a reusable, configured component could look like this:trait UserAuthenticatorComponentWithMD5 extends UserAuthenticatorComponent { // dependency specification duplication! this: UserRepositoryComponent => val encryptionMethod = EncryptionMethods.MD5 }If we don’t repeat the self-types, the compiler will complain about incorrect
UserAuthenticatorComponentusage.No control over initialization order
A problem also related to configuration, is that there is no type-safe way to assure that the components are initialized in the proper order. Suppose as above that the
UserAuthenticatorComponenthas an abstractencryptionMethodwhich must be specified when creating the component. If we have another component that depends onUserAuthenticatorComponent:trait PasswordEncoderComponent { this: UserAuthenticatorComponent => // encryptionMethod comes from UserAuthenticatorComponent val encryptionAlgorithm = Encryption.getAlgorithm(encryptionMethod) }and initialize our system as follow:
val env = new MysqlDatabaseComponentImpl with UserRepositoryComponent with UserAuthenticatorComponent with PasswordEncoderComponent { val encryptionMethod = EncryptionMethods.MD5 }then at the moment of initialization of
encryptionAlgorithm,encryptionMethodwill benull! The only way to prevent this is to mix in theUserAuthenticatorComponentWithMD5before thePasswordEncoderComponent. But the type checker won’t tell us that.Pros
Don’t get me wrong that I don’t like the Cake Pattern – I think it offers a very nice way to structure your programs. For example it eliminates the need for factories (which I’m not a very big fan of), or nicely separates dependencies on components and dependencies on data (*). But still, it could be better ;).
(*) Here each code fragment has in fact two types of arguments: normal method arguments, which can be used to pass data, and component arguments, expressed as the self type of the containing component. Whether these two types of arguments should be treated differently is a good question :).
What are your experiences with DI in Scala? Do you use a Java DI framework, one of the approaches used above or some other way?
Adam
-
Ruby on Rails + CDI/Weld on Torquebox example app
Posted on March 11th, 2011 2 commentsFor almost a year we’ve been successfully using Torquebox together with CDI/Weld as a base for two of our services: JBison and Circular. As we’ll be doing some presentations together with Tomek Szymański we’ve created a small application showing our setup and the CDI<->RoR integration.
The code is available on GitHub: https://github.com/softwaremill/trqbox-demo together with a readme explaining the modules, how to run the application and how to re-create it. Hope it will be helpful.
The application consists of two main modules: the backend and the frontend.
The backend is written using Java and CDI/Weld for dependency injection and management. Here we can use the whole power of CDI, with extensions, interceptors, producers etc. Also nothing stops us from using other JEE components (e.g. EJBs, JAX-RS, servlets), as Torquebox is built on JBoss AS 6, and the deployed application behaves more or less like a
.war.The frontend, on the other hand, is done purely in Ruby on Rails (plus some Javascript). For frontend development static typing is more often an obstacle than help; also, the fact that all changes are immediately visible (no redeploying etc.) is a great gain. Moreover (at least for me) doing rich ajax apps is much easier in RoR than when using e.g. JSF.
To bind the frontend and the backend, with the help from some infrastructure we can “inject” CDI beans into Rails controllers or an arbitrary Ruby class (which runs on JRuby, same JVM), e.g.:
class MyController < ApplicationController include_class "pl.softwaremill.demo.HelloWorld" def index @data = inject(HelloWorld).compute_data end endSo we can easily call our business logic to obtain data that should be displayed or trigger an action. Currently this works as a service locator, but thanks to some feedback from the Poznan JUG presentation we had this week I’ve got some ideas on improving it.
Our normal cycle of development is the following: first we develop the backend, using unit tests and Arquillian (integration tests) to verify that the beans behave as they should (if, for example, there are some new entities or queries, we test them using DB test). When this is done, we can deploy our new beans and proceed with writing the frontend.
This results in pretty fast development and little time spent waiting for the AS to boot. Plus the pleasure of using something new and unconventional ;).
Many thanks to Bob McWhirter and the whole Torquebox team as well as to Ales Justin for helping to solve some MC-related problems.
Adam
-
Dependency Injection in Scala: Extending the Cake Pattern
Posted on December 14th, 2010 20 commentsContinuing the mini-series on Dependency Injection (see my previous blogs: problems with DI, assisted inject for CDI and improving assisted inject), I took a look at how DI is handled in Scala.
There are several approaches, one of the most interesting being the Cake Pattern. It is a DI solution that uses only native language features, without any framework support. For a good introduction see either Jonas Boner’s blog (on which this post is largerly based) or Martin Odersky’s paper Scalable Component Abstractions.
I would like to extend the Cake Pattern to allow defining dependencies which need some user-provided data to be constructed (like in autofactories/assisted inject).
The Cake Pattern: interfaces
But let’s start with an example of the base pattern. Let’s say that we have a
Userclass,sealed case class User(username: String)
and that we want to create a
UserRepositoryservice. Using the Cake Pattern, first we create the “interface”:trait UserRepositoryComponent { // For expressing dependencies def userRepository: UserRepository // Way to obtain the dependency trait UserRepository { // Interface exposed to the user def find(username: String): User } }We have three important things here:
- the
UserRepositoryComponenttrait will be used to express dependencies. It contains the component definition, consiting of: - a way to obtain the dependency: the
def userRepositorymethod (could also be aval, but why adefis better I’ll explain later) - the interface itself, here a
UserRepositorytrait, which gives the functionality of locating users by username
The Cake Pattern: implementations
An implementation of a component looks pretty similar:
trait UserRepositoryComponentHibernateImpl extends UserRepositoryComponent { def userRepository = new UserRepositoryImpl class UserRepositoryImpl extends UserRepository { def find(username: String): User = { println("Find with Hibernate: " + username) new User(username) } } }Nothing special here. The component implementation extends the “interface” component trait. This brings into scope the
UserRepositorytrait, which can be implemented.Using dependencies
How can one component/service say that it depends on another? Scala’s self-type annotations are of much use here. For example, if a
UserAuthorizationcomponent requires theUserRepository, we can write this as follows:// Component definition, as before trait UserAuthorizationComponent { def userAuthorization: UserAuthorization trait UserAuthorization { def authorize(user: User) } } // Component implementation trait UserAuthorizationComponentImpl extends UserAuthorizationComponent { // Dependencies this: UserRepositoryComponent => def userAuthorization = new UserAuthorizationImpl class UserAuthorizationImpl extends UserAuthorization { def authorize(user: User) { println("Authorizing " + user.username) // Obtaining the dependency and calling a method on it userRepository.find(user.username) } } }The important part here is
this: UserRepositoryComponent =>. By this code fragment we specify that theUserAuthorizationComponentImplrequires some implementation of theUserRepositoryComponent. This also brings the content of theUserRepositoryComponentinto scope, so both the method to obtain the user repository and theUserRepositorytrait itself are visible.Wiring
How do we wire different components together? Again quite easily. For example:
val env = new UserAuthorizationComponentImpl with UserRepositoryComponentHibernateImpl env.userAuthorization.authorize(User("1"))First we need to construct the environment, by combining all of the components implementations that we want to use into a single object. Next, we can call methods on the environment to obtain services.
What about testing? Also easy:
val envTesting = new UserAuthorizationComponentImpl with UserRepositoryComponent { def userRepository = mock(classOf[UserRepository]) } envTesting.userAuthorization.authorize(User("3"))Here we have mocked the user repository, so we can test the
UserAuthorizationComponentImplin isolation.defs overvalsWhy are
defs in the component definition better as the way to obtain the dependency? Because if you use aval, all implementations are locked and have to provide a single dependency instance (a constant). With a method, you can return different values on each invocation. For example, in a web environment, this is a great way to implement scoping! The method can read from the request or session state. Of course, it is still possible to provide a singleton. Or a new instance of the dependency on each invocation.Dependencies that need user data
Finally, we arrive to the main point. What if our dependencies need some data at runtime? For example, if we wanted to create a
UserInformationservice, which wraps aUserinstance?Well, who said the the methods by which we obtain the dependencies need to be parameterless?
// Interface trait UserInformationComponent { // What is needed to create the component def userInformation(user: User) trait UserInformation { def userCountry: Country } } // Implementation trait UserInformationComponentImpl extends UserInformationComponent { // Dependencies this: CountryRepositoryComponent => def userInformation(user: User) = new UserInformationImpl(user) class UserInformationImpl(val user: User) extends UserInformation { def userCountry: Country { // Using the dependency countryRepository.findByEmail(user.email) } } } // Usage val env = new UserInformationComponentImpl with CountryRepositoryComponentImpl env.userInformation(User("someuser@domain.pl")).userCountryIsn’t this better than passing the
Userinstance as a method parameter?Using the Cake Pattern, creating stateful dependencies, which can be created at run-time with user-provided data, and still depend on other components is a breeze. This is similar to a factory method, however with much less noise.
The good and the bad
The good:
- no framework required, using only language features
- type safe – a missing dependency is found at compile-time
- powerful – “assisted inject”, scoping possible by implementing the dependency-providing method appropriately
The bad:
- quite a lot of boilerplate code: each component has a component interface, implementation, service interface and service implementation
However, I don’t think defining all four parts is always necessary. If there’s only one implementation of a component, you can combine the component interface and implementation into one, and if there’s a need, refactor later.
Adam
- the
-
Improving autofactories/assisted inject
Posted on December 7th, 2010 8 commentsIn my two previous posts I wrote about some problems with DI and a solution to part of those problems: assisted inject (as known in Guice)/autofactories (my implementation for CDI). Some problems remained however; for example in the bean constructor, the dependencies (or the environment) are mixed with the data obtained from the factory. That is also why the
@FactoryParameterannotation is required.This shortcoming can be quite easily overcome, by using field injection for dependencies, and constructors for data from the factory. How does it work? And what about testing? Read on :).
The problem
The main goal is to be able to define beans, in which dependency injection works as usual and which can be constructed on-demand with user-supplied data. Something more object-oriented than creating stateless beans where the user-supplied data is passed in method parameters, and something with less boilerplate than implementing factories.
Just to remind, as an example throughout the posts I am using a
ProductShipperbean, which needs some outside dependencies (“services”, for example aPriceCalculatorService), and must be provided with aProductobject.The solution
The base interface remains the same:
public interface ProductShipper { void ship(User target); interface Factory { ProductShipper create(Product product); } }Again just to remind, the biggest advantage of the nested factory interface is that it is clear what is needed to create a bean (here the shipper), and we spare some typing as we don’t need to write a long class name for the factory.
Now for the implementation. Before both outside dependencies and factory parameters were passed in the constructor. Now, we’ll use field injection, making a clear separation:
@CreatedWith(ProductShipper.Factory.class) public class ProductShipperImpl implements ProductShipper { @Inject private PriceCalculatorService priceCalculator; @Inject private TransportService transport; private final Product product; public ProductShipperImpl(Product product) { this.product = product; } // implement shipTo(User) }Looks quite simple. The only thing we needed to do is to specify the factory for the bean (
@CreatedWith) and provide a constructor matching the parameters of the factory. Hence, one problem remains: there’s no compile-time checking (only deployment-time), if the arguments lists match. So there’s still room for improvement! :)Usage
To use the autofactory, you simply have to inject the factory bean. The important thing is that you don’t have to implement the factory bean by hand, it is auto-generated. For example:
public class Test { @Inject private ProductShipper.Factory productShipperFactory; public void test() { ProductShipper shipper = productShipperFactory .create(new Product("butter")); shipper.shipTo(new User("me")); } }Testing
Many would argue that using field injection instead of constructor injection makes the bean much harder to test. But we can improve that quite easily, thanks to the
CDIInjectorhelper class, fromsoftwaremill-util. Here’s how we can test our bean:import static pl.softwaremill.common.util.CDIInjector.*; public class ProductShipperTest { @Test public void testShipping() { Product product = ...; ProductShipper shipper = new ProductShipperImpl(product) // Here's the important part: "dependency injection" into(shipper).inject(mockPriceCalculator, mockService); // Test goes on ... } }So instead of setting the fields explicitly via reflection (where we would have to write the field names), we just need to provide the target of injection (
into(shipper)), and the objects that we want to be injected (.inject(...)). We can also inject objects with qualifiers.As always the code is available on github, as part of the softwaremill-common project (
softwaremill-cdirelease 9 andsoftwaremill-utilrelease 13). The autofactories implementation is a portable extension (supports both styles: constructor and field/setter injection for dependencies), so all you need to do is to include the jar in your deployment.Adam
-
DI and OO: Assisted Inject in CDI / Weld
Posted on October 26th, 2010 1 commentMy last post sparked quite a lot of interest – thanks for all the comments both on the blog and on dzone! Some of them rightly pointed out that the original post contains a mistake (*) (but luckily it didn’t impact the main point). Many other suggested using the factory pattern as a solution for the problem described. However, as I wrote in the post, this requires one to implement a factory, which is impractical and leads to quite a lot of boilerplate code.
Maciej Biłas pointed me however to a nice solution, that is implemented in Guice: Assisted Inject. The idea is that an implementation of the factory can be automatically generated by the container, basing on the factory’s interface and leveraging some additional metadata from annotations. As I’m using CDI/Weld for some of my projects, I decided to write a portable extension supporting this.
As always an example would be best to illustrate what it’s about; I called my implementation
autofactories.Suppose that, as in my last post, we have a
ProductShipperinterface. To create a shipper, we need a product, so we’ll create a factory which will have one method with one argument. We can write this as follows:public interface ProductShipper { void ship(User target); interface Factory { ProductShipper create(Product product); } }By making the
Factorya nested interface, we gain two things:- it is clear what is needed to create a shipper just by looking at the main interface (no need to look at a separate factory class)
- we spare some typing as we don’t need to write another long class name (
ProductShipperFactory). However, usages of the factory identify it exactly (ProductShipper.Factory– notice the dot)
Now the implementation; let’s say it requires two services, which we want to inject, apart from the
Productobject, which is obtained through the factory method. Using autofactories, we can write it like this:@CreatedWith(ProductShipper.Factory.class) public class ProductShipperImpl implement ProductShipper { private final PriceCalculatorService priceCalculator; private final TransportService transport; private final Product product; @Inject public ProductShipperImpl(@FactoryParameter Product product, PriceCalculatorService priceCalculator, TransportService transport) { // assign fields } // implement shipTo(User) }Now you can just inject the factory interface and call the
createmethod on it, for example:public class Test { @Inject private ProductShipper.Factory productShipperFactory; public void test() { ProductShipper shipper = productShipperFactory .create(new Product("butter")); shipper.shipTo(new User("me")); } }Note that we never wrote the actual implementation of
ProductShipper.Factory. There are three annotations which are important here:@CreatedWithspecifies the factory interface, for which an implementation will be created. The interface should have only one method (later referred to as the factory method)@FactoryParameterspecifies that the annotated constructor parameter corresponds to a parameter of the same class in the factory method@Injectspecifies that other parameters should be injected from the context
Does assisted inject/autofactories solve the problems from my last blog? Only partly; there two big drawbacks of this solution:
- The dependencies of a bean on the environment/context (injected from the container) and on data (passed from the factory method) are mixed, while they are different kinds of dependencies
- No type safety: only at deployment time it is possible to verify that the parameters of the factory method match the constructor
The code is available on github, in the softwaremill-common project (
softwaremill-cdimodule). It is a portable extension, so you can use autofactories simply by including the jar in the classpath.The jar is deployed to our public Maven repository, see the project’s README for the artifact data.
There is also a test using Arquillian which can be a good usage example.
Next step: combining object services (where the emphasis is on polymorphism and extension methods) with assisted inject/autofactories.
Adam
(*) The statement that you can only create one instance of an object is wrong. Injecting an
Instancein CDI or a bean in theprototype scopein Spring, you can create on-demand instances. However all of them are constructed in the same way, using only dependencies from the container, so this doesn’t solve the original problem. -
Dependency injection discourages object-oriented programming?
Posted on October 13th, 2010 21 commentsSuppose you have a
Productentity and that you want to implement a method which sends the product to a customer (let’s call itship). For that method to work, you need a service for calculating prices and a goods transporting service. To wire the services nicely, the natural choice nowadays is a DI framework (Seam, Guice, Spring, CDI, …).Chances are high that to implement the above scenario, you would create a
ProductServiceor aProductManager(or if you have more specialized services, aProductShipper) which would look more or less like this:public class ProductService { // Here we can use setter injection, constructor injection, etc., doesn't matter @Inject private PriceCalculatorService priceCalculator; @Inject private TransportService transport; public void ship(Product product, Customer where) { int price = priceCalculator.calculate(product); // (...) transport.send(address, product); } // (...) }The main problem with that solution is that the product is always passed as an argument.
Check in your project: if you’re using DI, and you have an
Xentity, do you have anXServiceorXManagerwith lots of method whereXis the first argument?Wouldn’t it be better if you could create something like this:
public class ProductShipper { private final Product product; public ProductShipper(Product product) { this.product = product; } public void ship(Customer where) { // ??? } }The previous way is more procedural: the service/manager is a set of procedures you can run, where the execution takes a product and a customer as arguments. Here we have a more OO approach, which has many benefits:
- the product entity is encapsulated in the service
- you can pass the shipper object around
- you control where and how the shipper object is created
- you can create multiple copies of shipper objects, for multiple products
- etc
I’m not saying that achieving the above is not possible with a DI framework; only that DI encourages the
ProductServiceapproach: it’s just easier to code it procedurally, instead of e.g. creating aProductShipperfactory, passing all the needed dependencies to it and so on.An obvious problem with the new approach is that if you create a
ProductShipperobject yourself, you won’t have dependencies injected. For DI to work, the object must be managed by the container.Hence we come to some problems with DI frameworks:
- for DI to work, the objects must be managed by the container. Creating an object using some data not available upfront and having dependencies injected is not possible
- there can only be one (managed) instance of a class available at a single “execution” (for web applications, this will be per one request)
- managed objects are either stateless, or holders of “anemic” data objects; extra steps are required to create “rich” objects (if you have two
Productentities, you won’t be able to create twoProductShipperobjects with that products encapsulated, but you can create aProductsToShipHoldermanaged object into which you can add the products to ship)
How to solve these problems?
I think a good starting point is something that I call object services. Using them, you can inject a provider, with which you can obtain a service, given an entity (or any other object). The good side is that injection into the obtained services works normally. Following our example, the code could look like this:
public class UserInterface { // OSP stands for Object Service Provider @Inject OSP<Product, ProductShipper> shipperProvider; public void shipClicked() { shipperProvider.f(getProduct()).ship(getCustomer()); } } // OS stands for Object Service public class ProductShipper implements OS<Product> { private Product product; public void setServiced(Product product) { this.product = product; } // Here we can use setter injection, constructor injection, etc., doesn't matter @Inject private PriceCalculatorService priceCalculator; @Inject private TransportService transport; public void ship(Customer where) { int price = priceCalculator.calculate(product); // (...) transport.send(address, product); } }The good thing here is that
shipperProvider.f(getProduct())is a regular object, which has the product encapsulated. It can be freely passed around, and you can create multiple shippers for different products.(Another good thing here is that object services support polymorphism, so you can get different services injected for different objects!)
However this implementation still has some drawbacks; for example for injection to work the objects still have to be obtained using the provider, so that they are managed by the container. In reality most objects that are created are not managed by the container. How to obtain dependencies there? Normally they are passed e.g. in constructors, but then if suddenly an object deep down the hierarchy needs a dependency we are in trouble, and end up adding a new constructor parameter all the way up till we get to a managed object.
So stay tuned for more … :)
Adam
-
Ruby on Rails + CDI? Why not! Enter TorqueBox + Weld
Posted on July 27th, 2010 3 commentsI guess many people are often “unsatisfied” with how JSF works and how much time it sometimes takes to do a simple thing. That’s why we are trying out a new combination: RoR for the frontend and CDI for the backend. How?
Deploying RoR applications to JBoss AS is really easy thanks to the TorqueBox project. You just deploy a
.ymlfile using the providedraketasks and you can develop the application “live” – no redeploys, instant changes, and so on.Using RoR as a frontend to a CDI/Weld based application requries two more steps, so that RoR can see the business logic classes and share the same http session with CDI (so it’s possible to access
@SessionScopedbeans from RoR and CDI code).First you need to deploy your application in the
DefaultDomain(at least until TORQUE-85 is fixed). To do this, add ajboss-classloading.xmlfile to theMETA-INFdirectory with this content:<classloading xmlns="urn:jboss:classloading:1.0" domain="DefaultDomain" top-level-classloader="true" export-all="NON_EMPTY" import-all="true"> </classloading>Secondly, you need to add a filter to RoR’s web application, so that Weld and RoR share the same session. Just edit
config/web.xmlin your RoR application (the magic in the RoR deployer will add it to the virtual .war deployment it creates) and add the following:<web-app> <listener> <listener-class>org.jboss.weld.servlet.WeldListener</listener-class> </listener> </web-app>Now RoR and CDI share the same session (so you can use
@SessionScopedbeans etc, probably also@ConversationScoped, but I haven’t tried that). You can lookup CDI beans from RoR code using e.g. the BeanInject class from cdi-ext, or just by writing a very simple utility method which lookups theBeanManager.Adam
-
CDI & Weld Extensions in Git
Posted on May 17th, 2010 No commentsHello,
I’ve created a new
cdiextproject at github, initially with two extensions:1. Stackable Security Interceptors, about which I blogged here and here. Example usage:
@SecureBinding @Secure("#{loggedInUser.administrator}") public @interface AdministratorOnly { } public class SecureBean { @AdministratorOnly @Secure("#{additionalSecurityCheck}") public void doSecret() { ... } }2. Injectable ELEvaluator, which works both during a faces request and outside of one (e.g. during invocation of an MDB). Example usage:
@Inject private ELEvaluator elEvaluator; void someMethod() { // ... Integer result = elEvaluator.evaluate( "#{testParam1 + 10 + testParam2}", Integer.class, params); // ... }Thanks to Dan Allen for helping out with this one.
There are also some tests done using Arquillian – looks like it’s going to be a great testing tool! :)
Adam
-
Dependency Injection and replacing dependencies in CDI/Weld
Posted on December 16th, 2009 2 commentsFrom time to time, in a system I develop, which uses EJB3 beans as the basic “component model”, I have a need to do some operations using a new entity manager (but still in the same transaction). The problem here is that if I invoke a method on another bean, which has an entity manager injected (using
@PersistenceContext EntityManager em), the entity manager will be the original one. There is no way to temporarily replace it or any other dependency, just for the time of one invocation.That’s why I wanted to see if that would be possible to achieve using the recently released Weld framework, reference implementation of the CDI specification (part of JEE 6). Unlike in Seam, where injection is done whenever a method on a managed bean is invoked (which would theoretically make it easier to do the temporary replacement), in CDI injection happens once, when the objects are constructed. So the only way (at least the only way I see) to implement temporary replacement is to wrap the injected beans in some kind of an interceptor.
In CDI, injected beans can either be “stand-alone”, or come from a producer (factory) method (annotated with
@Producer). AsEntityManagers are typically created by producer methods, in the example below I assume this scenario. It is possible to slightly change the code so that it works for normal beans, however I didn’t manage to create a nice universal solution (which wouldn’t simply do an “if” to check if the bean is created by a producer method).To test, we define a simple bean which will have a dependency injected via constructor injection:
@ApplicationScoped public class FirstBean implements Serializable { private ISecondBean second; public FirstBean() { } @Inject public FirstBean(ISecondBean second) { this.second = second; } public void start(int c) { System.out.println("Type of second: " + second.getMessage(c)); } }The interface
ISecondBeanhas two implementations:public interface ISecondBean extends Serializable { String getMessage(int c); } @Alternative public class SecondBeanA implements ISecondBean { public String getMessage(int c) { return "variant A; " + c; } } @Alternative public class SecondBeanB implements ISecondBean { public String getMessage(int c) { return "variant B; " + c; } }The
@Alternativeannotation makes the bean disabled by default, so that Weld doesn’t try to inject an instance of it when there’s a matching injection point. That’s because we want to produce implementations ofISecondBeanusing a producer method:@ApplicationScoped public class SecondBeanProducer { @Produces public ISecondBean getSecondBean() { return new SecondBeanA(); // by default we use the A variant } }A very nice feature of Weld/CDI, especially for evaluation purposes, is that it’s possible to use it very easily in Java SE. To test our beans, all we need to do is run the
org.jboss.weld.environment.se.StartMain, putting a jar with our classes in the classpath. One important thing is that the jar must contain abeans.xmlfile (it can be empty, but it must exist). We can observe the container startup-event to do some work:@ApplicationScoped public class Main { @Inject private FirstBean first; public void start(@Observes ContainerInitialized event) throws Exception { System.out.println("Welcome to Main!"); first.start(1); first.start(2); first.start(3); } }The result will be:
Welcome to Main! Type of second: variant A; 1 Type of second: variant A; 2 Type of second: variant A; 3
Now we finally come to the point of implementing the replaceable dependencies. As you may have guessed,
ISecondBeancorresponds toEntityManager, and that’s the dependency that we will try to replace.To do that, we first have to define an interceptor. That’s quite easy and intuitive in CDI/Weld (documentation here). There are three steps:
- write an annotation, which will be an interceptor binding: all methods annotated with that annotation will be intercepted
- write the interceptor, annotating it with the annotation created earlier: that way Weld will know that the annotation binds the given interceptor
- enable the interceptor in beans.xml
Here’s the code (full interceptor code below):
@InterceptorBinding @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface ReplaceableResult { } @Interceptor @ReplaceableResult public class ReplaceableResultInterceptor { @AroundInvoke public Object replace(InvocationContext ctx) throws Exception { ... } }<beans> <interceptors> <class>test.ReplaceableResultInterceptor</class> </interceptors> </beans>Adding an interceptor for a method is easy: if we want to be able to temporarily replace implementations of
ISecondBean, all we need to do is annotate the producer method with the new annotation.SecondBeanProducernow takes the form:@ApplicationScoped public class SecondBeanProducer { @Produces @ReplaceableResult public ISecondBean getSecondBean() { return new SecondBeanA(); // by default we use the A variant } }We can now test the temporary replacement by modifying the
Mainbean that we used before:@ApplicationScoped public class Main { @Inject private FirstBean first; public void start(@Observes ContainerInitialized event) throws Exception { System.out.println("Welcome to Main!"); first.start(1); // Here we replace the implementation of ISecondBean just for // the duration of one method call. ReplaceableResultInterceptor.withReplacement( ISecondBean.class, new SecondBeanB(), // we are using the B variant new Callable<Void>() { @Override public Void call() throws Exception { first.start(2); return null; } }); first.start(3); } }The result will now be:
Welcome to Main! Type of second: variant A; 1 Type of second: variant B; 2 Type of second: variant A; 3
So the dependency in
FirstBeanwas swapped! Which was our goal: for the duration of the bean method invocation, whenever aISecondBeandependency is injected, the temporary implementation will be used.
Full code of the interceptor:@Interceptor @ReplaceableResult public class ReplaceableResultInterceptor { private static ThreadLocal<Map<Class<?>, Object>> replacements = new ThreadLocal<Map<Class<?>, Object>>() { @Override protected Map<Class<?>, Object> initialValue() { return new HashMap<Class<?>, Object>(); } }; @AroundInvoke public Object replace(InvocationContext ctx) throws Exception { Class<?> returnType = ctx.getMethod().getReturnType(); if (!returnType.isInterface()) { throw new UnsupportedOperationException("Only results of methods " + "which produce implementations of an interface can be replaced!"); } // Getting the result of the producer method Object result = ctx.proceed(); // Wrapping it in an interceptor, which on an invocation will check if // there's a replacement result = Proxy.newProxyInstance( returnType.getClassLoader(), new Class[] { returnType }, new ReplaceableInterceptor(returnType, result)); return result; } public static <V> V withReplacement(Class<?> replacing, Object replacement, Callable<V> toCall) throws Exception { boolean hasOld = false; Object old = null; try { hasOld = replacements.get().containsKey(replacing); old = replacements.get().put(replacing, replacement); return toCall.call(); } finally { if (hasOld) { replacements.get().put(replacing, old); } else { replacements.get().remove(replacing); } } } private class ReplaceableInterceptor implements InvocationHandler { private final Class<?> replacementsKey; private final Object delegate; private ReplaceableInterceptor(Class<?> replacementsKey, Object delegate) { this.replacementsKey = replacementsKey; this.delegate = delegate; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (replacements.get().containsKey(replacementsKey)) { return method.invoke(replacements.get().get(replacementsKey), args); } else { return method.invoke(delegate, args); } } } }Overall, CDI/Weld works very well and I’m very satisfied with it. One thing I’m missing is being to able to do programmatic configuration (Guice-style), but it’s already in the list of ideas for future portable extensions. I think that programmatic configuration and the ability to run Weld in JavaSE will create a great mix for “semi-integration” testing.
Adam






Twitter