Saturday, June 4, 2011

Seam JMS 3.0.0.Beta2 is now out!

Finally, Beta2 of the Seam JMS project is now available. This is mostly a minor improvement release:

1. Support for TopicBuilders and QueueBuilders, simple interfaces for sending and receiving messages with JMS. To use one, just inject a reference:

@Inject QueueBuilder queueBuilder;

Then, choose destinations and send messages:

queueBuilder.destination("jms/SomeQueue").send("This is my text");

No need for complicated objects or anything. In addition, the TopicBuilder supports Subtopics. Subtopics are based around message selectors, using a String property sm_jms_subtopic.

2. Changes in the mapping APIs. Instead of using @Routing(RouteType.INGRESS) or @Routing(RouteType.EGRESS) you can simply use @Inbound and @Outbound. I figure this will be easier to read and remember.

3. Some big documentation clean ups occurred, and I'm still working on some more.

Visit the module homepage here: http://sfwk.org/Seam3/JMSModule
Grab the download here: http://sourceforge.net/projects/jboss/files/Seam/JMS

Visit the Seam Community Forums with any questions, comments or issues!

Sunday, April 17, 2011

Running CDI Source on JBoss AS 6

For those unaware, last month an initiative called CDI Source was announced by Rick Hightower. It looks like their goals are pretty similar to Seam, a tool I've been using for a few years now; and most recently started actually contributing to!

I was curious yesterday (mostly because it was pouring here all day) to see what had come of it, and happened to notice they were first tackling CDI & Spring interoperability. Not a bad move I thought, Spring already has all of the add-ons you would be looking for (arguably too many), so being able to bring that in to a CDI enabled application makes a lot of sense. I would still argue that Spring really needs to be able to delegate down to an underlying CDI implementation in these cases, mostly for performance reasons.

I decided to clone their repositories. They have two currently, one is their underlying beancontainer and another for examples (they also host a resin plugin for maven, but out of scope..). When I cloned and started digging in to it, I found some things that were cool (tests worked out of the box) and some things I didn't like (platform dependence). I built the main project, no issue. I built the example spring app, had an issue there - tests didn't run. So I rebuilt without tests, generated a WAR file. I then tried to deploy it to JBoss AS 6. No luck, talk about nearly killing a VM. I deployed to a stopped JBoss instance, and attempted to start up, received a lot of classloader based errors (missing XAManager, base classloader setup wrong, etc). Never fun, though reminded me of the issues I have in Seam JMS :-)

When I dug into the code, I found a few problems. The biggest I saw was due to all of the extra dependencies that Spring pulls in, deployment to a full application server (as it always used to be) was going to be a challenge. I tried marking dependencies as provided, but no luck. Still were being pulled in for some reason. So I decided to pull out the pre-maven rule book and ripping out libraries under WEB-INF/lib. I was able to string the list down to these:

  • aopalliance-1.0.jar
  • aspectjrt-1.6.11.M2.jar
  • aspectjweaver-1.6.11.M2.jar
  • beancontainer-api-1.0-SNAPSHOT.jar
  • commons-beanutils-1.8.0.jar
  • commons-collections-3.1.jar
  • commons-dbcp-1.3.jar
  • commons-digester-2.0.jar
  • commons-fileupload-1.2.1.jar
  • commons-pool-1.5.4.jar
  • dom4j-1.6.1.jar
  • flexjson-2.1.jar
  • jcl-over-slf4j-1.6.1.jar
  • joda-time-1.6.jar
  • slf4j-api-1.6.1.jar
  • slf4j-log4j12-1.6.1.jar
  • spring-aop-3.0.5.RELEASE.jar
  • spring-asm-3.0.5.RELEASE.jar
  • spring-aspects-3.0.5.RELEASE.jar
  • spring-beans-3.0.5.RELEASE.jar
  • springbridge-1.0-SNAPSHOT.jar
  • spring-context-3.0.5.RELEASE.jar
  • spring-context-support-3.0.5.RELEASE.jar
  • spring-core-3.0.5.RELEASE.jar
  • spring-expression-3.0.5.RELEASE.jar
  • spring-jdbc-3.0.5.RELEASE.jar
  • spring-js-resources-2.2.1.RELEASE.jar
  • spring-orm-3.0.5.RELEASE.jar
  • spring-tx-3.0.5.RELEASE.jar
  • spring-web-3.0.5.RELEASE.jar
  • spring-webmvc-3.0.5.RELEASE.jar
  • tiles-api-2.2.1.jar
  • tiles-core-2.2.1.jar
  • tiles-jsp-2.2.1.jar
  • tiles-servlet-2.2.1.jar
  • tiles-template-2.2.1.jar
