Rick

Rick
Rick

Saturday, April 30, 2011

Red Hat's Ceylon language is an unneeded tempest in a teapot - JavaWorld

Posted from Diigo. The rest of my favorite links are here.

Thursday, April 21, 2011

Daily Dose: CDISource Promotes CDI Use | Javalobby

  • We made the Daily Dose!

    tags: CDI CDISource Andy Gibson Rob Williams Richard Hightower

    • Java Enterprise Edition 6 fans rejoice! CDISource is here. CDISource is a new organization created to promote the use of CDI (JSR 299).  Rick Hightower, co-creator of CDISource, explains the inspiration for CDISource:

      CDI is the Java standard for dependency injection (DI) and interception (AOP). It is evident from the popularity of DI and AOP that Java needs to address DI and AOP so that it can build other standards and JSRs on top of it. DI and AOP are the foundation of many Java frameworks, and CDI will be the foundation of many future specifications and JSRs.
  • CDI Source announcement from Rick Hightower

    tags: CDI

    • Announcing CDI Source

       
      We decided to create an organization, named CDISource, to promote the use of CDI. This organization is not tied to any vendor nor to Java EE 6.

      It did not take too long digging into CDI before I realized that Java Enterprise Edition 6 really nailed it this time. I have been a long time anti-EJB3 proponent. The interception model was flawed. The DI was flawed (or rather missing). CDI looks much better.

      CDI is the Java standard for dependency injection (DI) and interception (AOP). It is evident from the popularity of DI and AOP that Java needs to address DI and AOP so that it can build other standards and JSRs on top of it. DI and AOP are the foundation of many Java frameworks, and CDI will be the foundation of many future specifications and JSRs.

      CDI has merit on its own outside of the EJB and JSF space. Of course you can use CDI with JSF 2 and/or EJB 3.1. However CDI has a much wider scope than just Java EE 6 applications.
  • CDISource announcement

    tags: CDI CDISource Andy Gibson

    • n the last few weeks I have been rather busy working on a new project with Rick Hightower, who is fairly well known for his training and writings on Spring and JSF, and Rob WIlliams who is a blogger known as much for meddling in new technologies (and getting mad at the
    • In the last few weeks I have been rather busy working on a new project with Rick Hightower, who is fairly well known for his training and writings on Spring and JSF, and Rob WIlliams who is a blogger known as much for meddling in new technologies (and getting mad at them) as he is for intertwining various historical and literary references in his posts. The result of this is the CDISource project which aims to advocate and facilitate the use of the JSR 299 – Java Contexts and Dependency Injection framework across the Java landscape.
  • Gavin King, mentions CDISource in his blog.

    tags: CDISource Gavin King

  • CDI and Spring integration announcement. (Part of CDI Source.)

    tags: CDISource Spring CDI

Posted from Diigo. The rest of my favorite links are here.

The rationale for Ceylon, Red Hat's new programming language

  • Ceylon has really caught my eye. I am looking for a Strong Typed, slimmed down Java friendly language. I could not agree more about "the lambda calculus used only by theoretical computer scientists". AMEN! 

    tags: Ceylon Scala

    • It also seems like a matter of strong personal preference for King—his slides include a rather trollish dismissal of programming languages that are based on "the lambda calculus used only by theoretical computer scientists."
    • We looked closely at Scala, but we collectively concluded that it wasn't the right thing for us. Personally, I find that Scala's type system is simply more complex than I want or need, with several features I think actually harm understandability/readability, and I find its syntax a bit of a dog's breakfast.
      • I don't think it is too eccentric. There are language features that Scala provides that just make sense. However, they will never see the light of day for most developers. Scala will never be widely adopted. 

Posted from Diigo. The rest of my favorite links are here.

Wednesday, April 20, 2011

Comments on new JCache revival JSR wrt Annotations and Interception

In reading the intro and chapter 8 of the JSR 107 revised specification (http://tinyurl.com/jsr107-yeah).

It seems if there are annotations for caching, then we need a way to intercept the method calls and process the annotations.

As manik.surtani brings out in the comments on the google doc JSR 107 specification (http://tinyurl.com/jsr107-yeah).

"""
Does the spec also define how these annotations are used? E.g., would implementations need to:

1. Perform annotation scanning on a classpath
2. Intercept method calls that are appropriately annotated
3. Perform cache storage and retrieval accordingly? —
"""

CDI already does classpath scanning and CDI is a standalone JSR. It would seem that the way to do this would be to use CDI (JSR 299).
Weld (the reference implementation of CDI) has standalone support, i.e., it can be used outside of an Java EE 6 container.
Therefore CDI seems to be a natural choice as the "standard" way to provide this support.
Other frameworks, Spring, Guice, et al can provide compatible implementations of annotation scanning and feature weaving.

Also that Weld is standalone is particular nicety covered by Weld it is not in the 1.0 CDI JSR.
It will not be until the CDI 1.1. There should be some collaboration between this JSR and CDI 1.1.
I would hate two see two forms of classpath scanning and annotation processing.
It would be nice if one JSR built on top of the sweat of another.

(You may already have this planned.)

BTW I have written several AOP frameworks that capture annotations and process them for caching.
(Using Spring AOP, and AspectJ)
I am willing, able and deeply interested in developing some proofs of concepts CDI Extension that work with the new JSR 107 as part of the JSR work.

I recently wrote a CDI Extension that bridges the CDI and Spring worlds.
see http://goo.gl/UwJfU and http://goo.gl/C76sp

Saturday, April 16, 2011

CDI and Spring living in harmony



CDI and Spring living in harmony



Update: The CDI to Spring bridge works with CANDI, OpenWebBeans and Weld. The Spring to CDI extention works with CANDI and Weld.
The Spring to CDI extention partially works with OpenWebBeans (just the @SpringLookup).

Spring is very popular. CDI is very new. Although CDI is the standard for DI and Interception (light weight AOP), it is not as ubiquitous
and Spring.

Part of CDI success will be probably be indicative on how well it can play and integrate with Spring.

Realizing this, we took a Roo generated application, and fooled around with it until we were able to inject CDI beans into Spring objects. This effort is called the Spring CDI Bridge.
This basically allows you to inject CDI managed beans into Spring. We also had to go the other direction. We need the ability to inject Spring beans into CDI. This effort is called the CDI Spring Extension.

The golden ticket, is to be able to inject Spring beans into CDI beans that are then injected into Spring beans ad infinitum. This is tricky due to the different lifecycles and typing systems involved in Spring and CDI. We have achieved this as well.





Bridging from the CDI World into Spring



In order to bridge from the CDI world into the Spring world, we created a BeanFactoryPostProcessor.
This CdiBeanFactoryPostProcessor looks the CDI BeanManager in JNDI and uses it to find beans in CDI and map them as Spring bean definitions as follows:
applicationContext.xml example configuring a CdiBeanFactoryPostProcessor

 <bean class="org.cdisource.springintegration.CdiBeanFactoryPostProcessor" />

If you do not want to configure a BeanFactoryPostProcessor, you can also use CdiFactoryBean's to individually create bridges to CDI. CdiFactoryBean is similar to JndiObjectFactoryBean. In fact the CdiBeanFactoryPostProcessor configures bean definitions that are really CdiFactoryBean configured to look up a class in CDI.

.
applicationContext.xml example configuring a CdiFactoryBean to lookup a TaskRepository

 <bean class="org.cdisource.springintegration.CdiFactoryBean" name="taskRespository" >
        <property name="beanClass" value="org.cdisource.springapp.TaskRepository"/>
     </bean>

CdiBeanFactoryPostProcessor is fairly powerful. Just install it into Spring and then all of your CDI beans are available to Spring. No fuss. This works with Resin Candi, JBoss Weld, and OpenWebBeans http://openwebbeans.apache.org/owb/index.html.
You can find CdiBeanFactoryPostProcessor at CDI Spring Integration which is part of the CDI Source efforts to advocate the use of CDI. Please review CdiBeanFactoryPostProcessor and the test cases for it and the example roo based application that uses it. We are seeking feedback.




Bridging from the Spring World into CDI



We can also bridge from the Spring world into CDI. To do this we created two annotations: @Spring and @SpringLookup. @SpringLookup is the simpler of the two. It works in all three open source CDI implementations Resin Candi, JBoss Weld, and OpenWebBeans http://openwebbeans.apache.org/owb/index.html. The @Spring annotation is more complex (has more advanced features), and only works in Resin Candi, and JBoss Weld.
(We plan on filing bug reports against OpenWebBeans and trying to work with that team to improve OpenWebBeans so that the Spring annotation can work there as well.)
Examples of using Spring annotation

package org.cdisource.springintegration;

import javax.inject.Inject;

public class CdiBeanThatHasSpringInjection {
 @Inject @Spring(name="fooBar") 
 FooSpringBean springBean;

 @Inject @Spring(name="fooBarnotActuallyThere", required=false)
 FooSpringBean notActuallyThere;
 
 
 @Inject @Spring(type=FooSpringBean2.class) 
 FooSpringBean2 injectByType;

 public void validate () {
  if (springBean==null) {
   throw new IllegalStateException("spring bean was null");
  }
  if (notActuallyThere!=null) {
   throw new IllegalStateException("notActuallyThere should be null");
  }
  if (injectByType==null) {
   throw new IllegalStateException("injectByType should be there");
  }

 }
}


The form
by name

 @Inject @Spring(name="fooBar") 
 FooSpringBean springBean;


will look up the bean in Spring at the appropriate time given the appropriate name. The extension we wrote will create a Bean that has a @Named qualifier when it sees this type of injection. OpenWebBeans rejects this named qualifier. This works in Weld and Resin Candi (4.0.17 and later).
The form

 @Inject @Spring(name="fooBarnotActuallyThere", required=false)
 FooSpringBean notActuallyThere;


If there is a chance the bean will not be there, i.e., the injection is optional, you can specify a required=false. This means if we can't find the bean in Spring, don't throw an exception.
This works in Weld and Resin Candi (4.0.17 and later).
The form
by type

 @Inject @Spring(type=FooSpringBean2.class) 
 FooSpringBean2 injectByType;


The above form will look up the type in the Spring application context by type instead of by name.
FooSpringBean2 can be an interface or a concrete type.

Thus you could have a concreted implementation in Spring as follows:


 <bean name="fooBar3"  class="org.cdisource.springintegration.FooSpringBean2Impl"/>


The form
by type by name

 @Inject @Spring(name="foo2", type=FooSpringBean2.class) 
 FooSpringBean2 injectByType;


This is form will look up bean in the application context uses the name and the type. Spring throws an exemption if the types don't
match.

When developing this injection, using @Spring annotation was the ideal. Then we realized since the implementations did not support all of these
features (OpenWebBeans at this point). This is where the @SpringLookup came into play. In our minds it is not ideal, the implementations
should support the features in the @Spring annotation. @SpringLookup works in all three CDI containers. You use it as follows:


package org.cdisource.springintegration;

import javax.inject.Inject;

public class CdiBeanThatHasSpringLookupInjection {
 @Inject @SpringLookup("fooBar2")
 FooSpringBean springBean;

 @Inject @SpringLookup("fooBar2")
 FooSpringBean springBean2;

 
 public void validate () {
  if (springBean==null) {
   throw new IllegalStateException("spring bean was null");
  }
  if (springBean2==null) {
   throw new IllegalStateException("spring bean2 was null");
  }

 }
}


Using @SpringLookup never uses types and it always required. @Spring and @SpringLookup work with Candi 4.0.17 and Weld.





Background



The SpringBridge (CDI to Spring) always worked on all containers. It worked right out of the bat. I created something similar for Presto a
precursor to Crank. It would ask Hibernate for all of its managed beans and then registers a bunch of DAO, Controllers and Services on
your behalf for CRUD. The SpringBridge works the same way except instead of asking Hibernate for entities, it asks CDI for managed beans.
That part was easy. I had done it before (more or less) and am familiar with Spring after writing two large frameworks that sit on top of
Spring (Spring is my home court).

CDI is not my home court (yet). Here I needed a lot of help. The Weld reference guide to CDI was a big help. You can see the Extention uses
the lessons quite extensively (you may even see a bit of copy and paste in there). Also working with Andy Gibson and Rob Williams has
greatly expanded my CDI knowledge. I am more of a CDI enthusiast than a CDI expert.

Early version of the Spring Extention (Spring to CDI) did not work at all. We have friends on the Resin Candi core engineering team who
pointed us in the right direction. They whiteboarded a solution for us. They helped direct us what to do and then patched Resin Candi
so what we did would actually work with Resin 4.0.17. This would not exist without their help.

Initially, it only worked with Weld not Resin Candi 4.0.16. Then after Resin Candi 4.0.17, it worked better on Candi then Weld.
Then we had to rework it so it worked the same on Weld and Candi. Eseentially, we had to remove uneeded features so it would work with
Weld. Since the feature were uneeded, it was not a big deal (see Occam razor).

As I write this, Mark Struberg and I are on IRC chat #openwebbeans at ircfreenode. Mark is woking on the OpenWebBeans project.
He has forgotten more about CDI than I know and works from half way around the world from me in Austria.
He is going to see what is what with OpenWebBeans and @Spring annotation.
Perhaps @Spring Integration will work with OpenWebBeans really soon.

I guess what I am trying to say is, we could not have done this without a lot of help from a lot of people. Whatever bugs you find are mine,
whatever coolness you find is what we built on top of the shoulders of giants. We are seeking code reviews and feature requests.
What should Spring to CDI integration look like? This is our vision. What is yours?

There are 9 code listings in this article

Friday, April 15, 2011

Spring meet CDI, CDI meet Spring

I got the CDI to Spring Bridge working on Monday.
I got some design help from (Caucho) Resin's core engineering team on Monday to get an initial design and ideas for going from Spring to CDI .
(The other Direction!)
Today I got Spring to CDI integration working with Weld. It should also work with Resin 4.0.17 or Resin 4.0.18.

You can see the code at:

https://github.com/CDISource/cdisource/blob/master/spring/src/main/java/org/cdisource/springintegration/SpringIntegrationExtention.java

The tests are at:


https://github.com/CDISource/cdisource/tree/master/spring/src/test/java/org/cdisource/springintegration

This was really fun to write.

The CDI to Spring Bridge was easy and it was similar to something I wrote before for Presto (a precursor to Crank).
The Spring to CDi was much more difficult. It currently only works with Weld. It will work with Resin in the 4.0.17 release (likely).

This class does the CDI to Spring bridge:

https://github.com/CDISource/cdisource/blob/master/spring/src/main/java/org/cdisource/springintegration/CdiBeanFactoryPostProcessor.java

This class does the Spring to CDI bridge.

https://github.com/CDISource/cdisource/blob/master/spring/src/main/java/org/cdisource/springintegration/SpringIntegrationExtention.java

This roo based webapp/project uses the CDI to Spring Bridge (it runs in Resin and should run in any CDI compliant app server Glassfish, JBoss, etc.):

https://github.com/CDISource/examples/tree/master/spring-integration-example

Come fork it on github!

https://github.com/CDISource/cdisource

Tuesday, April 12, 2011

Combining Spring With CDI Part II

#summary Strategy for combining Spring and CDI

I added support for discovering all the beans in CDI and registering them all in Spring as bean definitions.

This is a continuations of the last post part 1.

The last step we added a FactoryBean that was tied to the TaskRepository.
The next step is to make this generic.

CdiFactoryBean

package org.cdisource.springintegration;

import javax.enterprise.inject.spi.BeanManager;
import javax.naming.InitialContext;

import org.springframework.beans.factory.FactoryBean;
import org.cdisource.beancontainer.BeanContainer;
import org.cdisource.beancontainer.BeanContainerImpl;
import org.cdisource.beancontainer.BeanContainerInitializationException;

public class CdiFactoryBean implements FactoryBean<Object> {

 private BeanContainer beanContainer = null;
 private final String BEAN_MANAGER_LOCATION = "java:comp/BeanManager";
 
 private Class<?> beanClass;
 
 private boolean singleton = true;

 
 public void setBeanClass(Class<?> beanClass) {
  this.beanClass = beanClass;
 }

 @Override
 public Object getObject() throws Exception {

  if (beanContainer==null) {
   InitialContext ic = new InitialContext();
   Object bean = null;
   try {
    bean = ic.lookup(BEAN_MANAGER_LOCATION);
   } catch (Exception e) {
    throw new BeanContainerInitializationException("Unable to lookup BeanManager instance in JNDI", e);
   }
   if (bean == null) {
    throw new BeanContainerInitializationException(
      "Null value returned when looking up the BeanManager from JNDI");
   }
   if (bean instanceof BeanManager) {
    beanContainer = new BeanContainerImpl((BeanManager)bean);
   } else {
    String msg = "Looked up JNDI Bean is not a BeanManager instance, bean type is " + bean.getClass().getName();
    throw new BeanContainerInitializationException(msg);
   }
  }
  return beanContainer.getBeanByType(beanClass);
 }

 @Override
 public Class<?> getObjectType() {
  return beanClass;
 }

 @Override
 public boolean isSingleton() {
  return singleton;
 }

 public void setSingleton(boolean singleton) {
  this.singleton = singleton;
 }

}


Then you can register this in the applicationContext as follows:
applicationContext.xml

     <bean class="org.cdisource.springintegration.CdiFactoryBean" name="taskRespository" >
      <property name="beanClass" value="org.cdisource.springapp.TaskRepository"/>
     </bean>


Of course, this is a bit of a pain. Do you really want to register every CDI bean in your system so it is available for Spring? Imagine a system with 25 CDI beans or 250 CDI beans. Imagine what the Spring XML file will look like. Yuck.

We need a way to map CDI beans into the spring applicationContext.

The next step is bulk import a bunch of beans from CDI into Spring as follows:

package org.cdisource.springintegration;

import java.lang.annotation.Annotation;
import java.util.Set;

import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Named;
import javax.naming.InitialContext;

import org.cdisource.beancontainer.BeanContainerInitializationException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

public class CdiBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

 @Override
 public void postProcessBeanFactory(
   ConfigurableListableBeanFactory beanFactory) throws BeansException {
  
  DefaultListableBeanFactory factory = (DefaultListableBeanFactory) beanFactory;
  
  Set<Bean<?>> beans = beanManager().getBeans(Object.class);
  for (Bean bean : beans) {
   BeanDefinitionBuilder definition = BeanDefinitionBuilder.rootBeanDefinition(CdiFactoryBean.class).addPropertyValue("beanClass", bean.getBeanClass()).setLazyInit(true);
   Named named = (Named) bean.getBeanClass().getAnnotation(Named.class);
   String name = named != null ? named.value() : bean.getBeanClass().getSimpleName() + "FactoryBean";
   factory.registerBeanDefinition(name, definition.getBeanDefinition());
  }
 }

 
 private final String BEAN_MANAGER_LOCATION = "java:comp/BeanManager";
 private BeanManager beanManager;

 private BeanManager beanManager() {
  if (beanManager == null) {
   Object bean = null;

   try {
    InitialContext ic = new InitialContext();
    bean = ic.lookup(BEAN_MANAGER_LOCATION);
   } catch (Exception e) {
    throw new BeanContainerInitializationException(
      "Unable to lookup BeanManager instance in JNDI", e);
   }
   if (bean == null) {
    throw new BeanContainerInitializationException(
      "Null value returned when looking up the BeanManager from JNDI");
   }
   if (bean instanceof BeanManager) {
    this.beanManager = (BeanManager) bean;
   } else {
    String msg = "Looked up JNDI Bean is not a BeanManager instance, bean type is "
      + bean.getClass().getName();
    throw new BeanContainerInitializationException(msg);
   }
  }
  return this.beanManager;

 }

}


The heart of the class functionality is here:

  DefaultListableBeanFactory factory = (DefaultListableBeanFactory) beanFactory;
  
  Set<Bean<?>> beans = beanManager().getBeans(Object.class);
  for (Bean bean : beans) {
   BeanDefinitionBuilder definition = BeanDefinitionBuilder
                                .rootBeanDefinition(CdiFactoryBean.class)
                                .addPropertyValue("beanClass", 
                                bean.getBeanClass()).setLazyInit(true);
   Named named = (Named) bean.getBeanClass().getAnnotation(Named.class);
   String name = named != null ? named.value() : bean.getBeanClass().getSimpleName() + "FactoryBean";
   factory.registerBeanDefinition(name, definition.getBeanDefinition());
  }


We iterate through the beans from CDI, create a Spring definition that uses CdiFactoryBean from the last step.

We register the CdiFactoryBean. We use the name from the @Named attribute if possible. If not we generate a name.

There are 4 code listings in this article

Combining Spring With CDI

#summary Combining Spring With CDI




Introduction



Notes on how to combine Spring with CDI




Using Roo to setup the sample project



I created a simple application in Roo that generated one Task entity as follows:

project --topLevelPackage org.cdisource.springapp
persistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY --jndiDataSource jdbc/basic
entity --class ~.Task --testAutomatically 
field string --fieldName title --notNull
field boolean --fieldName done 
controller all --package ~.web
perform tests
perform eclipse

Then I re-factored out the AspectJ stuff from the Task and created a new class called TaskRespository as follows:

package org.cdisource.springapp;

import java.util.List;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
@Transactional
public class TaskRepository {
 
    @PersistenceContext
    private EntityManager entityManager;

    
    public void persist(Task task) {
        this.entityManager.persist(task);
    }
    
    public void remove(Task task) {
        if (this.entityManager.contains(task)) {
            this.entityManager.remove(task);
        } else {
            Task attached = this.findTask(task.getId());
            this.entityManager.remove(attached);
        }
    }
    
    public void flush() {
        this.entityManager.flush();
    }
    
    public void clear() {
        this.entityManager.clear();
    }
    
    public Task merge(Task task) {
        Task merged = this.entityManager.merge(task);
        this.entityManager.flush();
        return merged;
    }
        
    public  long countTasks() {
        return entityManager.createQuery("select count(o) from Task o", Long.class).getSingleResult();
    }
    
    public  List<Task> findAllTasks() {
        return entityManager.createQuery("select o from Task o", Task.class).getResultList();
    }
    
    public  Task findTask(Long id) {
        if (id == null) return null;
        return entityManager.find(Task.class, id);
    }
    
    public  List<Task> findTaskEntries(int firstResult, int maxResults) {
        return entityManager.createQuery("select o from Task o", Task.class).setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
    }

}


I then changed the Controller (also pushing in the AspectJ stuff into the actual controller) to use the new TaskRepository as follows:

package org.cdisource.springapp.web;

import java.io.UnsupportedEncodingException;
import java.util.Collection;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.cdisource.springapp.Task;
import org.cdisource.springapp.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;

@RequestMapping("/tasks")
@Controller
public class TaskController {

 @Autowired
 TaskRepository repo;

 @RequestMapping(method = RequestMethod.POST)
 public String create(@Valid Task task, BindingResult bindingResult,
   Model uiModel, HttpServletRequest httpServletRequest) {

  if (bindingResult.hasErrors()) {
   uiModel.addAttribute("task", task);
   return "tasks/create";
  }

  System.out.println("HERE 1");
  uiModel.asMap().clear();
  System.out.println("HERE 2");
  task = repo.merge(task);
  System.out.println("HERE 3");

  return "redirect:/tasks/"
    + encodeUrlPathSegment(task.getId().toString(),
      httpServletRequest);

 }

 @RequestMapping(params = "form", method = RequestMethod.GET)
 public String createForm(Model uiModel) {
  uiModel.addAttribute("task", new Task());
  return "tasks/create";
 }

 @RequestMapping(value = "/{id}", method = RequestMethod.GET)
 public String show(@PathVariable("id") Long id, Model uiModel) {
  uiModel.addAttribute("task", repo.findTask(id));
  uiModel.addAttribute("itemId", id);
  return "tasks/show";
 }

 @RequestMapping(method = RequestMethod.GET)
 public String list(
   @RequestParam(value = "page", required = false) Integer page,
   @RequestParam(value = "size", required = false) Integer size,
   Model uiModel) {
  if (page != null || size != null) {
   int sizeNo = size == null ? 10 : size.intValue();
   uiModel.addAttribute("tasks", repo.findTaskEntries(page == null ? 0
     : (page.intValue() - 1) * sizeNo, sizeNo));
   float nrOfPages = (float) repo.countTasks() / sizeNo;
   uiModel.addAttribute(
     "maxPages",
     (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1
       : nrOfPages));
  } else {
   uiModel.addAttribute("tasks", repo.findAllTasks());
  }
  return "tasks/list";
 }

 @RequestMapping(method = RequestMethod.PUT)
 public String update(@Valid Task task, BindingResult bindingResult,
   Model uiModel, HttpServletRequest httpServletRequest) {
  if (bindingResult.hasErrors()) {
   uiModel.addAttribute("task", task);
   return "tasks/update";
  }
  uiModel.asMap().clear();
  repo.merge(task);
  return "redirect:/tasks/"
    + encodeUrlPathSegment(task.getId().toString(),
      httpServletRequest);
 }

 @RequestMapping(value = "/{id}", params = "form", method = RequestMethod.GET)
 public String updateForm(@PathVariable("id") Long id, Model uiModel) {
  uiModel.addAttribute("task", repo.findTask(id));
  return "tasks/update";
 }

 @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
 public String delete(@PathVariable("id") Long id,
   @RequestParam(value = "page", required = false) Integer page,
   @RequestParam(value = "size", required = false) Integer size,
   Model uiModel) {
  repo.remove(repo.findTask(id));
  uiModel.asMap().clear();
  uiModel.addAttribute("page", (page == null) ? "1" : page.toString());
  uiModel.addAttribute("size", (size == null) ? "10" : size.toString());
  return "redirect:/tasks";
 }

 @ModelAttribute("tasks")
 public Collection<Task> populateTasks() {
  return repo.findAllTasks();
 }

 String encodeUrlPathSegment(String pathSegment,
   HttpServletRequest httpServletRequest) {
  String enc = httpServletRequest.getCharacterEncoding();
  if (enc == null) {
   enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
  }
  try {
   pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
  } catch (UnsupportedEncodingException uee) {
  }
  return pathSegment;
 }
}


Here is the re-factored Task class with the JPA stuff pushed in:

package org.cdisource.springapp;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Configurable;

@Configurable
@Entity
public class Task {

    @NotNull
    private String title;

    private Boolean done;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;
    
    @Version
    @Column(name = "version")
    private Integer version;

    
    public String getTitle() {
        return this.title;
    }
    
    public void setTitle(String title) {
        this.title = title;
    }
    
    public Boolean getDone() {
        return this.done;
    }
    
    public void setDone(Boolean done) {
        this.done = done;
    }
    
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Title: ").append(getTitle()).append(", ");
        sb.append("Done: ").append(getDone());
        return sb.toString();
    }

    
    public Long getId() {
        return this.id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    public Integer getVersion() {
        return this.version;
    }
    
    public void setVersion(Integer version) {
        this.version = version;
    }
}


At this point the webapp runs. You can create tasks and list them.
I also wrote a simplified unit test for the TaskRepository:

package org.cdisource.springapp;


import static org.junit.Assert.assertEquals;

import java.util.List;

import org.cdisource.testing.junit.CdiTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.annotation.Transactional;
import org.junit.runner.RunWith;



@Configurable
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/META-INF/spring/testApplicationContext.xml")
@Transactional
public class TaskRepositoryTest {

 @Autowired
 private TaskRepository taskRepository;

 @Test
    public void testCrud() {
  Task task = new Task();
  task.setDone(true);
  task.setTitle("love rockets");
  taskRepository.persist(task);
  taskRepository.flush();
  List<Task> findAllTasks = taskRepository.findAllTasks();
  assertEquals(1, findAllTasks.size());
  taskRepository.remove(task);
  taskRepository.flush();
  List<Task> findAllTasks2 = taskRepository.findAllTasks();
  assertEquals(0, findAllTasks2.size());
    }

}






Using CDI for the TaskRepository instead of Spring



I added these to the pom.xml




{projecthome}/pom.xml



...
 <repositories>
        ...
        <repository>
            <id>caucho.maven.repo</id>
            <name>Caucho Repository</name>
            <url>http://caucho.com/m2</url>
        </repository>
        <repository>
            <id>caucho.maven.repo.snapshot</id>
            <name>Caucho Repository</name>
            <url>http://caucho.com/m2-snapshot</url>
        </repository>
        <repository>
   <id>java.net</id>
   <name>java.net Repository</name>
   <url>http://download.java.net/maven/2</url>
  </repository>
    </repositories>
...

 <dependencies>
 
  <dependency>
            <groupId>org.cdisource.beancontainer</groupId>
      <artifactId>beancontainer-api</artifactId>
      <version>1.0-SNAPSHOT</version>
  </dependency>

  <dependency>
            <groupId>org.cdisource.beancontainer</groupId>
      <artifactId>beancontainer-resin-impl</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>test</scope>
  </dependency>
        <dependency>
         <groupId>org.cdisource.testing</groupId>
   <artifactId>cdisource-testing-junit</artifactId>
   <version>1.0-SNAPSHOT</version>
         <scope>test</scope>
        </dependency>
...

The beancontainer-resin-impl is not needed at this point.
I was using it in a failed attempt to add a unit test for the new TaskRepository.
The next step is to CDIify the TaskRespository as follows:

package org.cdisource.springapp;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class TaskRepository {
 
    @PersistenceContext
    private EntityManager entityManager;

    
    public void persist(Task task) {
        this.entityManager.persist(task);
    }
    
    public void remove(Task task) {
        if (this.entityManager.contains(task)) {
            this.entityManager.remove(task);
        } else {
            Task attached = this.findTask(task.getId());
            this.entityManager.remove(attached);
        }
    }
    
    public void flush() {
        this.entityManager.flush();
    }
    
    public void clear() {
        this.entityManager.clear();
    }
    
    public Task merge(Task task) {
        Task merged = this.entityManager.merge(task);
        this.entityManager.flush();
        return merged;
    }
        
    public  long countTasks() {
        return entityManager.createQuery("select count(o) from Task o", Long.class).getSingleResult();
    }
    
    public  List<Task> findAllTasks() {
        return entityManager.createQuery("select o from Task o", Task.class).getResultList();
    }
    
    public  Task findTask(Long id) {
        if (id == null) return null;
        return entityManager.find(Task.class, id);
    }
    
    public  List<Task> findTaskEntries(int firstResult, int maxResults) {
        return entityManager.createQuery("select o from Task o", Task.class).setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
    }

}


Notice the removal of the Spring annotations and the addition of the CDI annotation.
There is only three lines of code difference.
Then to make this bean recognizable by Spring I added the following:

package org.cdisource.springapp;

import javax.enterprise.inject.spi.BeanManager;
import javax.naming.InitialContext;

import org.springframework.beans.factory.FactoryBean;
import org.cdisource.beancontainer.BeanContainer;
import org.cdisource.beancontainer.BeanContainerImpl;
import org.cdisource.beancontainer.BeanContainerInitializationException;

public class TaskRepositoryFactoryBean implements FactoryBean<TaskRepository> {

 private BeanContainer beanContainer = null;
 private final String BEAN_MANAGER_LOCATION = "java:comp/BeanManager";

 
 @Override
 public TaskRepository getObject() throws Exception {

  if (beanContainer==null) {
   InitialContext ic = new InitialContext();
   Object bean = null;
   try {
    bean = ic.lookup(BEAN_MANAGER_LOCATION);
   } catch (Exception e) {
    throw new BeanContainerInitializationException("Unable to lookup BeanManager instance in JNDI", e);
   }
   if (bean == null) {
    throw new BeanContainerInitializationException(
      "Null value returned when looking up the BeanManager from JNDI");
   }
   if (bean instanceof BeanManager) {
    beanContainer = new BeanContainerImpl((BeanManager)bean);
   } else {
    String msg = "Looked up JNDI Bean is not a BeanManager instance, bean type is " + bean.getClass().getName();
    throw new BeanContainerInitializationException(msg);
   }
  }
  return beanContainer.getBeanByType(TaskRepository.class);
 }

 @Override
 public Class<?> getObjectType() {
  return TaskRepository.class;
 }

 @Override
 public boolean isSingleton() {
  return true;
 }

}



Note that I added a new constructor to the BeanContainerImpl to make the above possible.

package org.cdisource.beancontainer;

import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Inject;

public class BeanContainerImpl extends AbstractBeanContainer {
    @Inject protected BeanManager manager;
    
    public BeanContainerImpl() {
     
    }
    
    public BeanContainerImpl(BeanManager manager) {
     this.manager = manager;
    }

...
}


I thought I had the webapp working at this point, but then realized that I was deploying old classes. I had to go back and rework things a few times to get things going.
At this point, the webapp almost works.
I change the persistence.xml as follows:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="persistenceUnit" >
  <!--  transaction-type="RESOURCE_LOCAL" Took this out. We are managing this in CDI not local.-->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>jdbc/basic</jta-data-source>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create"/>
            <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
            <property name="hibernate.connection.charSet" value="UTF-8"/>
        </properties>
    </persistence-unit>
</persistence>


I then had to disable Spring transaction support/JPA support in the web.xml and in the applicationContext.xml.
First in the web.xml as follows:
web.xml

    <!-- Commented this out to get it to work with CDI
    <filter>
        <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
        <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    </filter>
     -->
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <filter-mapping>
        <filter-name>HttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!-- Commented this out to get it to work with CDI
    <filter-mapping>
        <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    -->

applicationContext.xml

    <context:spring-configured/>
    <context:component-scan base-package="org.cdisource.springapp">
        <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>


    <!-- 
    
    Spring is no longer managing the transactions.

    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    
    <tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
     
    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/basic"/>
    <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
         -->
    
    
    <bean class="org.cdisource.springapp.TaskRepositoryFactoryBean" name="taskRespository"/>


I had some troubles getting the unit test to work. The web app does work.
The unit test is as follows:

package org.cdisource.springapp;


import static org.junit.Assert.assertEquals;

import java.util.List;

import javax.inject.Inject;

import org.cdisource.testing.junit.CdiTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;



@RunWith(CdiTestRunner.class)
public class TaskRepositoryTest {

 @Inject
 private TaskRepository taskRepository;

 @Test
    public void testCrud() {
  Task task = new Task();
  task.setDone(true);
  task.setTitle("love rockets");
  taskRepository.persist(task);
  taskRepository.flush();
  List<Task> findAllTasks = taskRepository.findAllTasks();
  assertEquals(1, findAllTasks.size());
  taskRepository.remove(task);
  taskRepository.flush();
  List<Task> findAllTasks2 = taskRepository.findAllTasks();
  assertEquals(0, findAllTasks2.size());
    }

}


There are 13 code listings in this article

Tuesday, April 5, 2011

Tuesday, March 29, 2011

Dependency Injection - An Introductory Tutorial Part 1 | Javalobby

CDI is the Java standard for dependency injection (DI) and interception (AOP). It is evident from the popularity of DI and AOP that Java needs to address DI and AOP so that it can build other standards and JSRs on top of it. DI and AOP are the foundation of many Java frameworks, and CDI will be the foundation of many future specifications and JSRs.

This article discusses dependency injection in a tutorial format. It covers some of the features of CDI such as type safe annotations configuration, alternatives and more. This tutorial is split into two parts, the first part covers the basis of dependency injection, @Inject, @Produces and @Qualifiers. The next part in this series covers advanced topics like creating pluggable components with Instance and processing annotations for configuration.

CDI is a foundational aspect of Java EE 6. It is or will be shortly supported by Caucho's Resin, IBM's WebSphere, Oracle's Glassfish, Red Hat's JBoss and many more application servers. CDI is similar to core Spring and Guice frameworks. Like JPA did for ORM, CDI simplifies and sanitizes the API for DI and AOP. If you have worked with Spring or Guice, you will find CDI easy to use and easy to learn. If you are new to Dependency Injection (DI), then CDI is an easy on ramp for picking up DI quickly. CDI is simpler to use and learn.

CDI can be used standalone and can be embedded into any application.

Source code for this tutorial, and instructions for use.

It is no accident that this tutorial follows this Spring 2.5 DI tutorial (using Spring "new" DI annotations) written three years ago. It will be interesting to compare and contrast the examples in this tutorial with the one written three years ago for Spring DI annotations.



Design goals of this tutorial


This tutorial series is meant to be a description and explanation of DI in CDI without the clutter of EJB 3.1 or JSF. There are already plenty of tutorials that cover EJB 3.1 and JSF with CDI as a supporting actor.

CDI has merit on its own outside of the EJB and JSF space. This tutorial only covers CDI. Repeat there is no JSF 2 or EJB 3.1 in this tutorial. There are plenty of articles and tutorials that cover using CDI as part of a larger JEE 6 application. This tutorial is not that. This tutorial series is CDI and only CDI.

This tutorial only has full, complete code examples with source code you can download and try out on your own. There are no code snippets where you can't figure out where in the code you are suppose to be.

We start out slow, step by step and basic. Then once you understand the fundamentals, we pick up the pace quite a bit.

All code examples have actually been run. We don't type in ad hoc code. If it did not run, it is not in our tutorial. We are not winging it.

There are clear headings for code listings so you can use this tutorial as a cookbook when you want to use some feature of CDI DI in the future. This is a code centric tutorial. Again, the code listings are in the TOC on the wiki page so you can find just the code listing you are looking for quickly like an index for a cookbook.

Decorators, Extentions, Interceptors, Scopes are out of scope for this first tutorial. Expect them in future tutorials.

If this tutorial is well recieved and we get enough feedback through, the JavaLobby articles, our google group and comments section of the wiki then we will add a comprehensive tutorial on CDI AOP (Decorators and Interceptors) and one on Extentions. The more positive and/or constructive feedback we get the more encouraged we will be to add more.



Dependency Injection


Dependency Injection (DI) refers to the process of supplying an external dependency to a software component. DI can help make your code architecturally pure.

It aids in design by interface as well as test-driven development by providing a consistent way to inject dependencies. For example, a data access object (DAO) may depend on a database connection.

Instead of looking up the database connection with JNDI, you could inject it.

One way to think about a DI framework like CDI is to think of JNDI turned inside out. Instead of an object looking up other objects that it needs to get its job done (dependencies), a DI container injects those dependent objects. This is the so-called Hollywood Principle, "Don't call us‚" (lookup objects), "we'll call you" (inject objects).

If you have worked with CRC cards you can think of a dependency as a collaborator. A collaborator is an object that another object needs to perform its role, like a DAO (data access object) needs a JDBC connection object for example.



Dependency Injection-`AutomatedTellerMachine` without CDI or Spring or Guice


Let's say that you have an automated teller machine (ATM, also known as an automated banking machine in other countries) and it needs the ability to talk to a bank. It uses what it calls a transport object to do this. In this example, a transport object handles the low-level communication to the bank.

This example could be represented by these two interfaces as follows:

See the rest at:
Dependency Injection - An Introductory Tutorial Part 1 | Javalobby

Monday, March 28, 2011

Announcing CDI Source

We decided to create an organization, named CDISource, to promote the use of CDI. This organization is not tied to any vendor nor to Java EE 6.

It did not take too long digging into CDI before I realized that Java Enterprise Edition 6 really nailed it this time. I have been a long time anti-EJB3 proponent. The interception model was flawed. The DI was flawed (or rather missing). CDI looks much better.

CDI is the Java standard for dependency injection (DI) and interception (AOP). It is evident from the popularity of DI and AOP that Java needs to address DI and AOP so that it can build other standards and JSRs on top of it. DI and AOP are the foundation of many Java frameworks, and CDI will be the foundation of many future specifications and JSRs.

CDI has merit on its own outside of the EJB and JSF space. Of course you can use CDI with JSF 2 and/or EJB 3.1. However CDI has a much wider scope than just Java EE 6 applications.

CDI is a foundational aspect of Java EE 6. It is or will be shortly supported by Caucho's Resin, IBM's WebSphere, Oracle's Glassfish, Red Hat's JBoss and many more application servers. CDI is similar to core Spring and Guice frameworks.

Like JPA did for ORM, CDI simplifies and sanitizes the API for DI and AOP. If you have worked with Spring or Guice, you will find CDI easy to use and easy to learn. 

If you are new to Dependency Injection (DI), then CDI is an easy on-ramp for picking up DI quickly. CDI is simpler to use and learn.

Although the ideas behind CDI are fundamentally sound, there are some missing pieces that can make it hard for adoption. CDISource aims to try to fill some of those missing pieces through tutorials, maven archetypes, and our open source library. We want to make the on-ramp for CDI easier by reducing the learning curve. CDI is nascent yet very promising.

Already CDISource has added support for doing unit testing (out of a Java EE container) with CDI. We did this by providing a standard interface for client side CDI so you can use Resin Candi, Seam Weld or Apache OpenWebBeans (all open source implementations of CDI).


In the last few weeks Andy Gibson, Rob Williams and I (Rick Hightower) (et al)  have been banging away on code, examples and ideas. We have come up with a mission statement (and a lot of working code).

Our mission is to :
  • Promote and facilitate the use of the Java Context and Dependency Injection (CDI) framework in relation to as many aspects of application development as possible.
  • Enable developers to take advantage of CDI independently of Java EE.
  • Provide lightweight, lean and agile access to the underlying CDI container as a core principle in our efforts.
  • Make testing easy without requiring a complex set of tools or complex deployment scenarios.
  • Enhance both Java EE development as well as the use of CDI in non Java EE application where possible.
  • Promote and enable the use of CDI in a vendor neutral environment and maximize the portability of application code across CDI implementations.
  • Not reject the ideas of Java EE but expand the usability of CDI outside the borders of Java EE application servers with frameworks that are not a part of the specification.
  • Not reject other CDI efforts but to provide another venue to promote those efforts. This is an addition. This is another voice in support of CDI.
To support these efforts we have setup the following: tutorials wiki, CDI Advocacy webiste for news on CDISource, blog, vimeo for tutorial videos, tutorial that work with Eclipse WTP, google code project for examples, google group for support, and a github repo for our beancontainer and test frameworks.

CDISource is looking for experts and enthusiasts to sign up and volunteer their time. 


You can start by looking at my brand new introduction to CDI DI over on JavaLobby.

Also look at Andy Gibson's CDISource announcement. He is much more eloquent than I.

There is so much more to come.





    Friday, February 18, 2011

    Random thoughts on JGroups

    I have been messing around with JGroups for a project.
    I am impressed how easy it is to get started. How much power it has! And how quickly they answer questions on the mailing list (even-though all my messages were screened for being too big). (Although the IRC chat is dead.)

    Some notes on JGroups (I took out the actual product names. I don't want to start a flame war.)


    JGroups is a framework for Reliable Multicast Communication.

    JGroups is used by JBoss clustering, JBoss fault tolerant JMS support, ehcache, OSCache, Apache Tomcat for clustering communication.
    JGroups is the de facto standard for reliable multicast communication a.k.a cluster communication.
    If there is a successful open source project that needs clustering, there is a good chance they are using JGroups.
    I have personally worked on projects that used JGroup. It works and it is easy to use.
    The API is similar to product X without all of the stupidity and needless abstractions that we don't need.
    If you simplify the Product X API and boil it down to exactly what we needed and then made the API work on the mostly widely used toolkit for clustering communication you would have JGroups.
    The classes we are using in Product X to do cluster communication are undocumented features. They are complicated to use.
    Conversely, JGroups has tons of documentation and is open source so we can even look at the code if we need to. Also the community is active and vibrant. 
    Steps for a JGroups push
    1. Some script or human invokes a startFlip method on the Revision Flipper
    2. Revision Flipper already knows about every service node in the cluster
    3. Revision flipper sends out a message on the "serviceACache" channel to repopulate the cache as part of this message is list of unique service names, e.g., serviceA1, serviceA2, etc.
    4. The individual service nodes get this message and populate their caches from the database if their service name is in the list (this prevents sending messages to services that were down)
    5. When the service nodes are done, they send a done message on the "serviceACache" channel
    6. If all service nodes that registered do not respond within a certain timeout, then the Revision Flipper files an bug report
    7. If any service nodes send an error message on the "serviceACache" channel then the Revision Flipper files a bug report with the details of the error
    8. Once all service are correlated by the Revision Flipper, it sends out a message to flip the caches on the "serviceACache" channel.
    9. The Revision Flipper does similar correlation of responses, error messages handling and timeout handling.
    10. When the Revision Flipper is finished with a particular service cache flipping, it sends out a message on the "serviceACache" channel that it is done. (It is then for services that were started in the middle of process to initialize themselves.)
    11. The Revision Flipper does a similar coordination with other service caches in the correct order based on configuration in the workflow engine
    12. If a service node comes up in the middle of flip, it waits until it gets the done message, it then populates it cache accordingly,



    package com.foo;
    
    import org.jgroups.JChannel;
    import org.jgroups.Message;
    import org.jgroups.ReceiverAdapter;
    import org.jgroups.View;
    import org.jgroups.blocks.MessageDispatcher;
    import org.jgroups.blocks.Request;
    import org.jgroups.blocks.RequestHandler;
    import org.jgroups.blocks.RequestOptions;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    
    public class RevisionFlipper extends ReceiverAdapter implements RequestHandler {
        private JChannel channel;
        private MessageDispatcher messageDispatcher;
        private String clusterName;
    
        public RevisionFlipper(String clusterName) {
            this.clusterName = clusterName;
        }
    
        public void viewAccepted(View newView) {
            // this.view = newView;
        }
    
        public void receive(Message msg) {
            System.out.println(msg.getSrc() + ": " + msg.getObject());
        }
    
        private void start() throws Exception {
            channel = new JChannel();
            channel.setReceiver(this);
            channel.connect(clusterName);
            messageDispatcher = new MessageDispatcher(channel, this, this, this);
            eventLoop();
    
            channel.close();
        }
    
        private void eventLoop() throws Exception {
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            while (true) {
                System.out.print("> ");
                System.out.flush();
                String line = in.readLine();
                if (line.equals("startFlip")) {
                    startFlip();
                } else {
                    Message msg = new Message(null, null, line);
                    channel.send(msg);
                }
            }
        }
    
        private void startFlip() {
    
            System.out.println("In start flip method");
            // 2. Revision Flipper already knows about every service node in the
            // cluster
            Message msg = new Message(null, null, "startFlip message");
            RequestOptions requestOptions = new RequestOptions(Request.GET_ALL,
                    5000);
            // 3. Using castMessage will block until all respond
            messageDispatcher.castMessage(null, msg, requestOptions);
            System.out.println("done casting");
        }
    
        public static void main(String[] args) throws Exception {
            new RevisionFlipper("serviceACache").start();
        }
    
        @Override
        public Object handle(Message msg) {
            System.out.println("HANDLE " + msg);
            return "success";
        }
    }
    
    

    I think this RPC approach is more appealing than using castMessage...

    package com.foo;    
    
    import org.jgroups.Channel;
    import org.jgroups.JChannel;
    import org.jgroups.blocks.Request;
    import org.jgroups.blocks.RequestOptions;
    import org.jgroups.blocks.RpcDispatcher;
    import org.jgroups.util.Util;
    
    public class RpcTest {
            Channel            channel;
            RpcDispatcher      disp;
            Object            rsp_list;
            String             props; // set by application
    
            public int print(int number) throws Exception {
                return number * 2;
            }
    
            public void start() throws Throwable {
                channel=new JChannel(props);
                disp=new RpcDispatcher(channel, null, null, this);
                channel.connect("RpcDispatcherTestGroup");
    
                for(int i=0; i < 10; i++) {
                    Util.sleep(100);
                    
                    RequestOptions requestOptions = new RequestOptions(Request.GET_ALL,
                            5000);
    
                    
                    rsp_list=disp.callRemoteMethods(null, "print", new Object[]{new Integer(i)}, new Class[]{int.class}, requestOptions);
                    System.out.println("Responses: " +rsp_list);
                }
                channel.close();
                disp.stop();
             }
    
            public static void main(String[] args) throws Throwable {
                try {
                    new RpcTest().start();
                }
                catch(Exception e) {
                    System.err.println(e);
                }
            }
        }
    
    

    Thursday, February 3, 2011

    Thoughts on Activiti deployments and usage


    I am trying to get some ideas on how people deploy Activiti. Do you use it embedded? Did  you just extend the REST-API war project? Do you actually deploy jar files to the REST-API war project? etc.
    We have a project that is going to manage a series of batch jobs. Described here under problem domain. The first phase of the project will require no human interaction (HI), but future phases will.
    I don't want to include HI, but I don't want to preclude it either.
    In order to use the tools for Activiti with all of its tooling, tracking, auditing and process viewing, we need to deploy our jars under the activiti-rest webapp. Essentially the tools (modeler, probe, explorer, etc.) use the REST API for Activiti (I think).
    I think we want to reduce this type of deployment as much as possible, i.e., we don't want to deploy just jar files that have tasks.
    I assert: If we want custom tasks and want to use the Activiti tooling (likely as per last meeting at work) then we will have to deploy Java classes (jar files) into that webapp or create a webapp that encompasses our tasks and the REST API. I don't like this approach. I don't think we would be able to get this past SCM group.
    The other option is to get a process id for the workflow send this around and have the clients of the workflow mark the current task as done (which will advance it to the next task or branch decision). This approach relies heavily on the API and in my opinion violates separating areas of concern.
    Our original idea (Ian and I's) was to use a message bus (Spring Integration) to mark the task done and then each task sends out a message where one or more batch processes (living in another JVM) will handle that step and send a done message when they are done. 
    The other possibility is to run embedded and not use the tools (no chance of HI in the future and we loose a lot of the tracking ability of the workflow). 
    I can send out some code examples and diagrams with pros and cons of each approach.
    Options:
    • Option 1: Run embedded to avoid deployment of custom tasks 
      • Can we stil use the Activiti tooling? Perhaps just to visualize, but can't run the process remotely, must run locally as custom tasks will not be deployed.
      • Custom tasks are embedded with custom nodes
      • If processing nodes exist on two different boxes, how do we send the id around
      • If it all exists on one box, then it will call into our existing custom service bus
    • Option 2: Send process id around, have each node be responsible for marking its task done
      • We could still use the tooling
      • This does spread the code around, we could wrap in a facade/lib
      • How do the nodes get the process id?
      • Seems like we need messaging
    • Option 3: Have the workflow be the message coordinator
      • Create one custom task that fires a start process message via Spring Integration (and passes name/value pairs of the execution context)
      • This custom task waits until it gets a message back that says that step is done, then it marks the task done
      • Use the complete tooling of Activiti to see processes and manage them
      • The message listeners can be Spring Managed Message Driven Beans, we can use JMS and Spring Integration for the message delivery
    • Option 4: Create custom war file based on activiti REST API war file
      • Allows use of Activiti tooling
      • We need to carry the source or break it up into jar files
      • Deploying new tasks is just a matter of rebuilding our war file
      • Calls out to services in our custom service bus
    To me the only option that make sense for our goals are Option 3 with some Option 2 (mostly Option 3 with a little Option 2 where needed) or Option 4.
    I don't like Option 1 because we lose a lot of the tooling, auditing and future human interaction.
    If I had to pick, I would pick Option 3. It divorces us from Activiti a lot. We just create one custom task to send a message and wait until it gets a continue or fail message. We can integrate with all other tasks easily including HI.
    None of our code (processing nodes) will rely on a workflow engine. Also there is some work already done to integrate Spring Integration and Activiti so we might not even have to create any custom tasks just use the integration as is.
    Based on internal meetings we have had it sounds like we are going to do either Option 1 or Option 4.
    Kafka and Cassandra support, training for AWS EC2 Cassandra 3.0 Training