Blog of Adam Warski

Java and JBoss related stuff
RSS icon Home icon
  • Ruby on Rails + CDI? Why not! Enter TorqueBox + Weld

    Posted on July 27th, 2010 Adam Warski 1 comment

    I 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 .yml file using the provided rake tasks 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 @SessionScoped beans 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 a jboss-classloading.xml file to the META-INF directory 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.xml in 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 @SessionScoped beans 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 the BeanManager.

    Adam

  • Initial valid-time support in Envers

    Posted on July 2nd, 2010 Adam Warski No comments

    I just commited initial support for valid-time auditing in Envers, a feature that a lot of users has been (directly or indirectly) asking for. It’s joint work, as Stephanie Pau contributed a patch with a large portion of those changes – thanks!

    You can try it out by checking out Hibernate trunk source code.

    What is valid-time about? So far Envers only stored the revision at which a change was made. This information is enough to retrieve historical data, however the queries are quite complicated and in advanced use cases can be time-consuming. This can be improved when we store both the start and end revisions, that is information on when data was “valid”. For historic entities, both column are filled, and for “current” data, the end revision column is null.

    Using the valid-time audit strategy, it will be possible to:

    • speed up and simplify the queries to retrieve historical data
    • implement support for queries, which traverse relations
    • implement other types of queries, like latest changes

    To configure Envers to store the end-revision number, you have to specify a property in your configuration file:

    
    <property name="org.hibernate.envers.audit_strategy">
       org.hibernate.envers.strategy.ValidTimeAuditStrategy
    </property>
    

    Envers will then generate and additional REVEND column (next to the REV column) in every audit (_AUD) entity/table; however this column won’t be part of the primary key. You can change the name of the end-revision column by setting the org.hibernate.envers.audit_strategy_valid_time_end_name property value.

    The value of the end-revision column can be calculated basing only on the original revision-changed columns, so using a couple of queries it will be possible to easily migrate existing data to the new audit strategy.

    Please note that this feature is experimental, and can be changed in the future. The associated JIRA issue is HHH-3763.

    Adam

  • NEnvers

    Posted on July 1st, 2010 Adam Warski No comments

    If you are a .NET and NHibernate user, soon you’ll be able to use Envers in your project!

    Simon Duduica has been working on an Envers to .NET port. This is still work in progress, but you can check out the current source code here: https://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunk/sandbox/simondud/Envers.NET

    A large portion was ported, but there’s also quite a lot left, so any help is appreciated. Big thanks to Simon and looking forward to a release :)

    Adam

  • Object Services in Scala

    Posted on June 21st, 2010 Adam Warski 2 comments

    Using Scala’s implicits it’s possible to implement Object Services in a much more “user-friendly” way. Just to remind, the goal is to extend a class hierarchy with a method, polymorphically. E.g. we have:

    
    trait Animal
    class Elephant extends Animal
    class Ant extends Animal
    

    and we want to add a paint method, which has a different implementation for an elephant, and for an ant (quite obviously :) ). In another words, we want to have a polymorphic extension method. One approach in Scala is to use pattern-matching. And in fact pattern-matching can be used to implement object services as described here (below is a method which uses reflection, but it can be easily swapped).

    Before we’ll go to the actual implementation, here’s how you can use the object services. We already have the objects, so it’s time to create the services:

    
    trait PaintService[O <: Animal] extends OS[O] {
       def paint(c: Canvas): Unit
    }
    
    class ElephantPaintService(elephant: Elephant) extends PaintService[Elephant] {
       def paint(c: Canvas): Unit { ... }
    }
    
    class AntPaintService(ant: Ant) extends PaintService[Ant] {
       def paint(c: Canvas): Unit { ... }
    }
    

    Now we need a place, where we register the services. In the Weld implementation, this was done automatically at container startup time. Here we’ll need one object (which could be auto-generated by a compiler plugin):

    
    object PaintServiceReg extends OSP[Animal, PaintService] {
       register[Elephant, ElephantPaintService]
       register[Ant, AntPaintService]
    }
    

    The type bound’s of the register method will make sure that you can register only appropriate services for appropriate object types. Finally, we can use our services. If we want to use the PaintService, we’ll need to import the content of the PaintServiceReg object. That way we have control, on what services are available when. Usage is quite simple and looks like a regular method invocation, as if the method was in the class hierarchy:

    
    import PaintServiceReg._
    
    val animal1: Animal = new Elephant
    animal1.paint(c)  // ElephantPaintService is called
    
    val animal2: Animal = new Ant
    animal2.paint(c)  // AntPaintService is called
    

    What’s left to show is the actual code for OS and OSP:

    
    trait OS[O]
    
    trait OSP[O <: AnyRef, S[_ <: O] <: OS[_]] {
       implicit def oToS(obj: O): S[O] = {
          val bestService = findBestService(obj.getClass())
          bestService.getConstructors()(0).newInstance(obj).asInstanceOf[S[O]]
       }
    
       protected def register[RO <: O, RS <: S[RO]](implicit manifestRO: Manifest[RO],
                manifestRS: Manifest[RS]) {
          serviceMap += manifestRO.erasure -> manifestRS.erasure
       }
    
       private var serviceMap: Map[Class[_], Class[_]] = Map()
    
       private def findBestService(objectCls: Class[_]): Class[_] = {
          serviceMap.foldLeft[(Class[_], Class[_])]((classOf[AnyRef], classOf[AnyRef]))
             ((curr, mapping) => {
             // Checking if the mapping is appropriate for the given object class
             // and more specific than the current one
             if (mapping._1.isAssignableFrom(objectCls) &&
                    curr._1.isAssignableFrom(mapping._1))
                mapping
             else curr
          })._2
       }
    }
    

    The implementation can be improved e.g. to always return the same object service reference for a given object (something like Eclipse Adapters – thanks for the link), or to provide alternative ways to instantiate the services – not necessarily with a one-arg constructor.

    The biggest problem here is that completeness is not checked – that is, if there’s a service missing for a class in the hierarchy, there will be a run-time error. But I think this also can be checked with a compiler plugin.

  • Object Services, or bridging anemic and rich models, in CDI/Weld

    Posted on May 27th, 2010 Adam Warski 3 comments

    Rich domain models are certainly a nice, object-oriented idea, but I always had one problem with them: what if they become bloated with completely unrelated methods? For objects that are frequently used in a system, we may want to add various methods, which depend on the actual class of the object. Also, what if we’d like to use some other (e.g. CDI) beans as part of the method logic? Normally in DI frameworks there’s no injection into model classes. Or we want to add a frontend-specific method, but we receive the instances from a backend service?

    Object Services try to address the issues above. Suppose we have a simple class hierarchy of animals:

    
    abstract class Animal
    class Elephant extends Animal
    class Ant extends Animal
    

    and we want to implement a paint method, which paints a picture of the given animal on a canvas. Quite obviously, painting an elephant is different from painting an ant. There are several solutions:

    • add a paint method to the Animal interface – problems outlined above
    • add a paint method, in which we check which Animal was passed using instanceof – quite ugly
    • use the visitor pattern – typesafe, but quite verbose

    I think the best solution would be to have type-safe “polymorphic extension methods”, so that in your code you could just add some methods to each class in a hierarchy, but unfortunately this isn’t supported by any Java (see also multiple dispatch).

    Another possibility is to use what I call “Object Services”. If we want to add some methods to a class hierarchy, we create a parallel hierarchy of “services” (which are normal classes):

    
    interface PaintService<T extends Animal> extends OS<T> {
       void paint(Canvas c);
    }
    
    // Implements OS<Elephant>
    class ElephantPaintService implements PaintService<Elephant> {
       // Here we can store the object, for which the service was invoked
       void setServiced(Elephant e) { ... }
       void paint(Canvas c) { ... }
    }
    
    // Implements OS<Ant>
    class AntPaintService implements PaintService<Ant> {
       // Injection works normally
       @Inject AnthillService anthill;
    
       void setServiced(Ant a) { ... }
       void paint(Canvas c) { ... }
    }
    

    OS is an interface marking some beans as object services; the class, to which the service corresponds is given as a type parameter.

    The ObjectServiceExtension will detect all beans that implement the OS interface, and register an OSP (Object Service Provider) bean which can be later injected to obtain a correct object service given an Animal:

    
    @Inject
    OSP<Animal, PaintService<Animal>> paintService;
    
    void paint(Animal a, Canvas c) {
       paintService.f(a).paint(c);
    }
    

    Each invocation of the f method will lookup the correct bean, based on the run-time type of the object passed, create a new instance of the found bean and set the object, for which the method was called. All beans created are CDI-managed, so injection etc works normally.

    
    void test(Canvas c) {
       // Will invoke paint(c) in AntPaintService
       paint(new Ant(), c);
    
       // Will invoke paint(c) in ElephantPaintService
       paint(new Elephant(), c);
    }
    

    The source code is available on GitHub in the cdiext project. To use it, just bundle the jar with your application.

    Thanks to Tomek SzymaƄski for discussing the implementation.

    So what’s next? The code could use a couple of improvements, but the biggest next task is to add deploy-time checking if there’s an object service for each class in a hierarchy (e.g. we have a PrintService and an ElephantPrintService, but forget to add an AntPrintService).

    Adam

  • CDI & Weld Extensions in Git

    Posted on May 17th, 2010 Adam Warski No comments

    Hello,

    I’ve created a new cdiext project 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

  • JSR-308, checkers framework and static analysis on GeeCON

    Posted on April 26th, 2010 Adam Warski 1 comment

    I’ll be speaking about the JSR-308 specification (annotations on java types), which will be part of Java 7, on the GeeCON conference, which will take place from the 13th till the 14th of May 2010 in Poznan, Poland.

    Apart from an introduction to the new annotations, I will cover the checkers framework, and do a live demo of some of the bundled checkers (nullability, immutability), as well as of my typestate checker. I will also show how to implement a simple custom checker, using the framework.

    If you’ll be there, be sure not to miss it. If you’ve not yet registered, visit http://2010.geecon.org :).

    See you there,
    Adam

  • Extending the security interceptor for Weld/JSF2

    Posted on April 13th, 2010 Adam Warski 2 comments

    In my previous post, I described how to create a simple security interceptor, which checks conditions defined using EL expressions, e.g.:

    
    @Secure("#{loggedInUser.name == arg0.name}")
    public List<Message> listMessages(User owner) { ... }  
    

    Now, it would be nice to be able to stack such annotations, so that they can be placed:
    * on methods
    * on classes – then the constraint applies to all methods
    * on other annotations, to create “security bindings”

    An example usage could be:

    
    @Secure("#{loggedInUser != null}")
    public class Messages {
       @AdminOnly
       public void deleteAllMessages() { ... }
    
       @Secure("#{loggedInUser.maxMessageListCount == count}")
       public List<Message> listMessages(@ELVar("user") User owner, @ELVar("count") int count) { ... }
    }  
    

    where @AdminOnly is defined as:

    
    @SecureBinding
    @Secure("#{loggedInUser.isAdministrator}")
    public @interface AdminOnly { }
    

    This way common security constraints can be expressed as annotations or on the class. I’m also using an improvement suggested by Dan Allen, to name the method arguments using @ELVar, instead of naming them arg0, arg1, etc. This also allows to refer to method arguments in the “security binding” annotations, whatever the position of the argument is.

    How to implement such annotations? Well, the first step is to create a portable extension (meaning it will work with any CDI implementation, not just Weld), which will gather, for each method, all the @Secure annotations, and their values, into one single annotation, @InterceptSecure. Having such a set of constraints to check for each method, we add the annotation to the method meta-data, using a utility class from Weld Extensions: the NewAnnotatedTypeBuilder. As the @InterceptSecure is an interceptor binding, the security interceptor will be called whenever the method is invoked.

    The extension observes the ProcessAnnotatedType event, which is fired for each bean type. If necessary, the type can be modified, to include the new annotations. The annotation is only added to Weld meta-data, not to the method itself (so there’s no bytecode manipulation or such).

    One last obstacle to overcome is to get the value of the generated @InterceptSecure annotation in the interceptor. Currently this is not possible using e.g. BeanManager, but should be address in CDI Maintenance Release (see here), so as a temporary solution all the generated annotations are stored in a map in the extension. All extensions are application-scoped beans, so the information can be accessed from the interceptor. One shortcoming of the solution is that one method may belong to several, differently annotated CDI beans.

    The code for the annotation and extension:

    
    @InterceptorBinding
    public @interface InterceptSecure {
        @Nonbinding
        String[]    value();
    }
    
    public class SecurityExtension implements Extension {
        private final Map<Method, InterceptSecure> interceptSecureForMethods = new HashMap<Method, InterceptSecure>();
    
        public InterceptSecure getInterceptSecure(Method m) {
            return interceptSecureForMethods.get(m);
        }
    
        public <T> void processAnnotatedType(@Observes ProcessAnnotatedType<T> event) {
            // A flag indicating if the builder was used to modify the annotations
            boolean used = false;
            NewAnnotatedTypeBuilder<T> builder = new NewAnnotatedTypeBuilder<T>(event.getAnnotatedType());
    
            // We need to read the values of the @Secure annotation that are present on:
            // 1. types (classes)
            // 2. methods
            // 3. arbitrarily nested on @SecureBinding annotations
    
            // Gathering the initial secure values from the type
            List<String> initialSecureValues = new ArrayList<String>();
            for (Annotation annotation : event.getAnnotatedType().getAnnotations()) {
                collectSecureValues(annotation, initialSecureValues);
            }
    
            for (AnnotatedMethod<?> m : event.getAnnotatedType().getMethods()) {
                // Gathering the secure values from the method
                final List<String> values = new ArrayList<String>(initialSecureValues);
                collectSecureValues(m, values);
    
                // If any values have been gathered, adding the annotation to the method and storing it
                // in the map.
                if (values.size() > 0) {
                    InterceptSecure is = new InterceptSecureImpl(values.toArray(new String[values.size()]));
                    builder.addToMethod(m.getJavaMember(), is);
                    used = true;
    
                    interceptSecureForMethods.put(m.getJavaMember(), is);
                }
            }
    
            // Setting the new annotated type, if any changed were made
            if (used) {
                event.setAnnotatedType(builder.create());
            }
        }
    
        private void collectSecureValues(AnnotatedMethod m, List<String> values) {
            for (Annotation annotation : m.getAnnotations()) {
                collectSecureValues(annotation, values);
            }
        }
    
        private void collectSecureValues(Annotation annotation, List<String> values) {
            if (Secure.class.isAssignableFrom(annotation.annotationType())) {
                values.add(((Secure) annotation).value());
            } else {
                if (annotation.annotationType().getAnnotation(SecureBinding.class) != null) {
                    for (Annotation nestedAnnotation : annotation.annotationType().getAnnotations()) {
                        collectSecureValues(nestedAnnotation, values);
                    }
                }
            }
        }
    
        private static class InterceptSecureImpl extends AnnotationLiteral<InterceptSecure> implements InterceptSecure {
            private final String[] values;
    
            private InterceptSecureImpl(String[] values) {
                this.values = values;
            }
    
            @Override
            public String[] value() {
                return values;
            }
        }
    }
    

    And for the interceptor:

    
    @Interceptor
    @InterceptSecure("")
    public class SecurityInterceptor {
        @Inject
        private SecurityExtension se;
    
        @AroundInvoke
        public Object checkSecurity(InvocationContext ctx) throws Exception {
            // Getting the generated @InterceptSecure annotation for the method.
            // After the CDI Maintenance Release is released, it should be possible to get the annotated
            // type of the currently invoked bean, see:
            // http://old.nabble.com/Retrieving-the-Bean-object-for-an-interceptor-td28147499.html
            // For now, we just use a map in the extension. One limitation is that this doesn't allow
            // different security annotations for methods which are used in several beans.
            InterceptSecure is = se.getInterceptSecure(ctx.getMethod());
            String[] toCheck = is == null ? null : is.value();
    
            // Check the el conditions as in the previous post
            // (...)
    
            return ctx.proceed();
        }
    }
    

    Adam

  • Hibernate 3.5-Final, Envers included, released!

    Posted on April 1st, 2010 Adam Warski No comments

    Hibernate 3.5 was just released; congratulations to Steve and the whole team!

    It’s the first final Hibernate release that includes Envers. You can find it both in the bundle downloadable from SF, as well as in the Maven repository.

    Happy Easter,
    Adam

  • Simple security interceptor in Weld/JSF2

    Posted on March 31st, 2010 Adam Warski 7 comments

    Waiting for the Seam3 security module, I wrote a simple security interceptor (inspired by the Seam2 security annotation). You can use it like this:

    
    @Secure("#{loggedInUser.name == arg0.name}")
    public List<Message> listMessages(User owner) { ... }
    

    Here, loggedInUser is a @Named Weld (CDI) bean, and arg0 is the first argument of the method. This is a slight modification to the Seam2 security annotation, where it wasn’t possible to reference arguments. If the EL expression doesn’t evaluate to true, an exception is thrown.

    The implementation is pretty straightforward, as adding an interceptor in Weld is really simple. First, we need the annotation:

    
    /**
     * @author Adam Warski (adam at warski dot org)
     */
    @Retention(RUNTIME)
    @Target({TYPE, METHOD})
    @InterceptorBinding
    public @interface Secure {
        /**
         * @return The EL expression that should be evaluated. If it evaluates to
         * {@code true}, access will be granted. The EL expression may reference
         * any objects that are in any context, as well as the arguments of the method,
         * under the names {@code arg0, arg1, arg2, ...}.
         */
        @Nonbinding
        String  value();
    }
    

    The key components here is the @InterceptorBinding meta-annotation, and specifying the value of to be @Nonbinding. If the value element was binding, then we would need to define an interceptor for each possible String value.

    Next, the interceptor itself:

    
    @Interceptor
    @Secure("")
    public class SecurityInterceptor {
        private String getArgName(int index) { return "arg" + index; }
    
        @AroundInvoke
        public Object invoke(InvocationContext ctx) throws Exception {
            FacesContext facesCtx = FacesContext.getCurrentInstance();
            ELContext elCtx = facesCtx.getELContext();
    
            Secure secure = getSecureAnnotation(ctx.getMethod());
            String expression = secure.value();
    
            // Populating the request map so that parameters are available (arg0, ...)
            Map<String, Object> requestMap = facesCtx.getExternalContext()
                    .getRequestMap();
            for (int i = 0; i < ctx.getParameters().length; i++) {
                Object parameter = ctx.getParameters()[i];
                requestMap.put(getArgName(i), parameter);
            }
    
            Boolean expressionValue = (Boolean) facesCtx.getApplication()
                    .getExpressionFactory()
                    .createValueExpression(elCtx, expression, Boolean.class)
                    .getValue(elCtx);
    
            // Removing the parameters (arg0, arg1, ...)
            for (int i = 0; i < ctx.getParameters().length; i++) {
                requestMap.remove(getArgName(i));
            }
    
            if (expressionValue == null || !expressionValue) {
                throw new SecurityException();
            }
    
            return ctx.proceed();
        }
    
        private Secure getSecureAnnotation(Method m) {
            for (Annotation a: m.getAnnotations()) {
                if (a instanceof Secure) { return (Secure) a; }
            }
            for (Annotation a: m.getDeclaringClass().getAnnotations()) {
                if (a instanceof Secure) { return (Secure) a; }
            }
    
            throw new RuntimeException("@Secure not found on method " + m.getName() +
                    " or its class " + m.getClass().getName());
        }
    }
    

    And finally, we need an entry in beans.xml, enabling the interceptor:

    
    <interceptors>
       <class>util.security.SecurityInterceptor</class>
    </interceptors>
    

    One shortcoming is that it’s not currently possible to place one @Secure annotation on the class, and another on the methods (see this thread on the forum). The idea is that then the class-level annotation expresses general security constraints, which can be later refined on the method level.

    Another missing feature, which could be easily added, is a message parameter to the annotation, which would be included in the exception in case the check fails.

    Adam