Yep, had to shrink it down to 36 libraries. Still a lot of libraries in place. Attempting to deploy this resulted in some Weld errors, resolving around injection targets. I figured they were incorrectly creating injection targets in the code, and confirmed that in their SpringIntegrationExtention class, they were making beans that were also injection targets, for some reason. When I removed this code, the application deployed fine. I still can't run the application correctly due to a tiles error (see here) but at least it deploys fine now.

As of this morning, I saw that Rick had also been working on it, and made essentially the same change I did to the code to make it work with Weld.

Tuesday, April 5, 2011

Seam JMS 3.0.0.Beta1 is now available

I am ecstatic to announce the release of Seam JMS 3.0.0.Beta1 to the wild. This is the first release of the module intended for deployment on JBoss AS 6. With this release we have added support for both egress (outbound to a JMS Queue/Topic) and ingress (inbound from a JMS Queue/Topic) event routes. We also provide a simplified messaging API for use within applications.

Downloads

The Seam JMS 3.0.0.Beta1 package can be downloaded at http://sourceforge.net/projects/jboss/files/Seam/JMS

Documentation

You can find our Reference Guide as well as API Docs

Maven Users

The easiest way to get started in a maven project is to include the following dependency in your project. You'll need to make sure you have a repository reference to the JBoss Community Repository.


<dependency>
<groupid>org.jboss.seam.jms</groupid>
<artifactid>seam-jms</artifactid>
<version>3.0.0.Beta1</version>
</dependency>


APIs

The core API for the module is around the MessageManager interface. This provides a series of convenient methods

Deployment Capabilities

You can also statically define routes within your application, both ingress and egress. You can define interfaces defining routes. Further details can be read in the Reference Guide.

Sunday, July 18, 2010

Outsource Source Control

It's been a while blog, but I have something on my mind that I need to get out there.

As some may know, my company still uses SCCS for source control. More over, they included a home grown wrapper around it to make source control SOX compliant. What? Why is source control a SOX compliance issue? For binary files, you don't even want to know (and we're big on discoverer reports).

Anyways, my group is allowed to use CVS, as SCCS cannot control Java (I swear this is what I was told). I hate it. I come from ClearCase and Subversion in my background. ClearCase had a lot of awesome features, but probably overkill for small shops. Subversion, to me it had very few features, but it worked.

Personally, I love the distributed model. The problem we have at work is that everyone can get on to test machines, and they will only host source code on test machines. I want a central server where no one else can get to the code. I've thought about outsourcing the source control, but I'm worried about externals getting the code. Anyone know if the hosters provide NDAs and private/secure repositories?

Saturday, March 20, 2010

Dyanmic ResourceBundles in CDI

So I consider this blog post more of a"Part 2" from my last blog post.

If you're anything like me, you like using ResourceBundles but find them to be an annoyance when it comes to using the same bundle in both your view and actions. I'm attempting to, with this blog post, make that a lot simpler for you.

What are resource bundles? java.util.ResourceBundle is an abstract class in Java SE that is Locale aware. It's an easy way to add i18n support in your application. You can use it to load "bundles" either programatically or from a properties file. In this example, I will provide you with some code that loads the bundle from a properties file, have an optional annotation that can specify what bundle and what locale, as well as code that dynamically looks up Locales.

Just like last time, we'll need to have a Producer method. In this example, the annotation is optional (as we assume that this code can handle the injection of any instance of java.util.ResourceBundle) and there will be an optional secondary producer for the Locale itself.

So first, the first draft of the Producer method:



@Produces
public ResourceBundle produceResourceBundle(InjectionPoint ip) {
Class container = ip.getMember().getDeclaringClass();
String baseName = container.getCanonicalName().replace(".","/");
Locale locale = Locale.getDefault();
return ResourceBundle.getBundle(baseName, locale);
}


Now, clearly this producer doesn't work that well, but it's a start. Using this, you can use @Inject ResourceBundle bundle; which if it is placed inside of a class com.tad.cdi.comps.Bundler, will look for a bundle with the same name; com/tad/cdi/comps/Bundler. Good so far, right?

Now I'm going to introduce the optional qualifier, @Bundle. Using @Bundle, you can specify a runtime dependency on either a different ResourceBundle (then the one being injected into) or a different locale.

