I thought this was interesting and there wasn't a lot of information on this online. It's using the Maven JAXB plugin to generate JAXB classes with the Fluent API. All the regular methods for getting and setting values are available, but there is also an API to chain together setting and creating classes. Thanks to Steve Berman for the Maven config.
Standard API
PersonResponse personList = new PersonResponse();
Person person = new Person();
person.setId(ID);
person.setFirstName(FIRST_NAME);
person.setLastName(LAST_NAME);
Person person2 = new Person();
person2.setId(SECOND_ID);
person2.setFirstName(SECOND_FIRST_NAME);
person2.setLastName(SECOND_LAST_NAME);
personList.getPerson().add(person);
personList.getPerson().add(person2);
Fluent API
PersonResponse personList = new PersonResponse().withPerson(
new Person().withId(ID).withFirstName(FIRST_NAME).withLastName(LAST_NAME),
new Person().withId(SECOND_ID).withFirstName(SECOND_FIRST_NAME).withLastName(SECOND_LAST_NAME));
Inside the build element's plugins section, this can be added to generate JAXB beans with the Fluent API.
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<configuration>
<extension>true</extension>
<args>
<arg>-Xfluent-api</arg>
</args>
<schemaDirectory>src/main/resources</schemaDirectory>
<plugins>
<plugin>
<groupId>net.java.dev.jaxb2-commons</groupId>
<artifactId>jaxb-fluent-api</artifactId>
<version>2.1.8</version>
</plugin>
</plugins>
</configuration>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
<repositories>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Maven 2 Repository</name>
<url>http://download.java.net/maven/2</url>
</repository>
</repositories>
Tuesday, December 9, 2008
Friday, December 5, 2008
Spring by Example Wins
I was going to really try to get back into working on the book, but I think I realistically don't have the time. I did make a small update to Spring In-depth, In Context before SpringOne started, but I was thinking about how Spring 3.0 is coming out soon so I would need to go through everything again. Posting examples on Spring by Example is less effort since each example is more or less standalone and I'm primarily writing up something specifically on the example. Instead of trying to explain the subject completely, which involves a lot more research and effort. Maybe one day I'll try to get back into working on it, but I actually think hands on examples are probably more valuable. At least that what I always like to see. I typically just want to get going on a project and I'll learn all the nuances of the technology as I go. Possibly the preface and intro from the book can become part of the Spring by Example documentation at some point.
Based on this decision I moved the work I had done for the book to Spring by Example.
Based on this decision I moved the work I had done for the book to Spring by Example.
Labels:
bayeux,
gwt,
osgi,
spring by example,
spring dm server
Tuesday, December 2, 2008
SpringOne Americas 2008 Presentation
SpringOne has been really interesting so far. Rossen Stoyanchev gave a really excellent presentation on all the nuances and best practices for using Spring MVC Annotations. I'll need to update all my web examples, because there's at least one thing if not more that could be done more elegantly. Like using the @ModelAttribute on a method to populate the model for a form instead of using a dummy method just for a create (so the form has an instance to bind to).
My presentation on GWT & Dojo Cometd with Spring Bayeux is tomorrow morning. I've put a lot of work into the presentation, writing up what I could for Spring In Depth, In Context, and getting the examples cleaned up as much as possible and checked into Subversion. Hopefully the presentation will go well and everyone will find it interesting.
My presentation on GWT & Dojo Cometd with Spring Bayeux is tomorrow morning. I've put a lot of work into the presentation, writing up what I could for Spring In Depth, In Context, and getting the examples cleaned up as much as possible and checked into Subversion. Hopefully the presentation will go well and everyone will find it interesting.
Spring by Example & 'Spring In-depth, In Context'
I've made updates to both sites. Spring by Example doesn't have anything too major, but the last site release updated the Spring by Example Web Module to version 1.1.1. For Spring In-depth, In Context, I finally had time to get the Chat and Trade Monitor examples I made for my SpringOne presentation posted and written up for Jetty. The examples are checked in except for the Trade Monitor example running an embedded Jetty in Tomcat. This is the same as the Trade Monitor that runs under Jetty, was just to show that you could still use Jetty's Bayeux implementation even if you were on Tomcat.
Also I finally had time to post a simple Spring dm Server example showing side-by-side versioning. It has a version 1.0 and 1.1 of a message service. The version 1.0 uses Commons Lang 2.1.0 and version 1.1 uses Commons Lang 2.4.0. There is a web module that just displays the data and you can switch back and forth between the two different message services at runtime. I'll work on this section more to add screen shots and a more detailed explanation of things, but I wanted to get what was ready posted.
Also I finally had time to post a simple Spring dm Server example showing side-by-side versioning. It has a version 1.0 and 1.1 of a message service. The version 1.0 uses Commons Lang 2.1.0 and version 1.1 uses Commons Lang 2.4.0. There is a web module that just displays the data and you can switch back and forth between the two different message services at runtime. I'll work on this section more to add screen shots and a more detailed explanation of things, but I wanted to get what was ready posted.
Labels:
gwt,
osgi,
spring dm server,
spring in-depth book
Wednesday, November 26, 2008
Maven & No Commons Logging
Maven includes Commons Logging by default, which isn't what you really want if you'd like to use SLF4J for your logging facade. A nice solution to fake out Maven was written at this blog. Basically you have a fake version 99.0 as an empty jar named the same as Commons Logging so it's downloaded instead.
I noticed builds were running really slow and it seems that he Maven repository (http://no-commons-logging.zapto.org/mvn2) has been down for days. As a temporary solution I've put the no Commons Logging jars into the Spring by Example repo and put a mirror entry into my settings.xml.
It would be nice if Maven just had a way to do global excludes if you don't want a jar no matter what transitive dependencies are resolved.
~/.m2/settings.xml
<settings>
<mirrors>
<mirror>
<id>no-commons-logging</id>
<name>No Commons Logging</name>
<url>http://www.springbyexample.org/maven/repo</url>
<mirrorof>no-commons-logging</mirrorof>
</mirror>
</mirrors>
</settings>
I noticed builds were running really slow and it seems that he Maven repository (http://no-commons-logging.zapto.org/mvn2) has been down for days. As a temporary solution I've put the no Commons Logging jars into the Spring by Example repo and put a mirror entry into my settings.xml.
It would be nice if Maven just had a way to do global excludes if you don't want a jar no matter what transitive dependencies are resolved.
~/.m2/settings.xml
<settings>
<mirrors>
<mirror>
<id>no-commons-logging</id>
<name>No Commons Logging</name>
<url>http://www.springbyexample.org/maven/repo</url>
<mirrorof>no-commons-logging</mirrorof>
</mirror>
</mirrors>
</settings>
Wednesday, November 19, 2008
SpringOne Americas 2008
I'm presenting this year at SpringOne Americas 2008. I'm really looking forward to it and have been working on examples and the slides for the conference. That's why I haven't posted much lately. I'll be presenting a Case Study of my investigation of GWT, Comet, and Bayeux integration with Spring for developing a trade monitor. I'll be posting the examples soon and will also write about them, but the slides will just be for those that the attend the conference. It should be a very good conference. I really enjoyed it last year. It's one of the more technical conferences I've been to.
Sunday, October 26, 2008
GWT & Comet Spring Integration
I'm making good progress integrating GWT & Comet with Spring. I just posted an update to the Spring by Example Web Module for a basic Spring GWT Controller and Spring Bayeux configuration for Comet on Jetty. Basically there is a Spring version of the Bayeux implementation and can configure it completely in Spring. Then it can be injected into BayeuxService implementations and there is a servlet that gets Bayeux from Spring instead of creating it. I think I'll possibly have a GWT version of the Dojo Comet Chat example soon.
Wednesday, October 22, 2008
Spring by Example RSS Feed
The Spring by Example main RSS feed has been updated to a new url, which is http://www.springbyexample.org/feed/. Before the feed was generated by the TWiki so it wasn't also including the static examples. Also, sometimes something on the TWiki was accidentally posted before it was ready and then stayed in a bad state on sites like Google Reader. The TWiki RSS feed is still active.
Spring by Example Update
I finally had time to update the example site and add a new module, but I've decided to start posting Spring by Example site specific postings on it's own blog (http://springbyexample.blogspot.com/). I'll use this blog for more about what I've been doing.
The new module is Custom ServletContext Scope Module. It let's you use Spring's custom scope to store beans in the web applications ServletContext. I needed this to refactor some old webapps that were sharing data using a static class and wanted to have them share the data in the ServletContext, but I don't have time to completely refactor them.
I also have a simple OSGi example using the Spring dm Server that I'll post and write up when I have time. Otherwise I've been putting a lot of time into working on GWT, Comet, and Spring integration. I'll eventually post more on this too when I get further along.
The new module is Custom ServletContext Scope Module. It let's you use Spring's custom scope to store beans in the web applications ServletContext. I needed this to refactor some old webapps that were sharing data using a static class and wanted to have them share the data in the ServletContext, but I don't have time to completely refactor them.
I also have a simple OSGi example using the Spring dm Server that I'll post and write up when I have time. Otherwise I've been putting a lot of time into working on GWT, Comet, and Spring integration. I'll eventually post more on this too when I get further along.
Saturday, October 11, 2008
Commons Configuration with Spring Modules
Tuesday, August 12, 2008
Spring by Example Content Update
I've updated all of the examples on Spring by Example by making them static content instead of being served in the TWiki. I think the formatting is improved and I think it will make maintaining things easier. The Spring by Example TWiki is still running and available for user contributions.
This is the first draft converting the content. If you find any errors or problems with any examples, please let me know.
This is the first draft converting the content. If you find any errors or problems with any examples, please let me know.
Monday, August 4, 2008
Spring Web Services Example
I ended up having time to finish up a really basic Spring Web Services example using JAXB for marshalling. It was very simple. Really once you have a project setup you will just have to focus on your XSD and business logic. It's nice having the marshalling/unmarshalling handled for you, but if the XML you're receiving becomes larger and you just need a specific part of it you can create a method that uses @XPathParam annotation in front of method variables to get a few values.
In the current example once everything is setup the client just has to make a call on the WebServiceTemplate passing in the request and receiving the response. Both are JAXB generated beans.
PersonResponse response =
(PersonResponse) wsTemplate.marshalSendAndReceive(request);
In the current example once everything is setup the client just has to make a call on the WebServiceTemplate passing in the request and receiving the response. Both are JAXB generated beans.
PersonResponse response =
(PersonResponse) wsTemplate.marshalSendAndReceive(request);
Saturday, August 2, 2008
Simple GWT Spring Webapp Example
I finally had time to finish up the GWT example I've been working on. I may add a bit more to it in the future (like an autocomplete search widget), but there is a lot there and should be helpful getting people started integrating GWT with Spring.
My general impression of using GWT is positive. It's definitely nice that you can work in Java and all the JavaScript is generated for you. Especially that it should perform well and work in different browers. It's a little tedious keeping everything in sync between the static servlet I use when running GWT in debug mode (avoids integrating Spring and injection into GWT debug) and the Spring controller. Also to have GWT use the main message resource for internationalization, a JavaScript object has to be maintained on the static HTML and JSP page (GWT debug vs. Spring webapp). It also wasn't obvious that if I made a bean to use with the main GWT entry point class that it had to be in the same package or a subpackage.
Also, as a side note, I have the person form working using Spring JS. It isn't too much work once I realized that it was working, but Spring Web Flow was refreshing the page afterword until I added at the end of the 'save' transition a render element specifying to only update the 'content' fragment. Otherwise only the 'onclick' attribute of the save button has to be modified.
<input type="submit" id="save"
name="_eventId_save" value="<fmt:message key="button.save">"
onclick="Spring.remoting.submitForm('save', 'person', {fragments:'content'}); return false;"/>
You currently can't specify a target div for returned fragments. I filed a JIRA (Enhance AjaxEventDecoration in Spring JS to specify a Target Div) to allow a targetId. Ideally it will be a list like fragments so you can specify what fragment goes with what div. I wanted to be able to have menu links refresh the content div without refreshing the entire page. Current funtionally assumes that you would just use AJAX for updates within functional areas. Like, I'm on the person page and want to just update the messages and personForm divs with fragments. So the fragment is expected to be wrapped in the div that is already is on the page and they are automatically matched up and updated. I think it will be a useful feature and hopefully will get added in an upcoming release.
My general impression of using GWT is positive. It's definitely nice that you can work in Java and all the JavaScript is generated for you. Especially that it should perform well and work in different browers. It's a little tedious keeping everything in sync between the static servlet I use when running GWT in debug mode (avoids integrating Spring and injection into GWT debug) and the Spring controller. Also to have GWT use the main message resource for internationalization, a JavaScript object has to be maintained on the static HTML and JSP page (GWT debug vs. Spring webapp). It also wasn't obvious that if I made a bean to use with the main GWT entry point class that it had to be in the same package or a subpackage.
Also, as a side note, I have the person form working using Spring JS. It isn't too much work once I realized that it was working, but Spring Web Flow was refreshing the page afterword until I added at the end of the 'save' transition a render element specifying to only update the 'content' fragment. Otherwise only the 'onclick' attribute of the save button has to be modified.
<input type="submit" id="save"
name="_eventId_save" value="<fmt:message key="button.save">"
onclick="Spring.remoting.submitForm('save', 'person', {fragments:'content'}); return false;"/>
You currently can't specify a target div for returned fragments. I filed a JIRA (Enhance AjaxEventDecoration in Spring JS to specify a Target Div) to allow a targetId. Ideally it will be a list like fragments so you can specify what fragment goes with what div. I wanted to be able to have menu links refresh the content div without refreshing the entire page. Current funtionally assumes that you would just use AJAX for updates within functional areas. Like, I'm on the person page and want to just update the messages and personForm divs with fragments. So the fragment is expected to be wrapped in the div that is already is on the page and they are automatically matched up and updated. I think it will be a useful feature and hopefully will get added in an upcoming release.
Labels:
gwt,
spring by example,
spring framework,
spring mvc,
tiles
Sunday, July 27, 2008
Spring by Example JDBC, Spring Dynamic Tiles Module, and Google Web Toolkit
I almost have everything ready to post a simple Google Web Toolkit (GWT) example with Spring. I have everything checked in and I also had to update Spring by Example JDBC and Spring by Example Dynamic Tiles Module.
Spring by Example JDBC version 1.0.3 was upgraded to match changes in Spring 2.5.5 and HsqldbInitializingDriverManagerDataSource & InitializingDriverManagerDataSource were changed to use SimpleDriverDataSource (which was added in Spring 2.5.5).
Spring by Example Dynamic Tiles Module 1.1 has a number of changes. The project was updated to use Spring 2.5.5, AJAX support like Spring JS and Spring Web Flow is provided, and a few other items (see release notes in the projects README.txt). Also, Spring by Example Dynamic Tiles Module 1.0 was compiled with Java 6, but should have been compiled with Java 5. The projects are basically all ready, but just need a little more testing. Although everything is checked into Subversion.
I'll try to get everything finalized and checked in over the next couple of days. I think the AJAX support that works with Spring JS' Spring.remoting.submitForm is great. It's really nice to have simple and easy control over updating specific div sections that match parts of a Tiles template.
Spring by Example JDBC version 1.0.3 was upgraded to match changes in Spring 2.5.5 and HsqldbInitializingDriverManagerDataSource & InitializingDriverManagerDataSource were changed to use SimpleDriverDataSource (which was added in Spring 2.5.5).
Spring by Example Dynamic Tiles Module 1.1 has a number of changes. The project was updated to use Spring 2.5.5, AJAX support like Spring JS and Spring Web Flow is provided, and a few other items (see release notes in the projects README.txt). Also, Spring by Example Dynamic Tiles Module 1.0 was compiled with Java 6, but should have been compiled with Java 5. The projects are basically all ready, but just need a little more testing. Although everything is checked into Subversion.
I'll try to get everything finalized and checked in over the next couple of days. I think the AJAX support that works with Spring JS' Spring.remoting.submitForm is great. It's really nice to have simple and easy control over updating specific div sections that match parts of a Tiles template.
Labels:
gwt,
spring by example,
spring framework,
spring mvc,
tiles
Thursday, July 10, 2008
Spring JPA Example with Hibernate
This took longer than I expected since I was able to reuse the Entity beans from the Hibernate annotation example. I had a lot of trouble getting the right jars to work together. Hopefully the Maven config in the project will help someone else.
The key things besides the classpath to get setup in the example were just the Spring Config and putting the JPA configuration in META-INF/persistence.xml. Also the LocalContainerEntityManagerFactoryBean actually returns a javax.persistence.EntityManagerFactory. I assumed it returned an EntityManger based on the name of the class.
One other point is that JpaDaoSupport has setEntityManger and setEntityManagerFactory as final. So you can't override them, use @Autowired, then super the value to the parent method. I ended up passing in the EntityManagerFactory in the constructor using @Autowired. Which is probably better since it's required, but I'm used to typically using setters in Spring.
Note: This example has the DAO class extend JpaDaoSupport and uses the JpaTemplate, but Spring recommends the native JPA style of coding.
"JpaTemplate mainly exists as a sibling of JdoTemplate and HibernateTemplate, offering the same style for people used to it. or newly started projects, consider adopting the native JPA style of coding data access objects instead, based on a "shared EntityManager" reference obtained through the JPA @PersistenceContext annotation." (from Spring 2.5.x JPA documentation)
The key things besides the classpath to get setup in the example were just the Spring Config and putting the JPA configuration in META-INF/persistence.xml. Also the LocalContainerEntityManagerFactoryBean actually returns a javax.persistence.EntityManagerFactory. I assumed it returned an EntityManger based on the name of the class.
One other point is that JpaDaoSupport has setEntityManger and setEntityManagerFactory as final. So you can't override them, use @Autowired, then super the value to the parent method. I ended up passing in the EntityManagerFactory in the constructor using @Autowired. Which is probably better since it's required, but I'm used to typically using setters in Spring.
Note: This example has the DAO class extend JpaDaoSupport and uses the JpaTemplate, but Spring recommends the native JPA style of coding.
"JpaTemplate mainly exists as a sibling of JdoTemplate and HibernateTemplate, offering the same style for people used to it. or newly started projects, consider adopting the native JPA style of coding data access objects instead, based on a "shared EntityManager" reference obtained through the JPA @PersistenceContext annotation." (from Spring 2.5.x JPA documentation)
Labels:
hibernate,
spring by example,
spring framework
Spring Config with Zero XML
So, if you really don't want to use any XML to configure Spring and you also don't want to use the Spring JavaConfig project (create beans using Java code), you can actually use annotation-based config. I found this looking at the context:component-scan unit tests. You just create a GenericApplicationContext and a ClassPathBeanDefinitionScanner. Then call refresh on the context load the bans and register a shutdown hook so you get destruction callbacks on your beans when the JVM is shutdown. The ClassPathBeanDefinitionScanner registers the @Autowired and @Required bean post processors. It also registers the JSR-250 Commons Annotations and the PersistenceAnnotationBeanPostProcessor for JPA if their jars are in the classpath. It's pretty straightforward.
Also it could be a good way to unit test how many beans are being pick up by the context:component-scan in case you're worried you configured the packages it's scanning incorrectly.
A downside to this is that if you are using the Spring IDE in Eclipse, you won't be able to register an XML file with it. The latest version handles XML configured beans and ones that are scanned so you can get consolidated bean graphs and all the other help it provides. I personally wouldn't do this and it's worth having a very, very small XML file just to define context:component-scan directly.
String basePackage = this.getClass().getPackage().getName();
GenericApplicationContext ctx = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(ctx);
int beanCount = scanner.scan(basePackage);
ctx.refresh();
ctx.registerShutdownHook();
Also it could be a good way to unit test how many beans are being pick up by the context:component-scan in case you're worried you configured the packages it's scanning incorrectly.
A downside to this is that if you are using the Spring IDE in Eclipse, you won't be able to register an XML file with it. The latest version handles XML configured beans and ones that are scanned so you can get consolidated bean graphs and all the other help it provides. I personally wouldn't do this and it's worth having a very, very small XML file just to define context:component-scan directly.
String basePackage = this.getClass().getPackage().getName();
GenericApplicationContext ctx = new GenericApplicationContext();
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner
int beanCount = scanner.scan(basePackage);
ctx.refresh();
ctx.registerShutdownHook();
Monday, July 7, 2008
Spring In-depth, In Context
I've been working for a while on a book for Spring 2.5. I've decided to post it for free online and hopefully it will be useful to people. It currently has a very good introduction to Spring, basic bean creation using XML and Annotations. Although the Annotations chapter isn't 100% complete. There are also partially complete chapters on resources & ApplicationContexts and AOP.
As updates are available, I'll continue to post them. I decided since there was a lot of information and examples done, it was better to release it now and continue to work on it when I have free time. I hope it helps people. It was a lot of work getting even this much done. There are so many nuances to Spring's configuration options between XML and Annotation-based configuration.
Also, a very special thanks to Susan Kerschbaumer who has co-authored the book with me and has personally done a really excellent job with what she has done so far. Currently Susan has only had time to work on the Preface, Chapter 1, and Chapter 2. But as she has time she will focus on other chapters.
Spring In-depth, In Context
As updates are available, I'll continue to post them. I decided since there was a lot of information and examples done, it was better to release it now and continue to work on it when I have free time. I hope it helps people. It was a lot of work getting even this much done. There are so many nuances to Spring's configuration options between XML and Annotation-based configuration.
Also, a very special thanks to Susan Kerschbaumer who has co-authored the book with me and has personally done a really excellent job with what she has done so far. Currently Susan has only had time to work on the Preface, Chapter 1, and Chapter 2. But as she has time she will focus on other chapters.
Spring In-depth, In Context
- Preface
- Chapter 1: Spring In Context: Core Concepts
- Chapter 2: A Practical Introduction to Inversion of Control
- Chapter 3: In-depth Inversion of Control (IoC) [Draft]
- Chapter 4: Annotation-based Bean Configuration [Draft]
- Chapter 5: Bean & Resource Loading [Draft]
- Chapter 6 :AOP [Draft]
Tuesday, June 24, 2008
Spring Web Flow 2.0 Subflows
I have a simple subflow working with Spring Web Flow 2.0. It also has success messages and validation controlled by the flow. The example builds on Simple Spring Web Flow Webapp by adding an address subflow to the person flow along with displaying a message resource after a successful save. Validation for the flow and subflow are handled automatically by Spring Web Flow. The person flow uses a bean, personValidator, named to match the flow. The address flow has a method, 'validateAddressForm(MessageContext context)', in the Address class that matches the id of the view-state it should be called for
The subflow was a little bit of work. It's pretty straightfoward, but I wasn't used to reading the error messages from Web Flow showing all the scope variables. Also, I couldn't find a specific example doing a subflow for Spring Web Flow 2.0. Basically the input needs to be configured in the subflow-state and then again at the beginning of the subflow, and the output needs to be configured the same way.
Excerpt from Person Flow
<subflow-state id="address" subflow="address">
<input name="id" value="addressId"/>
<input name="person" value="person"/>
<output name="address" />
<transition on="saveAddress" to="personForm">
<evaluate expression="personDao.saveAddress(id, address)" result="flowScope.person" />
<set name="flashScope.statusMessageKey" value="'address.form.msg.success'" />
</transition>
<transition on="cancelAddress" to="personForm" />
</subflow-state>
Excerpt from Address Subflow
<input name="id" />
<input name="person" />
...
<end-state id="saveAddress">
<output name="address" value="address"/>
</end-state>
The subflow was a little bit of work. It's pretty straightfoward, but I wasn't used to reading the error messages from Web Flow showing all the scope variables. Also, I couldn't find a specific example doing a subflow for Spring Web Flow 2.0. Basically the input needs to be configured in the subflow-state and then again at the beginning of the subflow, and the output needs to be configured the same way.
Excerpt from Person Flow
<subflow-state id="address" subflow="address">
<input name="id" value="addressId"/>
<input name="person" value="person"/>
<output name="address" />
<transition on="saveAddress" to="personForm">
<evaluate expression="personDao.saveAddress(id, address)" result="flowScope.person" />
<set name="flashScope.statusMessageKey" value="'address.form.msg.success'" />
</transition>
<transition on="cancelAddress" to="personForm" />
</subflow-state>
Excerpt from Address Subflow
<input name="id" />
<input name="person" />
...
<end-state id="saveAddress">
<output name="address" value="address"/>
</end-state>
Labels:
spring by example,
spring framework,
spring web flow
Thursday, June 19, 2008
Spring Web Flow Request Exception
In the previous post on Spring Web Flow 2.0, I mentioned that I was getting a 'Could not complete request' error as an IllegalStateException at the end of the flow. I found the issue. It was because the URL in the flow handler wasn't a context relative one. I was returning 'person/search', but that was just being added to the end of the current URL. The correct value to return is 'contextRelative:/person/search.html' (the servlet-mapping for the DispatcherServlet is '*.html'). With this working, I was able to remove the view attribute from the end-state elements in the flow. See the Simple Spring Web Flow Webapp example for more information.
@Component
public class PersonFlowHandler extends AbstractFlowHandler {
/**
* Where the flow should go when it ends.
*/
@Override
public String handleExecutionOutcome(FlowExecutionOutcome outcome,
HttpServletRequest request,
HttpServletResponse response) {
return getContextRelativeUrl(PersonController.SEARCH_VIEW_KEY);
}
/**
* Where to redirect if there is an exception not handled by the flow.
*/
@Override
public String handleException(FlowException e,
HttpServletRequest request,
HttpServletResponse response) {
if (e instanceof NoSuchFlowExecutionException) {
return getContextRelativeUrl(PersonController.SEARCH_VIEW_KEY);
} else {
throw e;
}
}
/**
* Gets context relative url with an '.html' extension.
*/
private String getContextRelativeUrl(String view) {
return "contextRelative:" + view + ".html";
}
}
@Component
public class PersonFlowHandler extends AbstractFlowHandler {
/**
* Where the flow should go when it ends.
*/
@Override
public String handleExecutionOutcome(FlowExecutionOutcome outcome,
HttpServletRequest request,
HttpServletResponse response) {
return getContextRelativeUrl(PersonController.SEARCH_VIEW_KEY);
}
/**
* Where to redirect if there is an exception not handled by the flow.
*/
@Override
public String handleException(FlowException e,
HttpServletRequest request,
HttpServletResponse response) {
if (e instanceof NoSuchFlowExecutionException) {
return getContextRelativeUrl(PersonController.SEARCH_VIEW_KEY);
} else {
throw e;
}
}
/**
* Gets context relative url with an '.html' extension.
*/
private String getContextRelativeUrl(String view) {
return "contextRelative:" + view + ".html";
}
}
Tuesday, June 17, 2008
Simple Spring Web Flow 2.0 Example Ready
I finally have a very Simple Spring Web Flow 2.0 example ready. It's building on the Spring MVC annotation-based Controller and Spring Security 2.0 examples I did recently. I'm actually still working on a more advanced example showing how to have a subflow for Person addresses, but I wanted to post what was working so far and it might be less confusing to people as they're getting started since there is less going on.
There is an error currently when leaving the flow from a save and a cancel. It says 'Could not complete request' and is an IllegalStateException. It seems to be some problem with a redirect, but everything works fine.
The more advanced subflow example just needs to have messages and validation added to it., and I might try to switch it from using a Hibernate DAO class to using Spring Web Flow's built in JPA persistence hooks. It really took a long time to get the subflow working. I had to try a lot of different things to get the address id passed into the subflow. Spring Web Flow is really nice, but there could be a lot more documentation and examples illustrating things like this. I couldn't find any concrete examples doing this for Spring Web Flow 2.0.
The person flow uses Spring Security to limit the flow to a 'ROLE_USER'. Based on whether or not an id attribute is available, the decision-state element will forward to a 'createPerson' or 'editPerson' action-state. The 'createPerson' one uses El to create a new Person instance for the form to bind to using a method on the person controller. The edit uses the person DAO instance to look up the person record. They both forward to the 'personForm' where you can save or cancel, and save uses the person DAO to save the person instance. The person instance is automatically bound by specifying the model attribute as 'person' on the view-state. Both cancel and save then populate the latest search results and forward to the search page.
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<secured attributes="ROLE_USER" />
<input name="id" />
<decision-state id="createOrEdit">
<if test="id == null" then="createPerson" else="editPerson" />
</decision-state>
<action-state id="createPerson">
<evaluate expression="personController.newPerson()"
result="flowScope.person" />
<transition to="personForm" />
</action-state>
<action-state id="editPerson">
<evaluate expression="personDao.findPersonById(id)"
result="flowScope.person" />
<transition to="personForm" />
</action-state>
<view-state id="personForm" model="person" view="/person/form">
<transition on="save" to="savePerson">
<evaluate expression="personDao.save(person)" />
<evaluate expression="personDao.findPersons()"
result="flowScope.persons" />
</transition>
<transition on="cancel" to="cancelPerson" bind="false">
<evaluate expression="personDao.findPersons()"
result="flowScope.persons" />
</transition>
</view-state>
<end-state id="savePerson" view="/person/search" />
<end-state id="cancelPerson" view="/person/search" />
</flow>
There is an error currently when leaving the flow from a save and a cancel. It says 'Could not complete request' and is an IllegalStateException. It seems to be some problem with a redirect, but everything works fine.
The more advanced subflow example just needs to have messages and validation added to it., and I might try to switch it from using a Hibernate DAO class to using Spring Web Flow's built in JPA persistence hooks. It really took a long time to get the subflow working. I had to try a lot of different things to get the address id passed into the subflow. Spring Web Flow is really nice, but there could be a lot more documentation and examples illustrating things like this. I couldn't find any concrete examples doing this for Spring Web Flow 2.0.
The person flow uses Spring Security to limit the flow to a 'ROLE_USER'. Based on whether or not an id attribute is available, the decision-state element will forward to a 'createPerson' or 'editPerson' action-state. The 'createPerson' one uses El to create a new Person instance for the form to bind to using a method on the person controller. The edit uses the person DAO instance to look up the person record. They both forward to the 'personForm' where you can save or cancel, and save uses the person DAO to save the person instance. The person instance is automatically bound by specifying the model attribute as 'person' on the view-state. Both cancel and save then populate the latest search results and forward to the search page.
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<secured attributes="ROLE_USER" />
<input name="id" />
<decision-state id="createOrEdit">
<if test="id == null" then="createPerson" else="editPerson" />
</decision-state>
<action-state id="createPerson">
<evaluate expression="personController.newPerson()"
result="flowScope.person" />
<transition to="personForm" />
</action-state>
<action-state id="editPerson">
<evaluate expression="personDao.findPersonById(id)"
result="flowScope.person" />
<transition to="personForm" />
</action-state>
<view-state id="personForm" model="person" view="/person/form">
<transition on="save" to="savePerson">
<evaluate expression="personDao.save(person)" />
<evaluate expression="personDao.findPersons()"
result="flowScope.persons" />
</transition>
<transition on="cancel" to="cancelPerson" bind="false">
<evaluate expression="personDao.findPersons()"
result="flowScope.persons" />
</transition>
</view-state>
<end-state id="savePerson" view="/person/search" />
<end-state id="cancelPerson" view="/person/search" />
</flow>
Labels:
spring by example,
spring framework,
spring web flow
Monday, June 9, 2008
Using Spring Security to Secure a Webapp
I had to go to a few different places to get all this working, but I have simple security on a webapp that secures the URLs and a method on a DAO interface. Besides securing the delete method in the DAO interface, the link is also hidden from non-admin users. I have this working with JDBC authentication and also with static users defined in the XML (which are commented out, but still in the XML configuration).
Basically you just need to define a security filter, configure Spring Security in an XML file, secure methods either with pointcuts in the XML or with annotations.
Secure DAO Method
Either secure with an annotation-based config, as in the example posted.
<security:global-method-security secured-annotations="enabled" />
/**
* Deletes person.
*/
@Secured ({"ROLE_ADMIN"})
public void delete(Person person);
Or as a pointcut in the XML configuration.
<security:global-method-security>
<!-- Any delete method in a class ending in 'Dao' in the 'org.springbyexample.orm.hibernate3.annotation.dao' package. -->
<security:protect-pointcut
expression="execution(* org.springbyexample.orm.hibernate3.annotation.dao.*Dao.delete(..))"
access="ROLE_ADMIN"/>
</security:global-method-security>
In Spring Security Config
<security:authentication-provider>
<security:jdbc-user-service data-source-ref="dataSource" />
</security:authentication-provider>
SQL Script
Script works for HSQLDB and based on Spring Security Script. The ACL tables aren't defined because they aren't used at all in this example.
SET IGNORECASE TRUE;
CREATE TABLE users (
username VARCHAR(50) NOT NULL PRIMARY KEY,
password VARCHAR(50) NOT NULL,
enabled BIT NOT NULL
);
CREATE TABLE authorities (
username VARCHAR(50) NOT NULL,
authority VARCHAR(50) NOT NULL
);
CREATE UNIQUE INDEX ix_auth_username ON authorities (username, authority);
ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users foreign key (username) REFERENCES users(username);
INSERT INTO users VALUES ('david', 'newyork', true);
INSERT INTO users VALUES ('alex', 'newjersey', true);
INSERT INTO users VALUES ('tim', 'illinois', true);
INSERT INTO authorities VALUES ('david', 'ROLE_USER');
INSERT INTO authorities VALUES ('david', 'ROLE_ADMIN');
INSERT INTO authorities VALUES ('alex', 'ROLE_USER');
INSERT INTO authorities VALUES ('tim', 'ROLE_USER');
Basically you just need to define a security filter, configure Spring Security in an XML file, secure methods either with pointcuts in the XML or with annotations.
Secure DAO Method
Either secure with an annotation-based config, as in the example posted.
<security:global-method-security secured-annotations="enabled" />
/**
* Deletes person.
*/
@Secured ({"ROLE_ADMIN"})
public void delete(Person person);
Or as a pointcut in the XML configuration.
<security:global-method-security>
<!-- Any delete method in a class ending in 'Dao' in the 'org.springbyexample.orm.hibernate3.annotation.dao' package. -->
<security:protect-pointcut
expression="execution(* org.springbyexample.orm.hibernate3.annotation.dao.*Dao.delete(..))"
access="ROLE_ADMIN"/>
</security:global-method-security>
In Spring Security Config
<security:authentication-provider>
<security:jdbc-user-service data-source-ref="dataSource" />
</security:authentication-provider>
SQL Script
Script works for HSQLDB and based on Spring Security Script. The ACL tables aren't defined because they aren't used at all in this example.
SET IGNORECASE TRUE;
CREATE TABLE users (
username VARCHAR(50) NOT NULL PRIMARY KEY,
password VARCHAR(50) NOT NULL,
enabled BIT NOT NULL
);
CREATE TABLE authorities (
username VARCHAR(50) NOT NULL,
authority VARCHAR(50) NOT NULL
);
CREATE UNIQUE INDEX ix_auth_username ON authorities (username, authority);
ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users foreign key (username) REFERENCES users(username);
INSERT INTO users VALUES ('david', 'newyork', true);
INSERT INTO users VALUES ('alex', 'newjersey', true);
INSERT INTO users VALUES ('tim', 'illinois', true);
INSERT INTO authorities VALUES ('david', 'ROLE_USER');
INSERT INTO authorities VALUES ('david', 'ROLE_ADMIN');
INSERT INTO authorities VALUES ('alex', 'ROLE_USER');
INSERT INTO authorities VALUES ('tim', 'ROLE_USER');
Labels:
spring by example,
spring framework,
spring security
Sunday, June 8, 2008
Unit Testing AspectJ Load-time Weaving with Maven
This came up as a question on the Spring forums and I actually spent a bit of time trying to figure out how to get the unit test working properly when I did this originally. To unit test AspectJ Load-time Weaving (LTW), the surefire plugin needs to be configured to take the LTW agent. Which in this example is the Spring Agent. Also, the test needs to be run in it's own JVM so the javaagent argument can be applied.
The dependency on spring-agent can have it's scope set to 'provided'. It isn't needed as part of the build since it's used as a command line argument and Maven still downloads the jar so it can be referenced for the test in the local Maven repository.
Note: The argLine element should all be together on one line, but was separated to display in the blog entry.
<properties>
<spring.version>2.5.4</spring.version>
</properties>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-agent</artifactId>
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4</version>
<configuration>
<forkMode>once</forkMode>
<argLine>
-javaagent:${settings.localRepository}
/org/springframework/spring-agent/${spring.version}/
spring-agent-${spring.version}.jar
</argLine>
<useSystemClassloader>true</useSystemClassloader>
</configuration>
</plugin>
Labels:
aop,
aspectj,
ltw,
maven,
spring by example,
spring framework
Friday, June 6, 2008
Maven Internationalized Compilation Issue
I've never had this come up before, but as I was working on a security that was using the internationalization (i18n) from the Basic Webapp Internationalization I decided to add actually inserting a UTF-8 Korean name into the database. This ended up revealing a bug in the
Spring by Example JDBC Module. It wasn't correctly setting the encoding type when reading in a script file. This was easy enough to fix and I made a 1.0.2 release with that and a few other changes including better unit testing for UTF-8 scripts.
I had everything working in Eclipse, but I couldn't successfully run the tests from the command line. I spent quite a while on this and finally realized it was the actual compilation step that was causing a problem. It took a long time because debugging in Eclipse, everything was fine.
The solution to the problem was to explicitly add the character encoding type to the Maven compiler plugin. Eclipse was automatically correctly setting the encoding. After doing the internationalization examples, it seems like everything is still stuck the way it was 7-10 years ago for the most part. You would think that everything should default to the way Java stores a java.lang.String (UTF-16).
<plugin>
<artifactid>maven-compiler-plugin</artifactid>
<configuration>
<source>1.5</source>
<target>1.5</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
Spring by Example JDBC Module. It wasn't correctly setting the encoding type when reading in a script file. This was easy enough to fix and I made a 1.0.2 release with that and a few other changes including better unit testing for UTF-8 scripts.
I had everything working in Eclipse, but I couldn't successfully run the tests from the command line. I spent quite a while on this and finally realized it was the actual compilation step that was causing a problem. It took a long time because debugging in Eclipse, everything was fine.
The solution to the problem was to explicitly add the character encoding type to the Maven compiler plugin. Eclipse was automatically correctly setting the encoding. After doing the internationalization examples, it seems like everything is still stuck the way it was 7-10 years ago for the most part. You would think that everything should default to the way Java stores a java.lang.String (UTF-16).
<plugin>
<artifactid>maven-compiler-plugin</artifactid>
<configuration>
<source>1.5</source>
<target>1.5</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
Saturday, May 24, 2008
Simple Form using Spring MVC Annotations
I just posted a new example using Spring 2.5's new MVC annotations. The new annotations seem pretty nice. I'm not always for tightly coupling configuration with annotations, but in this case most controllers normally have a single purpose. Plus, you still have the XML configuration as an option if a looser coupling between controller and mappings is needed.
The webapp has basic create, update, delete, and search functionality for a person form. The form basically just has a hidden id (primary key), first name, and last name fields. The example uses Spring MVC annotations, Tiles 2 with Spring By Example's Dynamic Tiles Spring MVC Module, Hibernate configured with annotations and used in Spring with a Hibernate template, and internationalized messages. So a requested URL will go through a controller if there is a mapping, data may be put in place for the page to render, message resources are also put into scope for the page to render, and finally the Dynamic Tiles view renderer takes the request URL and uses it as the body of a default Tiles template. The example is released under the Apache 2.0 license.
The @RequestMapping annotation is used to indicate what requests a method should handle and can handle Ant style patterns to match a request (not shown below). The @RequestParam annotation can be used to have a request parameter automatically mapped to a variable in the method signature. Or a class can be specified, like in the save method, and any values from the request that can be bound to an instance of the class will be and that instance will be passed into the method.
The create method shows that an Object returned will automatically put into the model based on the classes' name (Person.class --> 'person').
Excerpt from Controller
The webapp has basic create, update, delete, and search functionality for a person form. The form basically just has a hidden id (primary key), first name, and last name fields. The example uses Spring MVC annotations, Tiles 2 with Spring By Example's Dynamic Tiles Spring MVC Module, Hibernate configured with annotations and used in Spring with a Hibernate template, and internationalized messages. So a requested URL will go through a controller if there is a mapping, data may be put in place for the page to render, message resources are also put into scope for the page to render, and finally the Dynamic Tiles view renderer takes the request URL and uses it as the body of a default Tiles template. The example is released under the Apache 2.0 license.
The @RequestMapping annotation is used to indicate what requests a method should handle and can handle Ant style patterns to match a request (not shown below). The @RequestParam annotation can be used to have a request parameter automatically mapped to a variable in the method signature. Or a class can be specified, like in the save method, and any values from the request that can be bound to an instance of the class will be and that instance will be passed into the method.
The create method shows that an Object returned will automatically put into the model based on the classes' name (Person.class --> 'person').
Excerpt from Controller
@Controller
public class PersonController {
final Logger logger = LoggerFactory.getLogger(PersonController.class);
private static final String FORM_VIEW_KEY = "/form/person";
private static final String SEARCH_VIEW_KEY = "/search/person";
private static final String FORM_MODEL_KEY = "person";
private static final String SEARCH_MODEL_KEY = "persons";
/**
* Creates a person object and forwards to person form.
*/
@RequestMapping(value="/form/person.html")
public Person create() {
return new Person();
}
/**
* Gets a person based on it's id.
*/
@RequestMapping(value="/info/person.html")
public ModelAndView info(@RequestParam("id") Integer id) {
Person result = personDao.findPersonById(id);
return new ModelAndView(FORM_VIEW_KEY,
FORM_MODEL_KEY,
result);
}
/**
* Saves a person.
*/
@RequestMapping(value="/save/person.html")
public ModelAndView save(Person person) {
personDao.save(person);
return new ModelAndView(FORM_VIEW_KEY,
FORM_MODEL_KEY,
person);
}
...
/**
* Searches for all persons and returns them in a
*Collection
as 'persons' in the
*ModelMap
.
*/
@RequestMapping(value="/search/person.html")
public ModelMap search() {
Collection<Person> lResults = personDao.findPersons();
return new ModelMap(SEARCH_MODEL_KEY, lResults);
}
}
Labels:
spring by example,
spring framework,
spring mvc
JavaOne 2008
JavaOne was interesting this year. It was non-stop from morning until late at night between presentations, meeting people, and parties in the evening. I wish more of the presentations were more technical, but many were to convey new technologies, JSRs, etc. and didn't have time to delve in-depth. Although, spec leads don't always make the best lecturers even though they know the subject well. Two very good speakers were Brian Goetz and Joshua Bloch.
Brian Goetz's presentation of possible new concurrency features in Java 7 was very interesting. A key feature is to allow a large task that can keep being forked to build a work queue and let the VM manage threading and delegating the task to available CPUs. From what he said, this will apparently scale much better than the way things are handled currently on large multi-core systems, which will become more and more prevalent. Built on top of this forking will be ParallelArrays which will allow much better concurrent processing of large arrays by delegating tasks like getting the max value, sums, filtering, etc. to multiple core processors and then processing the results coming back from all the cores.
Joshua Bloch has an update to his Effective Java book adding around 20 more examples. Apparently his example of creating the classic singleton with a private constructor that returns an instance through a method is hackable in some way (he didn't go over the code) and he said the best way to create a singleton is to use an Enum since then the VM will enforce the singleton paradigm for you. Otherwise he covered some interesting tips on more effectively using enums instead of using complicated two dimensional arrays to contain the data. He signed autographs of the new book at the book store a number of times and I believe his book was the top seller at the book store.
Getting to see new technologies was probably the highlight of JavaOne for me. Sentilla has a new wireless sensor device that uses Java ME. They had them setup at the conference to record temperature, CO2 levels, and used an IR sensor to track people coming in and out of conference rooms. I got a dev kit to play with, but I still need to order some sensors for it (comes with a built in accelerometer). The new Java Speech API presentation was really interesting. It looks very easy to use for speech recognition and synthesis. The spec lead from Conversay did a great demo of their implementation for mobile devices. In a completely normal voice he was able to create a reminder. They've apparently worked on this for 3 years and this implementation in just 256K of memory (main engine not in Java). I was also able to attend the JSR-303 Bean Validation presentation. It's nice to finally see that there will be a validation implementation in the Java language for people to leverage. Validation is very often overlooked by developers even thought it's very important, but hopefully this will help make validation much more accesible to the average developer. In the final keynote address with James Gosling, there were a number of interesting things. There was a Java powered car with quite a number of sensors on it. The JMars project uses Java to help correlate all the data we've been receiving from Mars to make it easier to review. It was pretty cool that they showed a satellite image and were able to bring up a rover view of the same spot. Also an arrow pointed between the two images to indicate the rock you saw from orbit was the same one the rover was looking at. Someone from CERN labs was there and apparently almost everything they have is Java powered. Lot's of Swing GUIs and probably one of the cooler things was seeing Java 3D show the result of a collision and all the subatomic particles generated.
It's really amazing what Java is being used for and how much better the performance is compared to 10 years ago. It's also amazing how far Open Source projects have come and their wide acceptance in corporate culture. SpringSource, the developers of the Spring Framework, have become a very large company based their framework. I saw people from SpringSource every night I was out. Oddly there were only 3 Spring presentations at JavaOne (two of new features in Spring 2.5 by Rod Johnson and a Spring Security presentation by Ben Alex). I say oddly because according to SpringSource, Spring has surpassed EJBs as the primary skillset requested on job boards from developers. I felt Sun focused a little too much on it's technologies. It is supposed to be JavaOne, not SunOne. There's nothing wrong with an Open Source project surpassing something in Java EE. In fact I think that this is what gives Java an edge over .NET. Without all the great open source initiatives, it would be a much more level playing field between the two.
I'm glad I was able to attend and hopefully I will be able to attend again next year. I had time to see Tim O'Brien, author of the Jakarta Commons Cookbook (among others), and current Maven Sage. I also met Emmanuel Bernard, the specification lead for JSR-303, briefly after his presentation. I was able to talk to a few people from SpringSource that I met at The Spring Experience too. I highly recommend going to The Spring Experience if you're using Spring or want to. It looks like Java will be more and more places that you might not expect it over the next year. Hopefully it will be another good year for Java and the language and Open Source projects will continue to evolve to fulfill everyone's needs. I'm happy that I still enjoy programming in it and also to be getting back involved in Open Source.
Brian Goetz's presentation of possible new concurrency features in Java 7 was very interesting. A key feature is to allow a large task that can keep being forked to build a work queue and let the VM manage threading and delegating the task to available CPUs. From what he said, this will apparently scale much better than the way things are handled currently on large multi-core systems, which will become more and more prevalent. Built on top of this forking will be ParallelArrays which will allow much better concurrent processing of large arrays by delegating tasks like getting the max value, sums, filtering, etc. to multiple core processors and then processing the results coming back from all the cores.
Joshua Bloch has an update to his Effective Java book adding around 20 more examples. Apparently his example of creating the classic singleton with a private constructor that returns an instance through a method is hackable in some way (he didn't go over the code) and he said the best way to create a singleton is to use an Enum since then the VM will enforce the singleton paradigm for you. Otherwise he covered some interesting tips on more effectively using enums instead of using complicated two dimensional arrays to contain the data. He signed autographs of the new book at the book store a number of times and I believe his book was the top seller at the book store.
Getting to see new technologies was probably the highlight of JavaOne for me. Sentilla has a new wireless sensor device that uses Java ME. They had them setup at the conference to record temperature, CO2 levels, and used an IR sensor to track people coming in and out of conference rooms. I got a dev kit to play with, but I still need to order some sensors for it (comes with a built in accelerometer). The new Java Speech API presentation was really interesting. It looks very easy to use for speech recognition and synthesis. The spec lead from Conversay did a great demo of their implementation for mobile devices. In a completely normal voice he was able to create a reminder. They've apparently worked on this for 3 years and this implementation in just 256K of memory (main engine not in Java). I was also able to attend the JSR-303 Bean Validation presentation. It's nice to finally see that there will be a validation implementation in the Java language for people to leverage. Validation is very often overlooked by developers even thought it's very important, but hopefully this will help make validation much more accesible to the average developer. In the final keynote address with James Gosling, there were a number of interesting things. There was a Java powered car with quite a number of sensors on it. The JMars project uses Java to help correlate all the data we've been receiving from Mars to make it easier to review. It was pretty cool that they showed a satellite image and were able to bring up a rover view of the same spot. Also an arrow pointed between the two images to indicate the rock you saw from orbit was the same one the rover was looking at. Someone from CERN labs was there and apparently almost everything they have is Java powered. Lot's of Swing GUIs and probably one of the cooler things was seeing Java 3D show the result of a collision and all the subatomic particles generated.
It's really amazing what Java is being used for and how much better the performance is compared to 10 years ago. It's also amazing how far Open Source projects have come and their wide acceptance in corporate culture. SpringSource, the developers of the Spring Framework, have become a very large company based their framework. I saw people from SpringSource every night I was out. Oddly there were only 3 Spring presentations at JavaOne (two of new features in Spring 2.5 by Rod Johnson and a Spring Security presentation by Ben Alex). I say oddly because according to SpringSource, Spring has surpassed EJBs as the primary skillset requested on job boards from developers. I felt Sun focused a little too much on it's technologies. It is supposed to be JavaOne, not SunOne. There's nothing wrong with an Open Source project surpassing something in Java EE. In fact I think that this is what gives Java an edge over .NET. Without all the great open source initiatives, it would be a much more level playing field between the two.
I'm glad I was able to attend and hopefully I will be able to attend again next year. I had time to see Tim O'Brien, author of the Jakarta Commons Cookbook (among others), and current Maven Sage. I also met Emmanuel Bernard, the specification lead for JSR-303, briefly after his presentation. I was able to talk to a few people from SpringSource that I met at The Spring Experience too. I highly recommend going to The Spring Experience if you're using Spring or want to. It looks like Java will be more and more places that you might not expect it over the next year. Hopefully it will be another good year for Java and the language and Open Source projects will continue to evolve to fulfill everyone's needs. I'm happy that I still enjoy programming in it and also to be getting back involved in Open Source.
Spring Hibernate Examples
Before JavaOne I was able to post some Hibernate examples to Spring by Example. They are simple examples showing how to configure Hibernate with XML or annotations and setting them up with a Spring Hibernate template. There is also one example showing how to use transactions and also how to do a transactional JUnit 4 test.
Labels:
hibernate,
spring by example,
spring framework
Wednesday, March 26, 2008
JAXB with Maven
Finally Sun has Maven repositories for getting Sun jars and also they have a nice plugin for generating JAXB 2 classes with Maven using the maven-jaxb2 plugin. It defaults to generating schemas located in src/main/resources and the generated output goes to target/generated-sources/xjc. The generated output will automatically be included in your final jar.
Excerpt from pom.xml
Excerpt from pom.xml
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.1</version>
<scope>test</scope>
</dependency>
<build>
<plugins>
<plugin>
<groupid>org.jvnet.jaxb2.maven2</groupid>
<artifactid>maven-jaxb2-plugin</artifactid>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Maven 2 Repository</name>
<url>http://download.java.net/maven/2</url>
</repository>
</repositories>
<!-- For maven-jaxb2-plugin -->
<pluginrepositories>
<pluginrepository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Maven 2 Repository</name>
<url>http://download.java.net/maven/2</url>
</pluginrepository>
</pluginrepositories>
Friday, March 7, 2008
Spring by Example Site is Open!
The Spring by Example site is finally open! I've been working this for a couple of months, but wanted it to be fairly nice when it went live. It has a few good examples and I have more to post. A few people I know have said they will contribute examples as they have time also. These are some of my favorite examples posted so far.
Tim Voet also posted an example using a BeanPostProcessor to dynamically insert a logger based on the bean's class if it has a setLogger method. This is a nice way to avoid typos when creating loggers.
- Custom Thread Scope
- Spring custom scope implementation for thread scoped beans.
- Dynamic Tiles Spring MVC Module
- Have a default Tiles definition that takes the url of an incoming request and assumes it should be the request body and dynamically inserts the url into the default definition.
- Spring by Example JDBC
- Some nice utitlies for helping initialize scripts and to make it easier using HSQL DB. They are especially useful for unit tests.
- Spring by Example JCR Module
- Utilities for helping to recurse through JCR Nodes.
- Spring by Example Util's HttpClientTemplate
- Callback template around Commons HttpClient.
- Spring by Example Util's HttpClientOxmTemplate
- Callback template around Commons HttpClient that uses Spring OXM to marshall and unmarshall XML for HTTP requests.
Tim Voet also posted an example using a BeanPostProcessor to dynamically insert a logger based on the bean's class if it has a setLogger method. This is a nice way to avoid typos when creating loggers.
Subscribe to:
Posts (Atom)