Thursday, February 23, 2012

A maven trick

I was playing around with STS, adding Grails to it for my own purposes. I don't know if this messed things up or not, but when I went to run one of my other spring projects, it came up with this error:

java.lang.NoClassDefFoundError: org/junit/runner/notification/StoppedByUserException


I removed the Grails plug-in, but still got the same error. A clean didn't help either.

Here's what did:

Open a terminal window, navigate to the top level of the directory of your project, and type:

mvn eclipse:clean
mvn clean
mvn eclipse:eclipse

Then refresh the project STS, navigate to your junit test and run as such, and you're back in business.

Monday, February 20, 2012

Hibernate - getting started

In this blog, we'll explore how to run some hibernate from the source - hibernate.org. It has a nice tutorial, which is also short and sweet.

In order to get the tutorials up and running, download the code from here:

http://docs.jboss.org/hibernate/core/4.0/quickstart/en-US/html_single/#d0e127

and click on the files/hibernate-tutorials.zip link. Once the file is downloaded and unzipped, copy it into your STS workspace. (I'm assuming you have STS and maven installed - if not, you may need to research downloading maven/eclipse or just STS).

Once that's done, bring up a terminal window and navigate to hibernate-tutorials directory you just copied into the workspace. For each of the four tutorial projects (hbm, entitymanager, annotations and envers), navigate into the directory and type "mvn eclipse:eclipse". That creates an eclipse project file. That allows you import the four projects into STS. Use file, import, select "existing projects into workspace", and find one of the folders (e.g. hibernate-tutorial-hbm) and import it. Do this for all of the projects.

You can run them by right-clicking and select "junit test".

I won't rehash what's done in each of them. Here's the url for the very short, but very clear and easy to follow tutorial: http://docs.jboss.org/hibernate/core/4.0/quickstart/en-US/html/

The basics of are this:

Chapter 2 - Tutorial Using Native Hibernate APIs and hbm.xml Mappings

hibernate-tutorial-hbm:

- uses Hibernate mapping files (hbm.xml) to provide mapping information
- uses the native Hibernate APIs

The hibernate.cfg.xml file contains info like database driver, username, password, connection url, etc.
The Event.hbm.xml file contains the mapping of the field.


The next tutorial, chapter 3:

hibernate-tutorial-annotations

Tutorial Using Native Hibernate APIs and Annotation Mappings

Objectives

Use annotations to provide mapping information

Use the native Hibernate APIs

The event.hbm.xml file, which maps the class fields to the database fields, is gone. Annotations within the source code give the same information. The hibernate.hbm.xml file reflects the change with a declaration of the mapping class, "mapping class="org.hibernate.tutorial.annotations.Event".

Here's what event looks like with annotations:


import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.GenericGenerator;

@Entity
@Table( name = "EVENTS" )
public class Event {
private Long id;

private String title;
private Date date;

public Event() {
// this form used by Hibernate
}

public Event(String title, Date date) {
// for application use, to create new events
this.title = title;
this.date = date;
}

@Id
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment")
public Long getId() {
return id;
}

private void setId(Long id) {
this.id = id;
}

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "EVENT_DATE")
public Date getDate() {
return date;
}

public void setDate(Date date) {
this.date = date;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}
}



Chapter 4. Tutorial Using the Java Persistence API (JPA)

Objectives

Use annotations to provide mapping information.

Use JPA.

This chapter shows utilizes the Java persistence API instead of the native hibernate API. Here, the hibernate.hbm.xml is replaced by persistence.xml. persistence.xml, like the hibernate.hbm.xml file, shows the configuration information, such as jdbc driver, url, name password, plus a couple of hibernate-specific values which as a result begin with "hibernate-". The programmatic API is slightly different, using "persist" instead of "save.", but looks very similar

The final chapter adds some auditing capability via the @org.hibernate.envers.Audited annotation.

Saturday, February 18, 2012

Autowiring and Component scans

In our last blog entry, we took the "Hello World" program from the Spring 2.5 Recipes book and incorporated it into a Spring template utility project.

One if the interesting facts about the generated template test is that it includes the service as an "@Autowired" annotation:


@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class ExampleConfigurationTests {

@Autowired
private Service service;

@Test
public void testSimpleProperties() throws Exception {
assertNotNull(service);
}

}



A component scan statement in the bean configuration file apparently tells the Spring container to search for the @Component annotation in the specified package and subpackages:


<context:component-scan base-package="com.apress.springrecipes.hello" />


It's specified in the ExampleService bean:


@Component
public class ExampleService implements Service {



So, although the test class that uses it doesn't specify "ExampleService", but rather just "Service", since ExampleService is the only component in the package that matches the @Autowired annotation (it's a Service), Spring selects that as the class to be instantiated.