Bundle.java:

@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Bundle {
public String baseName() default "";
public String locale() default "";
}


The Producer method to support this grows a bit, as we now support @Bundle, @Bundle(baseName="") @Bundle(locale="") and @Bundle(baseName="",locale="") so we have to add this logic to the producer.

A note for those not familiar with them: Locales, in string format, take the shape of language_Country_qualifier, so you can write something as simple as "en", "sp_US", or even "fr_CA_with.napoleon.dialect" as your Bundle.

An appropriate producer method would look something like this:


@Produces
public ResourceBundle produceResourceBundle(InjectionPoint ip) {
Bundle b = null;
if (ip.getAnnotated().isAnnotationPresent(Bundle.class)) {
b = ip.getAnnotated().getAnnotation(Bundle.class);
}
Class container = ip.getMember().getDeclaringClass();
String baseName = (b == null || b.baseName().equals("")) ? container.getCanonicalName() : b.baseName();
Locale locale = null;
if (b == null) {
locale = Locale.getDefault();
} else if (b.locale().equals("") || b.locale().equals("default")) {
locale = Locale.getDefault();
} else {
String[] lpieces = b.locale().split("_", 3);
switch (lpieces.length) {
case 0:
locale = Locale.getDefault();
break;
case 1:
locale = new Locale(lpieces[0]);
break;
case 2:
locale = new Locale(lpieces[0], lpieces[1]);
break;
case 3:
locale = new Locale(lpieces[0], lpieces[1], lpieces[2]);
break;
default:
locale = Locale.getDefault();
break;
}
}
baseName = baseName.replace(".", "/");
return ResourceBundle.getBundle(baseName, locale);
}


What we're doing with this code, we allow a a baseName to be specified in the @Bundle, this can take the form of "some.dotted.expression" or even "some/path/expression," meaning the bundle can be anywhere - doesn't need to be one dedicated to this class. Note that the behavior of @Bundle if no baseName is found is to use the enclosing class. Locale works similarly as well, you can specify locale="some_locale_expression" to load the locale, or leave it blank to load the default locale.

Still, this may not do everything that you need. If you're like me, you have some object that contains the locale of the current HTTP Session/User. And it may look something like this:


@SessionScoped
public class User {
...
public Locale getUsersLocale() { return myLocale; }
...
}


Well, if you've already gotten that part, then you're almost done. Using the BeanManager interface in CDI, you can actually dynamically load this Locale using BeanManager.getReference. First thing you need to do is add a Producer equivalent to the above method. Preferably, since User is already a SessionScoped CDI ManagedBean, the producer will go into the same method. Now, you do need to remember to handle the rules of CDI Producers - can't return null. So here's how to add the necessary logic to produce the Locale:


@SessionScoped
public class User {
...
public Locale getUsersLocale() { return myLocale; }
@Produces public Locale produceSessionUsersLocale() { return myLocale; }
...
}


What this now does is produce a Dependent Locale into your context. You can then modify your ResourceBundle producer in the following way; note that I have added logic that works even if this producer is absent, based on the previous steps.


@Inject
BeanManager beanManager;

@Produces
public ResourceBundle produceResourceBundle(InjectionPoint ip) {
Bundle b = null;
if (ip.getAnnotated().isAnnotationPresent(Bundle.class)) {
b = ip.getAnnotated().getAnnotation(Bundle.class);
}
Class container = ip.getMember().getDeclaringClass();
String baseName = (b == null || b.baseName().equals("")) ? container.getCanonicalName() : b.baseName();
Locale locale = null;
try {
Bean localeBean = (Bean) beanManager.getBeans(Locale.class).iterator().next();
CreationalContext cc = beanManager.createCreationalContext(localeBean);
Locale producedLocale = (Locale) beanManager.getReference(localeBean, Locale.class, cc);
locale = producedLocale;
} catch (Exception e) {
//not sure what to do here yet.
System.out.println("Caught an exception trying to load a ResourceBundle");
if (b == null) {
locale = Locale.getDefault();
} else if (b.locale().equals("") || b.locale().equals("default")) {
locale = Locale.getDefault();
} else {
String[] lpieces = b.locale().split("_", 3);
switch (lpieces.length) {
case 0:
locale = Locale.getDefault();
break;
case 1:
locale = new Locale(lpieces[0]);
break;
case 2:
locale = new Locale(lpieces[0], lpieces[1]);
break;
case 3:
locale = new Locale(lpieces[0], lpieces[1], lpieces[2]);
break;
default:
locale = Locale.getDefault();
break;
}
}
}
baseName = baseName.replace(".", "/");
return ResourceBundle.getBundle(baseName, locale);
}


So as you can see, we are attempting to lookup the Locale in the current context. If we find one, we always use that Locale; otherwise we use the original logic.

Now obviously, this guide wouldn't be too useful unless we had some Arquillian test cases.

The code is located in the same project as the previous post, but here are the essentials.

A test producer object, this can produce Locale as needed:


public class LocaleProducer {
@Produces
public Locale produceSomeLocale() {
System.out.println("Have a request for Locale English...");
return Locale.ENGLISH;
}
}


I also wrote two tests, one that uses the Locales with and without @Bundle, another that uses the producer style.

To verify the logic without Producing Locales:


@Deployment
public static JavaArchive createDeployment() {
return Archives.create("test.jar", JavaArchive.class)
.addClass(BundleProducer.class)
.addClass(Bundle.class)
.addResource("com/tad/cdi/mods/properties/ResourceBundleInjectTest.properties")
.addResource("com/tad/cdi/mods/properties/Special_sp.properties")
.addManifestResource("META-INF/beans.xml",
ArchivePaths.create("beans.xml"));
}

@Inject ResourceBundle bundle;

@Inject @Bundle(baseName="com/tad/cdi/mods/properties/Special",locale="sp")
ResourceBundle bundleSpecialSP;

@Test
public void testBundleContents() {
assertEquals("world",bundle.getString("hello"));
}

@Test
public void testBundleSpecified() {
assertEquals("bottom",bundleSpecialSP.getString("bob"));
}


And to test including the ability to produce locales:


@Deployment
public static JavaArchive createDeployment() {
return Archives.create("test.jar", JavaArchive.class)
.addClass(BundleProducer.class)
.addClass(Bundle.class)
.addClass(LocaleProducer.class)
.addResource("com/tad/cdi/mods/properties/ProducedLocaleTest_en.properties")
.addManifestResource("META-INF/beans.xml",
ArchivePaths.create("beans.xml"));
}

@Inject ResourceBundle bundle;

@Test
public void testBundleContents() {
assertEquals("world",bundle.getString("hello"));
}


So there you have it, enjoy your ResourceBundles!

Sunday, March 14, 2010

Writing a Property Loader in Java EE 6 and Testing it using Arquillian

So, like most people, I'm interested in Java EE 6, and the new CDI framework that comes with it. I see it as a huge time saver and seems to fit in well with the whole ecosystem of Java EE (not to mention, it also knocks Spring down a little, a plus in my book).

We're beginning to adopt Java EE 6 at work. A big application has been running for a few weeks already and now we have a couple of smaller applications that are likely to run with our live site (one being a search engine). I'm not aiming this article to be an intro to Weld, CDI or Java EE 6; I would expect anyone reading this to be at least familiar with the concepts.

Something that's big for us is testing, and allowing the application to be configurable. We definitely push the separation between development and administration and I have been ensuring that all applications match that mindset. As a result, loading property files is a typical use case for us. I was looking at how we've been doing it, and decided that it should be much simpler if we had a producer method to produce property files. Some of our files reside in the deployment archives, most on the file system; and we usually like to make it a system property to configure where to read the files from. Below is some sample code explaining how to implement a Property Loader in CDI

First, the qualifier; it only takes one argument the value.

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface ConfiguredBy {
@Nonbinding public String value();
}


We use Nonbinding on the value so that there's only one producer necessary; since the value is essentially an argument to what we want to produce, and what it gets attached to is the Produced object. For the sake of my code, I only support producing instances of java.util.Properties.

Here's what the Producer method looks like (and yell if you don't like my code; note that the real version would be cleaner assuming you had an injectable SLF4J Logger).

   @Produces @ConfiguredBy("")