Our experiment today, though, is to first just implement @Autowired in a regular (not used for testing) class. If that works out, we'll try to see if we can use the component scan to avoid coding the beans.

We'll base our logic on this tutorial:

http://www.mkyong.com/spring/spring-auto-wiring-beans-with-autowired-annotation/

So, first let's generate a spring utility project. We'll call it "SpringTestAutowireAnnotation", and give it the same package name as the tutorial: "com.mkyong.common".

We can download the source code, and drag and drop the java source files into that package in the generated project. Also, we'll copy these bean configuration statements from the configuration file into our own project's configuration file (src/main/resources/META-INF/spring/app-context.xml):

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

<bean id="customer" class="com.mkyong.common.Customer" >
<property name="action" value="buy" />
<property name="type" value="1" />
</bean>

<bean id="personA" class="com.mkyong.common.Person" >
<property name="name" value="mkyongA" />
</bean>



So, now here's our app-context.xml:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<description>Example configuration to get you started.</description>

<context:component-scan base-package="com.mkyong.common" />

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

<bean id="customer" class="com.mkyong.common.Customer" >
<property name="action" value="buy" />
<property name="type" value="1" />
</bean>

<bean id="personA" class="com.mkyong.common.Person" >
<property name="name" value="mkyongA" />
</bean>

</beans>



We'll have to change the means of retrieving the application context in the "App" class from this:

ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"SpringBeans.xml"});


to this:

ApplicationContext context =
new ClassPathXmlApplicationContext("app-context.xml");



And, also, add the classpath app-context to the new run configuration for the project:

To do this, right click on App.java, select "Run As", "Run Configuration", click the new icon, give it a name like "SpringAutoWiredTest", click on the "Classpath" tab, select "User Entries", click the "Advanced" button on the right, select "Add External Folder", then navigate to the current project and then down to "src/main/resources/META-INF/spring", and then press "Choose".

Apply the changes and run.

Here's the output:

Customer [person=Person [name=mkyongA], type=1, action=buy]



Ok, now the ultimate test. Can we get delete the beans from the configuration file, add the @Component annotation to the beans, and get the same results? Let's try it.

Here's the new app-context.xml, with the beans deleted:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<description>Example configuration to get you started.</description>

<context:component-scan base-package="com.mkyong.common" />

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

</beans>



Let's add the @Component annotations:

import org.springframework.stereotype.Component;