/**
* Produces a java.util.Properties object based on the qualifier ConfiguredBy
* and the injection point.
*
* Behavior is as follows:
* - the value can be a System property or a path.
* - If it's a system property, we convert it to the value of that property first
*
* - Then we check to see if the value now is an absolute path or a classpath entry
* - We try both.
*/
public Properties produceProperties(InjectionPoint ip) {
Properties p = new Properties();
String value = ip.getAnnotated().getAnnotation(ConfiguredBy.class).value();
System.out.println("Producing properties with value.... "+value);
if(value == null || value.equals("")) {
//if the given file is empty, we can't load it too well.
return p;
}
String propValue = System.getProperty(value);
if(propValue != null) {
value = propValue;
}

File f = new File(value);
if(f.exists() && !f.isDirectory()) {
//so it's on the file system, let's load it.
try{
FileInputStream fis = new FileInputStream(f);
p.load(fis);
} catch (IOException e) {
System.out.println("Problem reading the file, ignoring.");
}
}
//now we try to get it from the classpath, as a resource.
try{
InputStream is = this.getClass().getClassLoader().getResourceAsStream(value);
p.load(is);
} catch (Exception e) {
System.out.println("Problem reading the file, ignoring.");
}
return p;
}
So what this code allows us to do is attempt to load a file based on a System property, and it can exist on the file system or as a resource in the class loader.

Now here's the fun part, how to test this using Arquillian. For those that don't know, Arquillian is a new tool from JBoss designed to help testing software in a container. As of this post, they support Glassfish V3, Weld SE, JBoss AS 5.1 and JBoss AS 6.0. It looks like they also support OpenEJB; but I'm not sure what version. I was able to run my tests on this class using the Weld SE container using JUnit. They also support TestNG; but I've historically always leaned towards JUnit.

Here's an example of a testing class, in this case I use a System property to find the location of a file in the classpath.

First, the maven dependencies.


<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-se</artifactId>
<version>1.0.1-Final</version>
</dependency>

<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-weld-embedded</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-junit</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>


In order to test a system property, I needed to add it explicitly in the surefire plugin in maven:


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<systemPropertyVariables>
<propertyProducerTestSystemProperty.file>META-INF/test1.properties</propertyProducerTestSystemProperty.file>
</systemPropertyVariables>
</configuration>
</plugin>


My test1.properties file, located in src/test/resources/META-INF/, was simply:


key1=value2
key2=value2
key3=something
key4=key4

My test case class was then very simple to write. This is all I had to do to test my producer method, create an injection point!


@RunWith(Arquillian.class)
public class PropertyProducerTestSystemProperty {

@Deployment
public static JavaArchive createDeployment() {
return Archives.create("test.jar", JavaArchive.class)
.addClass(PropertyProducer.class)
.addClass(ConfiguredBy.class)
.addManifestResource("META-INF/test1.properties",
ArchivePaths.create("test1.properties"))
.addManifestResource(
"META-INF/beans.xml",
ArchivePaths.create("beans.xml"));
}

@Inject @ConfiguredBy("propertyProducerTestSystemProperty.file")
Properties properties;

@Test
public void testPropertySize() {
Assert.assertEquals(4,properties.size());
}
@Test
public void testPropertyContains() {
Assert.assertFalse(properties.containsKey("search.url.base"));

}
@Test
public void testPropertyValue() {
Assert.assertEquals("something", properties.getProperty("key3"));
}

}

The createDeployment method, since it's annotated @Deployment signifies the files that will be included in the test - what the container will need to deploy. Note that there's no code in my code that has a direct dependency on how it's tested - switching from Weld SE to Glassfish is simply done in maven. Also note that they have more robush ways of testing in the examples, but it's beyond the scope of this topic.

For each test case, the injection point will get processed and injected; and you can verify that the tests pass.

If you want to give this a try, you can clone the source from my google code site, tadcdicomps and then click on the Source tab. this is the properties project under hg. To run the tests, I have a Test Suite that has multiple test classes in it, the command I ran after building was

mvn test -Dtest=PropertiesTestSuite

Enjoy!

Friday, January 29, 2010

A feature that JSF needs

I've noticed for some time now that there are just some things that are hokey in JSF.

If you're like me, you almost always have your forms setup like this:

<h:outputLabel for="pvalue" value="Value"/>
<h:inputText value="#{propertyAction.propValue}" id="pvalue"/>


Now if there's a validation on this input, you need to mark the label (otherwise users get a really bizarre error message that they won't understand)

<h:outputLabel for="pvalue" value="Value"/>
<h:inputText value="#{propertyAction.propValue}" id="pvalue" label="Value"/>


And if you're using a bundle, it'll look something like this:

<h:outputLabel for="pvalue" value="${msgs['value']}"/>
<h:inputText value="#{propertyAction.propValue}" id="pvalue" label="${msgs['value']}"/>


So why can't JSF be smart enough to realize "Ok, I have an outputLabel for this input type, it has a validation error, let me use that label instead." and make the label attribute optional and can override the outputLabel in this case.