@Component
public class Customer {


and

import org.springframework.stereotype.Component;

@Component
public class Person {



Here's the output:


Customer [person=Person [name=null], type=0, action=null]


The name and action are null, because these were specified in the beans which we deleted. That's something to keep in mind when considering when and how to use the @Component tag.

Friday, February 17, 2012

Spring utilty template - merging with Hello Word

I had previously meant to do a blog on using a spring template utility to do the hello world example in chapter 2 from the Spring 2.5 Recipe book, but got sidetracked. So, let's give it another go.

The basics of it are, when you create a Simple Spring Utility project from STS (new, Spring Template Project, Simple Spring Utility Project), you get an ExampleService and a Service interface generated for you. The Service interface is just this:


package com.apress.springrecipes.hello;

public interface Service {

String getMessage();

}



And the ExampleService implements the Service interface and returns "hello, World":



package com.apress.springrecipes.hello;

import org.springframework.stereotype.Component;


/**
* {@link Service} with hard-coded input data.
*/
@Component
public class ExampleService implements Service {

/**
* Reads next record from input
*/
public String getMessage() {
return "Hello world!";
}

}


The above example includes an example of using the @Component annotation, which means you don't have to specify the bean in the spring xml file. If we look in there (in "src/main/resources/META-INF/spring/app-context.xml"), we'll see the following declaration:


<context:component-scan base-package="com.apress.springrecipes.hello" />


This tells the Spring container to look through the specified package and subpackages for any class with the "@Component" annotation and make it a bean. (There are also subclasses of @Component, but that's the gist of it).

Getting back to the main point, to see this in action, you need to run the unit tests that get generated from the template. For example, if you drill down into "src/test/java", you'll find a class called "ExampleServiceTests.java", that looks like this:



package com.apress.springrecipes.hello;

import com.apress.springrecipes.hello.ExampleService;
import junit.framework.TestCase;

public class ExampleServiceTests extends TestCase {

private ExampleService service = new ExampleService();

public void testReadOnce() throws Exception {
assertEquals("Hello world!", service.getMessage());
}

}


If you right-click and run that as a junit test, you'll see the green bar indicating it passed the test.

However, we'd like to run the code from the Spring Recipe book:



package com.apress.springrecipes.hello;

public class HelloWorld {

public void hello() {
System.out.println("Hello world!");
}
}




Based on the book, the main class should look (roughly) like this:



public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("app-context.xml"); // why would expect to find beans.xml?

HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");
helloWorld.hello();
}



Note that I changed the name of the spring beans file to "app-context.xml". It's in "src/main/resources/META-INF/spring/app-context.xml".

Let's add the entry for HelloWorld into it:


<bean id="helloWorld" class="com.apress.springrecipes.hello.HelloWorld">
</bean>


Now, if you just run main like this, it will crash, because app-context.xml (the bean configuration file) isn't in the classpath. It's in "src/main/resources/META-INF/spring/app-context.xml.


So, how to we get it that into the class path?

Here's how:

In the STS, select Run > Run Configurations. Click on the user entries item in the dialog box, then advanced > add external folder, then drill down to the path leading up to the configurations file. Also, obviously, use the main class above as the main class. When you run it, you should see "hello world!" in your console output.

Hibernate in Spring 3

Hibernate is something that I've done a couple of tutorials on in the past. Basically, to me it's been something that lets you map in XML what fields in the object correspond to what fields in the db, so you don't have to code JDBC statements.

But, I ran the hibernate wizard on spring 3 templates, and it actually seems as if it's close to the Groovy version, which means there aren't any mappings to be done at all. Let's find out why.

Checking app-context.xml, we find the following 3 statements

<jdbc:embedded-database id="dataSource" type="H2"/>

<tx:annotation-driven transaction-manager="transactionManager" />

<context:component-scan base-package="xyz.sample.barehibernate" />

So, it looks like it's using an embedded HQL data source, supports transactions, and scans the package for components.

Next, let's look at the source code the template wizard create. First, there's a class called "Hibernate Configuration" which ought to be interesting:

I'll add comments to show my guesses as to what the code means:



package xyz.sample.barehibernate;

import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.dialect.H2Dialect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;

@Configuration // this is used for configuration - not sure what that exactly means, but it's a java configuration vs. xml
// configuration
public class HibernateConfiguration {

@Value("#{dataSource}") // clearly pulling in the data source from app-context.xml.
private DataSource dataSource;

@Bean // A bean which will be scanned by the container
public AnnotationSessionFactoryBean sessionFactoryBean() { // method to generate an annotation-based Hibernate
// session, used by the container
Properties props = new Properties();
props.put("hibernate.dialect", H2Dialect.class.getName()); // set up the HSQL dialect to be used
props.put("hibernate.format_sql", "true"); // we like SQL

AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean(); // private instantiation
bean.setAnnotatedClasses(new Class[]{Item.class, Order.class}); // give it the classes to be "hibernated"
// this is the "magic" that saves mapping
bean.setHibernateProperties(props); // set the props
bean.setDataSource(this.dataSource); // set the data source
bean.setSchemaUpdate(true); // allow updates/
return bean;
}


// Give whoever needs the transaction manager the session factory bean decorated with the
// Hibernate transaction manager

@Bean
public HibernateTransactionManager transactionManager() {
return new HibernateTransactionManager( sessionFactoryBean().getObject() );
}

}




Now the domain classes, again with comments:

package xyz.sample.barehibernate;


import java.util.Collection;
import java.util.LinkedHashSet;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;


/**
* An order.
*/
@Entity // It's a domain object
@Table(name="T_ORDER") // here's the table name
public class Order {

@Id // this is the id
@GeneratedValue(strategy=GenerationType.AUTO) // and it should be auto-generated
private Long id; // make it a long

private String customer;

@OneToMany(cascade=CascadeType.ALL) // it can have many items
@JoinColumn(name="ORDER_ID") // here's the column name to join it on
private Collection items = new LinkedHashSet(); // and the list of items

// getters and setters

/**
* @return the customer
*/
public String getCustomer() {
return customer;
}

/**
* @param customer the customer to set
*/
public void setCustomer(String customer) {
this.customer = customer;
}

/**
* @return the items
*/
public Collection getItems() {
return items;
}

/**
* @param items the items to set
*/
public void setItems(Collection items) {
this.items = items;
}

/**
* @return the id
*/
public Long getId() {
return id;
}

}

// this is the order header

package xyz.sample.barehibernate;


import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

/**
* An item in an order
*/
@Entity // It's a domain object (persistable)
public class Item {

@Id // see above
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@ManyToOne // many of these to one order
private Order order;

// pojo variables, getters and setters

private String product;

private double price;

private int quantity;

/**
* @return the order
*/
public Order getOrder() {
return order;
}

/**
* @return the product
*/
public String getProduct() {
return product;
}

/**
* @param product
* the product to set
*/
public void setProduct(String product) {
this.product = product;
}

/**
* @return the price
*/
public double getPrice() {
return price;
}

/**
* @param price
* the price to set
*/
public void setPrice(double price) {
this.price = price;
}

/**
* @return the quantity
*/
public int getQuantity() {
return quantity;
}

/**
* @param quantity
* the quantity to set
*/
public void setQuantity(int quantity) {
this.quantity = quantity;
}

/**
* @return the id
*/
public Long getId() {
return id;
}
}




So by a magic combination of scanning (to avoid coding the beans (and configuration?) in the spring beans file, a variety of annotations (Entity, manytoone, onetomany, id, generated value, and a hibernation configuration java class which uses the magic of reflection to set the properties, we have a full-blown hibernate system without mapping of specific fields.

Below is an example of how to utilize the data via some unit tests, aslo generated:


@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class OrderPersistenceTests {

@Autowired
private SessionFactory sessionFactory;

@Test
@Transactional
public void testSaveOrderWithItems() throws Exception {
Session session = sessionFactory.getCurrentSession();
Order order = new Order();
order.getItems().add(new Item());
session.save(order);
session.flush();
assertNotNull(order.getId());
}

@Test
@Transactional
public void testSaveAndGet() throws Exception {
Session session = sessionFactory.getCurrentSession();
Order order = new Order();
order.getItems().add(new Item());
session.save(order);
session.flush();
// Otherwise the query returns the existing order (and we didn't set the
// parent in the item)...
session.clear();
Order other = (Order) session.get(Order.class, order.getId());
assertEquals(1, other.getItems().size());
assertEquals(other, other.getItems().iterator().next().getOrder());
}

@Test
@Transactional
public void testSaveAndFind() throws Exception {
Session session = sessionFactory.getCurrentSession();
Order order = new Order();
Item item = new Item();
item.setProduct("foo");
order.getItems().add(item);
session.save(order);
session.flush();
// Otherwise the query returns the existing order (and we didn't set the
// parent in the item)...
session.clear();
Order other = (Order) session
.createQuery( "select o from Order o join o.items i where i.product=:product")
.setString("product", "foo").uniqueResult();
assertEquals(1, other.getItems().size());
assertEquals(other, other.getItems().iterator().next().getOrder());
}

}

Saturday, February 11, 2012

Spring Recipes, for Spring 2.5 - Chapter 1

So, I know this is a little out of date, but I think Spring Recipes for 2. 5 is the best Spring book out there. It doesn't cover 3.0, but you will definitely get the fundamentals down. Plus, I saw a review of the 3.0 book that said it was *huge*, and I really would rather keep things as streamlined a possible. I really want to nail down the fundamentals of Spring.

I previously went through the first five chapters (see previous entries in this blog), but it was a while ago. Now, I'm coming back to it using STS and Spring 3, so it will be a little bit strange. I'm not sure this is the best route to go, but I'm tentatively starting out on it.

So, without further ado, here's a review on chapter one.

Using a Container

Chapter one talks about containers. You start out simply enough, with a "ReportGenerator" interface that has the method "generate". Generate accepts statistics and generates a report. There are a couple of implementing classes - PdfReportGenerate and HTMLReportGenerator. One of them will print a pdf report, the other will implement an HTML report. All the report service has to do is instantiate whichever of the two it needs, and call "generate" and pass the statistics.

The problem is that, say your product services a couple of different organizations, one likes pdf reports, the other HTML reports. That means you have to go in and muck with your report generator for each different organization. So, really for separation of concerns - you don't want your "what is this organizations type of report" logic mixed in with the "how do I gather statistics" logic, something needs to be done.

You might initially think, well, let's just create a separate class that instantiates the report service, instantiates the concrete report generator class and sets the report generator class on the report service. But, possibly as a scalability issue, they suggest setting up a "container" with a map that holds an instance of the report service, an also an instance of the report generator. So, this generator will hang around with an instance of the report service and the report generator that any old class can grab and use.

So, the report service grabs the report generator from the container whenever it needs it, confident that the correct version of it has been been put in place by the container. Later on, too keep from mucking with the container, you can have the container read a configuration file for the correct report generator class.

But what grabs the report service from the container? Well, the way you would *initially* handle that (we're working our way through all this), is to create the container from a *main* class. The main class then grabs the report generator from the container, and calls something like "createAnnualReport(2007)". The report service will have that method, and will scurry about putting together whatever data it needs to create the annual report. Then, as mentioned earlier, the report service will grab whatever report generator is provided by the container, and call "generate(collected data) on it.

One detail we skimmed over was that when container is created, it puts a static reference to itself (this) into a static variable. This allows the report service to grab the static instance of container from the Container class. Main doesn't need to bother with that when it gets the report service because it instantiated the container.

Whew! That's actually fairly complicated. Just think of the Container as a cupboard full of goodies, which loads itself when instantiated. The main class- the user of the service - happily grabs the reports service from the cupboard (Container) (after instantiating it), and then uses that service.

The service just uses the cupboard (Container) to get *whatever* report generator is there. It gets the that, then calls the report generator method.

Using a Service Locator.

That's all well and good - but what if the cupbard/container varies by organization? Some use one server, some use another, perhaps. If you're writing this framework, do you want to have the code to get the Container (from the report service) vary, depending on how the container is created? According to the book, this could be "complex, proprietary code." Actually, I wish they gave a better example of this problem. It probably has something to do with the fact that it wouldn't make sense for each use of the service to create it's own container - why have a bunch of cupboards (fleeting though they may be) when you can just have one? I'm kind of guessing here, it's a working hypotheses.

So, you've got to look up the cupboard - find it somewhere on the system. Probably that varies depending on the system. And we don't want random services, such as the report service, to have to be responsible for this. It doesn't want to change every time it's on a new system.

So, we separate out the container/cupboard lookup logic into a separate class - the service locator bunny class. This is all about separation of concerns, reducing dependencies, etc. So, instead of having the Report Service grab the report generator directly from the container, we have it do something like "ServiceLocator.getReportGenerator();" And inside the ServiceLocator bunny, it will have method like:

private static Container = Container.instance

and a method which returns the report generator after grabbing it from the cupboard. So, the Service Locator will handle all the work of figuring out where the container is.

Inversion of Control / Dependency Injection

Although we've gotten rid of a specific dependency by providing a container for the Report Service to grab its ReportGenerator from, and even removed the need of the Report Service be concerned about how to implement lookup by giving it a Resource Locater which handles that work - we can make Report Service even dumber. After all, all this was all about was getting the correct instance of the report generator to the report service. So, why not just give report service a setter method for the report generator? No lookup whatsoever in your Report Service! This is good stuff, right?

So, now the container becomes more than just a cupboard. She becomes old Mother Hubbard, giving little Report Service the right instance of the Report Generator and sending her off to school. Mother Hubbard / Container can also now reduce her exposure by no longer providing access to "this".

Note that there are several ways to do injection - setter (via a set method), construction (via - you guessed it - construction) and interface (not widely used).

Adding a Configuration File.

Ok, now that we've set up all these principals, we really ought to make the whole thing configurable. So, what can we configure, and how?

For sure, we can define the pdf or html instance of the report generator. We give it a name that the container can refer to it with, and also the actual class name:

reportGenerator=com.apress.springrecipes.report.PdfReportGenerator

Come to think of it, we can also specify the report service:

reportService=com.apress.springrecipes.report.ReportService

Anything else...hmmm,,,,

Ah - what about which classes get injected where? We gotta let old mother Hubbard, our container/cupboard, know this:

reportService.reportGenerator=reportGenerator

Nice.

Then, the book shows a slick implementation of the Container class. I *think* there might be typo on Dependency Injection part - it seems like "value" should be "parts[1]" on a certain line. I haven't tested it though.

Good tutorial on maven, spring

Well, our hopes for a quick attack on Spring 3.0 have been somewhat dashed by an apparent bug in the template generation for an MVC app - although we did luckily manage to get one up and running, which I've carefully preserved.
(note - this was fixed by just doing a "clean" on the project).

The tutorial did give a pom.xml file at the end - and I'm wondering if it's possible to use a war file generate from that successfully create multiple mvc apps.

Maven is something I've never really had a chance to get into, so I took this as an opportunity to learn a *little* bit about it.

This is a tutorial I landed upon:

http://pookey.co.uk/wordpress/archives/50-getting-started-with-maven-and-spring

I actually got the whole thing to work, start to finish.

The first thing your supposed to do is this command:

mvn archetype:generate --batch-mode \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DgroupId=uk.co.pookey.spring \
-DartifactId=spring-hello \
-Dversion=1.0-SNAPSHOT

When you run it from the command line, get rid of the backslashes and put it all on the same line. It turns out when you run it, because you're specifying the archetype, it's based on some kind of super-pom that specifies a lot of files.

It also creates a source and build file structure, and a program called App.java, which looks like this:


package uk.co.pookey.spring;

public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}


My theory is that the "hello world" app is part of the archetype template. So, you just get this nice vanilla directory structure with a hello world app built in.

The directory created gets its name from DartifactId=spring-hello

it also creates a file called pom.xml, as well as src and target directories.

Here's the path of the App.java: src/main/java/uk/co/pookey/spring/App.java

In order to get the App.java to work, you need to add this to your pom.xml:


<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>

<configuration>
<mainClass>uk.co.pookey.spring.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>

This makes this command possible:

mvn exec:java

which will execute the java class.

But first, you need to compile it:


$ mvn compile

Then run:

$ mvn exec:java


It you'll see the "Hello" message.


This is fine for creating a standard product structure, but we're trying to learn a little bit of spring too.

Well, this example does that for us. First it specifies in pom.xml a dependency on the spring container:


<dependencies>
...
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.5.5</version>
</dependency>
</dependencies>


I turns out there's a huge, searchable archive of maven dependencies here:

http://www.mvnrepository.com/

But, this is the one where we are getting our version from:

http://www.mvnrepository.com/artifact/org.springframework/spring


This is the strength of maven - it just knows what the version numbers of the jar files you need are, automatically - since you specified them in the first place. It also pulls down any spring dependencies.

Next we create a new pojo in src/main/java/uk/co/pookey/SayHello.java:

package uk.co.pookey;

public class SayHello
{

private String name;

public void setName(String name)
{
this.name = name;
}

public String getName()
{
return name;
}

public void greet()
{
System.out.println("Hello " + getName());
}

}

This can accept a dependency injection of name, which is printed out later on.

Next we create the famed bean configuration file:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="hello" class="uk.co.pookey.SayHello">
<property name="name" value="Pookey" />
</bean>
</beans>


This is going to be placed in src/main/resources/application-context.xml. You need to create the resources directory.

Finally, we see an example of dependency injection:



package uk.co.pookey.spring;

import uk.co.pookey.SayHello;

import org.springframework.core.io.ClassPathResource;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;

public class App
{
public static void main( String[] args )
{
BeanFactory factory = new XmlBeanFactory(
new ClassPathResource("application-context.xml"));

SayHello hello = (SayHello) factory.getBean("hello");
hello.greet();
}
}



The app class pulls the hello bean from the XMLBeanFactory and calls "greet" on it. The factory has already taken care of setting the name to "Pookey" based on the configuration.

Just type "mvn clean compile exec:java" from the directory level of the pom.xml, and you see the "hello, Pookey" result.

To summarize, we've figured out how to create a simple hello world app using maven and spring, even bringing in some dependency injection. You can create a project from out of nowhere using maven from the command line. It uses an archetype that it finds in the cloud and downloads a bunch of jars and creates your directory structure. We added a couple of entries to allow us to execute the program, as well as introduce a dependency on Spring 2.5. We also added the bean configuration file to specify the dependency.

The next question is, how to we import the into an IDE like STS? We'll tackle that in a subsequent post.

Spring BareMvc - a bare expanation

Spring 3.0 MVC tutorial - a detailed breakdown - part 1.
I'm having a bit of a problem getting off the blocks with Spring. I've decided to get a simple Spring MVC web app running based on this tutorial:

http://blog.springsource.org/2011/01/04/green-beans-getting-started-with-spring-mvc/

And I got *one* working. But, when I add another, I get a not found and the server shows a mapping error.

So, I'm just going to review the tutorial to see if I can glean any hints from that:

Spring MVC, a part of the core Spring Framework, is a mature and capable action-response style web framework, with a wide range of capabilities and options aimed at handling a variety of UI-focused and non-UI-focused web tier use cases.



All this can potentially be overwhelming to the Spring MVC neophyte. I think it's useful for this audience to show just how little work there is to get a bare Spring MVC application up and running (i.e. consider my example something akin to the world's simplest Spring MVC application), and that's what I'll spend the rest of this article demonstrating.


Off to a good start.


I'm assuming you are familiar with Java, Spring (basic dependency injection concepts), and the basic Servlet programming model, but do not know Spring MVC. After reading this blog entry, readers may continue learning about Spring MVC by looking at Keith Donald's Spring MVC 3 Showcase, or the variety of other online and print resources available that cover Spring and Spring MVC.


I might check out the MVC showcase later on.

A note on dependencies and build systems: this article does not assume that you are using a particular build system, e.g. Maven, Gradle or Ant. A fairly minimal sample Maven POM file is includes as an example at the end of the article.


I badly want to use maven. I can use that on my resume as well.

Spring MVC includes most of the same basic concepts as other so-called web MVC frameworks.

Incoming requests enter the framework via a Front Controller. I

n the case of Spring MVC, this is an actual Java Servlet called DispatcherServlet.


Think of DispatcherServlet as the gatekeeper.

It doesn't perform any real web or business logic, but rather delegates to POJOs called Controllers where the real work is done (either in whole or via the back-end).

When the work has been done, it's the responsibility of Views to produce the output in the proper format (whether that's a JSP page, Velocity template, or JSON response).

Strategies are used to decide which Controller (and which method(s) inside that Controller) handles the request, and which View renders the response.

The Spring container is used to wire together all these pieces. It all looks something like this:






Bootstrapping the DispatcherServlet and Spring Container
As mentioned, all incoming requests flow through a DispatcherServlet.

Like any other Servlet in a Java EE application, we tell the Java EE container to load this Servlet at web app startup time via an in the web app's WEB-INF/web.xml.

The DispatcherServlet is also responsible for loading a Spring ApplicationContext that is used to perform wiring and dependency injection of managed component.

On this basis, we specify some init parameters to the Servlet which configure the Application Context.

Let's look at the config in web.xml:
WEB-INF/web.xml




xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">



appServlet
org.springframework.web.servlet.DispatcherServlet

contextConfigLocation
/WEB-INF/spring/appServlet/servlet-context.xml

1



appServlet
/




Ok, there were a couple of important points made. The dispatcher servlet is loaded when the web-app is loaded. This may imply that each app has it's own dispatcher servlet.

This would make sense. each app should have its own front controller. When the request comes into the server, via port 8080, there should be something that lets whatever processes that request know which directory it needs to go to - like the get command parameter. Once it get's there, the DispatcherServlet takes over.


A number of things are being done here:
We register the DispatcherServlet as as a Servlet called appServlet

We map this Servlet to handle incoming requests (relative to the app path) starting with "/"

// the relative to the app path is key. This must be the directory.
// It's actually saying "start looking at the part after the "/"
// It would be good to see an example.


We use the ContextConfigLocation init parameter to customize the location for the base configuration XML file for the Spring Application Context that is loaded by the DispatcherServlet, instead of relying on the default location of -context.xml).



So, this is just telling the server where the spring application context configuration xml file is.


Wait, What if Somebody Doesn't Want to Configure Spring via XML?
The default type of Application Context loaded by the DispatcheServlet expects to load at least on XML file with Spring bean definitions. As you'll see, we'll also enable Spring to load Java-based config, alongside the XML.
Everybody will have their own (sometimes very strong) opinion in this area, but while I generally prefer-Java based configuration, I do believe that smaller amounts of XML config for certain areas can sometimes still make more sense, for one of a number of reasons (e.g. ability to change config without recompilation, conciseness of XML namespaces, toolability, etc.). On this basis, this app will use the hybrid approach, supporting both Java and XML.
Rest assured that if you prefer a pure-Java approach, with no Spring XML at all, it's pretty trivial to achieve, by setting one init param in web.xml to override the default Application Context type and use a variant called AnnotationConfigWebApplicationContext instead.


All this is saying is you can use java-based configurations (how? through annotations?) instead of an xml based one by specifying a param in the web.xml saying the context type is annotation. Then you don't have to specify the path of the spring configuration file.


Here's the controller:

package xyz.sample.baremvc;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {

@RequestMapping(value = "/")
public String home() {
System.out.println("HomeController: Passing through...");
return "WEB-INF/views/home.jsp";
}
}



So, this is telling the controller what the view to return is. That's abundantly clear.


Let's walk through the key aspects of this class:
The class has been annotated with the @Controller annotation, indicating that this is a Spring MVC Controller capable of handling web requests. Because @Controller is a specialization of Spring's @Component Stereotype annotation, the class will automatically be detected by the Spring container as part of the container's component scanning process, creating a bean definition and allowing instances to be dependency injected like any other Spring-managed component.

// So, the @Controller annotation means it's going to be a spring-managed bean.

The home method has been annotated with a @RequestMapping annotation, specifying that this method should handle web requests to the path "/", i.e. the home path for the application.

// I guess this means anything with "/" or after. In this case I think maybe
// something like "/baremvc

The home method simply logs a message to system out, and then returns WEB-INF/views/home.jsp, indicating the view which should handle the response, in this case a JSP page. (If hardcoding the entire view path including WEB-INF prefix, and the fact that it's a JSP, seems wrong to you, you are right. We'll deal with this later)

// Ok, that's maybe what I didn't change on the first try




Now, we need to create the view. This JSP page will simply print a greeting.
WEB-INF/views/home.jsp
view sourceprint?
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>


Home


Hello world!





Ok. Next up:


Finally, as previously mentioned, we need to create a minimal Spring Application Context definition file.
WEB-INF/spring/appServlet/servlet-context.xml


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">














Let's examine the contents of this file:
You'll note that a few different Spring XML namespaces are being used: context, mvc, and the default beans
The declaration ensures the Spring container does component scanning, so that any code annotated with @Component subtypes such as @Controller is automatically discovered. You'll note that for efficiency, we limit (to xyz.sample.baremvc in this case) what part of the package space Spring should scan in the classpath


The declaration sets up Spring MVC's support for routing requests to @Controllers, as well as how some things like conversion, formatting and validation are handled (with some sensible defaults based on what (libraries) is present in your classpath, and the ability to override if needed)



Ok, apparently annotation-driven means you can use controllers. Fair enough.

The web app is now ready to run. Assuming the Servlet container (tc Server in my case) is set to listen on localhost:8080, starting the application and then hitting the URL http://localhost:8080/baremvc via our browser results in a display of the expected greeting:




As trivial as it is, running this application involves all the major pieces of a working Spring MVC application. Let's walk through the major sequences and component interactions:

When the web app starts up, the DispatcherServlet is loaded and initialized because of the entry in web.xml.

// right.

The DispatcherServlet loads an annotation-based Application Context, which has been configured to scan for annotated components via a regular expression specifying the base package(s).

// That would've been the entry in the spring context file:



Annotated components such as the HomeController are detected by the container.

// because of the component-scan command.

The HTTP request to http://localhost:8080/baremvc hits the servlet engine and is routed to our (baremvc) webapp.

The servlet engine of the container. The servlet engine sees the "baremvc" and knows to route it to our web app. Question - which part of the web deployment identifies it as baremvc?


The implicit "/" path at the end of the URL matches the regex that has been registered for the DispatcherServlet, and the request is routed to it

// That's what we saw in web.xml:


appServlet
/



The DispatcherServlet needs to decide what to do with the request. It uses a strategy called a HandlerAdapter to decide where to route the request. The specific HandlerAdapter type (or types, since they can be chained) to be used can be customized, but by default, an annotation-based strategy is used, which routes requests appropriately to specific methods in classes annotated as @Controller, based on matching criteria in @RequestMapping annotations found in those classes. In this case, the regex on the home method is matched, and it's called to handle the request.

// So, the implicit "/" at the end of the url is mapped by:

@Controller
public class HomeController {

@RequestMapping(value = "/")


The home method does its work, in this case just printing something to system out. It then returns a string that's a hint (in this case, a very explicit one, WEB-INF/views/home.jsp) to help chose the View to render the response.
The DispatcherServlet again relies on a strategy, called a ViewResolver to decide which View is responsible for rendering the response. This can be configured as needed for the application (in a simple or chained fashion), but by default, an InternalResourceViewResolver is used. This is a very simple view resolver that produces a JstlView which simply delegates to the Servlet engine's internal RequestDispatcher to render, and is thus suitable for use with JSP pages or HTML pages.
The Servlet engine renders the response via the specified JSP



Taking It to the Next Level
At this point, we've got an app which certainly qualifies as the world's simplest Spring MVC application, but frankly, doesn't really meet the spirit of that description. Let's evolve things to another level.
As previously mentioned, it's not appropriate to hard-code a path to a view template into a controller, as our controller curretly does. A looser, more logical coupling between controllers and views, with controllers focused on executing some web or business logic, and generally agnostic to specific details like view paths or JSP vs. some other templating technology, is an example of separation of concerns. This allows much greater reuse of both controllers and views, and easier evolution of each in isolation from the other, with possibly different people working on each type of code.
Essentially, the controller code ideally needs to be something like this variant, where a purely logical view name (whether simple or composite) is returned:

//...
@Controller
public class HomeController {

@RequestMapping(value = "/")
public String home() {
System.out.println("HomeController: Passing through...");
return "home";
}
}



This is actually the default of the wizard that using the spring version I downloaded.


Spring MVC's ViewResolver Strategy is actually the mechanism meant to be used to achieve this looser coupling between the controller and the view. As already mentioned, in the absence of the application configuring a specific ViewResolver, Spring MVC sets up a default minimally configured InternalResourceViewResolver, a very simple view resolver that produces a JstlView.

There are potentially other view resolvers we could use, but to get a better level of decoupling, all we actually need to do is set up our own instance of InternalResourceViewResolver with slightly tweaked configuration. InternalResourceViewResolver employs a very simple strategy; it simply takes the view name returned by the controller, and prepends it with an optional prefix (empty by default), and appends it with an optional suffix (empty by default), then feeds that resultant path to a JstlView it creates. The JstlView then delegates to the Servlet engine's RequestDispatcher to do the real work, i.e. rendering the template. Therefore, to allow the controller to return logical view names like home instead of specific view template paths like WEB-INF/views/home.jsp, we simply need to configure this view resolver with the prefix WEB-INF/views and the suffix .jsp, so that it prepends and appends these, respectively, to the logical name returned by the controller.


One easy way to configure the view resolver instance is to introduce the use of Spring's Java-based container configuration, with the resolver as a bean definition:
package xyz.sample.baremvc;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
public class AppConfig {

// Resolve logical view names to .jsp resources in the /WEB-INF/views directory
@Bean
ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}


I get it. He specified a scan in the spring context xml file for the package, the spring will find it and apply it to its configuration. The @Bean tells it to use this method to create a bean.







It's hard to make a case for this object that one particular approach is much better than the other, so it's really a matter of personal preference in this case (and we can actually see one of the strengths of Spring, its flexible nature).


Ok, this is a good cutoff point before getting into the next part. Oh, yeah - you can get rid of the error by running a "clean" on the project.