![]() |
|
Comenteaza
Configure Maven to generate classes from XML Schema using JAXB
In my previous post I showed how to create RESTful services using Spring Framework. For representation of resources in XML I used JAXB and I followed the bottom-up approach (I wrote the Java classes and I let to generate XML/XSD from Java classes). In this post I will demonstrate how you can generate the same Java classes (User and UserList) from XML Schema (XSD) during Maven build, therefore using a top-down approach. For generation of Java classes from XML Schema during Maven build I will use Java.net Maven 2 JAXB 2 Plugin.
Along with the default generation of Java classes from XML Schema using xjc tool, I will add the following customizations:
Making all the generated classes to implement Serializable (useful when you want to use classes with some remote services: RMI, EJB, etc).
Use java.util.Calendar instead of javax.xml.datatype.XMLGregorianCalendar for fields generated from elements of type xs:dateTime.
Generated classes should also have a generated toString() method.
Classes have to be annotated with XmlRootElement (required by Spring Framework when classes are used to represent state in RESTful services).
You can further enhance and customize the generation of Java classes using various plugins.
Project sources are available for download. So let’s start, step by step:
Create Maven project. Below you can see the POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.zmeu</groupId>
<artifactId>zmeu-blog-maven-jaxb</artifactId>
<version>1.0-SNAPSHOT</version>
<name>ZMEU Blog Maven JAXB</name>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.0</version>
<configuration>
<schemaDirectory>src/main/resources/schema</schemaDirectory>
<bindingDirectory>src/main/resources/schema</bindingDirectory>
<generatePackage>org.zmeu.blog.jaxb</generatePackage>
<strict>false</strict>
<extension>true</extension>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>0.6.2</version>
</plugin>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics-annotate</artifactId>
<version>0.6.2</version>
</plugin>
</plugins>
<args>
<arg>-Xannotate</arg>
<arg>-XtoString</arg>
</args>
</configuration>
<executions>
<execution>
<id>generate</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics-runtime</artifactId>
<version>0.6.2</version>
</dependency>
</dependencies>
</project>
Write XML Schema (schema.xsd):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="user" type="user" />
<xs:element name="userList" type="userList" />
<xs:complexType name="user">
<xs:all>
<xs:element name="id" type="xs:long" minOccurs="0" />
<xs:element name="name" type="xs:string" />
<xs:element name="registrationDate" type="xs:dateTime" />
</xs:all>
</xs:complexType>
<xs:complexType name="userList">
<xs:sequence>
<xs:element name="user" type="user" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:schema>
Customize JAXB Bindings (binding.xjb):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:annox="http://annox.dev.java.net"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<jaxb:globalBindings>
<!-- Use java.util.Calendar instead of javax.xml.datatype.XMLGregorianCalendar for xs:dateTime -->
<jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime"
parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime"
printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />
<!-- Force all classes implements Serializable -->
<xjc:serializable uid="1" />
</jaxb:globalBindings>
<!-- Annotate the following classes with XmlRootElement -->
<jaxb:bindings schemaLocation="schema.xsd" node="/xs:schema">
<jaxb:bindings node="xs:complexType[@name='user']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="user" />
</annox:annotate>
</jaxb:bindings>
<jaxb:bindings node="xs:complexType[@name='userList']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="userList" />
</annox:annotate>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
Run the build using mvn clean install command. Build must be successful. Generated classes will be located in target/generated-sources/xjc directory. Below is a snippet from generated User class:
.....
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "user", propOrder = {})
@XmlRootElement(name = "user")
public class User implements Serializable, ToString {
private final static long serialVersionUID = 1L;
protected Long id;
@XmlElement(required = true)
protected String name;
@XmlElement(required = true, type = String.class)
@XmlJavaTypeAdapter(Adapter1 .class)
@XmlSchemaType(name = "dateTime")
protected Calendar registrationDate;
.....
}
You are done!








CRUD RESTful services using Spring Framework
In this post I will show how to build CRUD (Create, Read, Update, Delete) REST-ful (Representational State Transfer) services using Spring Framework. Spring Framework version used in this example is 3.0.6.RELEASE. Apache Tomcat version used for testing the web services is 6.0.29 (default Tomcat version used by Tomcat Maven Plugin of Apache Maven 2.2.1). Project sources are available for download. So let’s start, step by step:
First we have to define the resource on which the CRUD operation will be performed and how this resource will be represented. In our example we will use a resource that represents a User. The resource will be represented using XML (Extensible Markup Language). At the end of the post I will show how you can switch the resource representation to JSON (JavaScript Object Notation) or any other supported form.
Create a Maven project. We will use Maven for project management and build. Maven POM is shown below:
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.zmeu</groupId>
<artifactId>zmeu-blog-spring-rest</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>ZMEU Blog Spring REST</name>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
<!-- Logging dependencies -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<scope>runtime</scope>
</dependency>
<!-- Testing dependencies -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Write User class that will represent our resource. Due to fact that we have decided to represent our resource using XML, we will annotate our class using JAXB (Java Architecture for XML Binding) annotations. When JAXB is used, Spring requires java classes to be annotated with @XmlRootElement (see Jaxb2RootElementHttpMessageConverter). If you are using Java 6 then you don’t have to do anything special because Java 6 is coming already with JAXB2, otherwise you will have to include dependencies to JAXB into your project. You can see below the User.java listing:
package org.zmeu.blog.spring.rest.domain;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name = "userType")
@XmlRootElement(name = "user")
public class User {
private long id;
private String name;
private Date registrationDate;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getRegistrationDate() {
return registrationDate;
}
public void setRegistrationDate(Date registrationDate) {
this.registrationDate = registrationDate;
}
@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("id", getId());
builder.append("name", getName());
builder.append("registrationDate", getRegistrationDate());
return builder.toString();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof User)) {
return false;
}
User other = (User) obj;
EqualsBuilder equalsBuilder = new EqualsBuilder();
equalsBuilder.append(getId(), other.getId());
return equalsBuilder.isEquals();
}
@Override
public int hashCode() {
HashCodeBuilder hashCodeBuilder = new HashCodeBuilder();
hashCodeBuilder.append(getId());
return hashCodeBuilder.toHashCode();
}
}
In order to represent a list of users we will create a new class UserList.java
package org.zmeu.blog.spring.rest.domain;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name = "userListType")
@XmlRootElement(name = "userList")
public class UserList {
private List<User> users = new ArrayList<User>();
public UserList() {}
public UserList(List<User> users) {
this.users = users;
}
@XmlElement(name = "user")
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
Write a Spring service that will provide CRUD operations for our resource. In our case this is a simple service which uses a java.util.Map for storage. Normally this should be a service that performs some validations and delegates the persistence activities to a DAO (Data Access Object). First define the interface UserService.java:
package org.zmeu.blog.spring.rest.service;
import java.util.Collection;
import org.zmeu.blog.spring.rest.domain.User;
public interface UserService {
User create(User user);
User read(long userId);
User update(User user);
User delete(long userId);
Collection<User> list();
}
And after the implementation UserServiceImpl.java:
package org.zmeu.blog.spring.rest.service;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.lang3.Validate;
import org.springframework.stereotype.Service;
import org.zmeu.blog.spring.rest.domain.User;
@Service
public class UserServiceImpl implements UserService {
private final AtomicLong USER_ID_SEQ = new AtomicLong();
private final ConcurrentMap<Long, User> usersMap = new ConcurrentHashMap<Long, User>();
@Override
public User create(User user) {
user.setId(USER_ID_SEQ.incrementAndGet());
usersMap.put(user.getId(), user);
return user;
}
@Override
public User read(long userId) {
return usersMap.get(userId);
}
@Override
public User update(User user) {
User updatedUser = usersMap.replace(user.getId(), user);
Validate.isTrue(updatedUser != null, "Unable to find user with id: " + user.getId());
return updatedUser;
}
@Override
public User delete(long userId) {
User removedUser = usersMap.remove(userId);
Validate.isTrue(removedUser != null, "Unable to find user with id: " + userId);
return removedUser;
}
@Override
public Collection<User> list() {
return usersMap.values();
}
}
Write a Spring MVC controller that will do the actual work required by a RESTful service. Our controller maps to the following locations:
URL
HTTP Method
Description
http://host:port/servletContextPath/users
GET
Retrieves the user list.
http://host:port/servletContextPath/users
POST
Creates a new user.
http://host:port/servletContextPath/users/12
GET
Retrieves user with id = 12.
http://host:port/servletContextPath/users/12
PUT
Updates user with id = 12.
http://host:port/servletContextPath/users/12
DELETE
Deletes user with id = 12.
Below you can see UserController.java source code:
package org.zmeu.blog.spring.rest.controller;
import java.util.ArrayList;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.zmeu.blog.spring.rest.domain.User;
import org.zmeu.blog.spring.rest.domain.UserList;
import org.zmeu.blog.spring.rest.service.UserService;
@Controller
@RequestMapping(value = "/users")
public class UserController {
private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);
@Autowired
private UserService userService;
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public User create(@RequestBody User user) {
LOGGER.info("Creating new user {}", user);
return userService.create(user);
}
@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
@ResponseBody
public User read(@PathVariable(value = "userId") long userId) {
LOGGER.info("Reading user with id {}", userId);
User user = userService.read(userId);
Validate.isTrue(user != null, "Unable to find user with id: " + userId);
return user;
}
@RequestMapping(value = "/{userId}", method = RequestMethod.PUT)
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void update(@PathVariable(value = "userId") long userId, @RequestBody User user) {
LOGGER.info("Updating user with id {} with {}", userId, user);
Validate.isTrue(userId == user.getId(), "userId doesn't match URL userId: " + user.getId());
userService.update(user);
}
@RequestMapping(value = "/{userId}", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void delete(@PathVariable(value = "userId") long userId) {
LOGGER.info("Deleting user with id {}", userId);
userService.delete(userId);
}
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public UserList list() {
LOGGER.info("Listing users");
return new UserList(new ArrayList<User>(userService.list()));
}
@ExceptionHandler(IllegalArgumentException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public String handleClientErrors(Exception ex) {
LOGGER.error(ex.getMessage(), ex);
return ex.getMessage();
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public String handleServerErrors(Exception ex) {
LOGGER.error(ex.getMessage(), ex);
return ex.getMessage();
}
}
Configure Spring. As you already observed, we used annotations all over, so Spring configuration is minimal (applicationContext.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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="org.zmeu.blog.spring.rest" />
<mvc:annotation-driven />
</beans>
Configure web application. Our web.xml configuration is also minimal. You can see that we only registered the Spring MVC DispatcherServlet and added the Log4jConfigListener for logging.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
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">
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Build the project. From command line, run mvn clean install command from the directory where pom.xml is located. Build must be successful.
Deploy the resulted web application. Run mvn tomcat:run from command line from the same location.
Test and consume RESTful services. Below you can see the class that is testing our RESTful services. I used TestNG testing framework (JUnit can be used as well). Tests that are shown below can be used as an example of how to consume RESTful services. All tests are disabled by default @Test(enabled = false). You have to enable them. This is done in order to skip tests execution at the build time. Tests should be run only after deploying the web application. In order to execute the tests, run mvn test command.
package org.zmeu.blog.spring.rest.controller;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.zmeu.blog.spring.rest.domain.User;
import org.zmeu.blog.spring.rest.domain.UserList;
@Test(enabled = false)
public class UserControllerTest {
private static final String REST_SERVICE_URL = "http://localhost:8080/zmeu-blog-spring-rest/users";
private RestTemplate restTemplate;
@BeforeClass
protected void beforeClass() {
restTemplate = new RestTemplate();
}
public void create() {
createAndAssertUser();
}
public void read() {
User createdUser = createAndAssertUser();
User user = restTemplate.getForObject(REST_SERVICE_URL + "/{userId}", User.class, createdUser.getId());
assertUser(user, createdUser);
}
public void update() {
User user = createAndAssertUser();
user.setName("Updated user name");
restTemplate.put(REST_SERVICE_URL + "/{userId}", user, user.getId());
User updatedUser = restTemplate.getForObject(REST_SERVICE_URL + "/{userId}", User.class, user.getId());
assertUser(updatedUser, user);
}
public void updateIncorrectUrl() {
User user = createAndAssertUser();
user.setName("Updated user name");
try {
restTemplate.put(REST_SERVICE_URL + "/{userId}", user, user.getId() + 1);
fail("Expecting HttpClientErrorException: 400 Bad Request");
} catch (HttpClientErrorException e) {
assertEquals(e.getStatusCode(), HttpStatus.BAD_REQUEST);
}
}
public void delete() {
User createdUser = createAndAssertUser();
restTemplate.delete(REST_SERVICE_URL + "/{userId}", createdUser.getId());
try {
restTemplate.getForObject(REST_SERVICE_URL + "/{userId}", User.class, createdUser.getId());
fail("Expecting HttpClientErrorException: 400 Bad Request");
} catch (HttpClientErrorException e) {
assertEquals(e.getStatusCode(), HttpStatus.BAD_REQUEST);
}
}
public void list() {
UserList initialUsers = restTemplate.getForObject(REST_SERVICE_URL, UserList.class);
User createdUser = createAndAssertUser();
UserList users = restTemplate.getForObject(REST_SERVICE_URL, UserList.class);
List<User> createdUsers = new ArrayList<User>(users.getUsers());
createdUsers.removeAll(initialUsers.getUsers());
assertEquals(createdUsers.size(), 1);
assertUser(createdUsers.get(0), createdUser);
}
private User createAndAssertUser() {
User user = new User();
user.setId(0);
user.setName("User name");
user.setRegistrationDate(new Date());
return createAndAssertUser(user);
}
private User createAndAssertUser(User user) {
User createdUser = restTemplate.postForObject(REST_SERVICE_URL, user, User.class);
assertUserNoId(createdUser, user);
return createdUser;
}
private void assertUserNoId(User actual, User expected) {
assertTrue(actual.getId() > 0);
assertEquals(actual.getName(), expected.getName());
assertEquals(actual.getRegistrationDate(), expected.getRegistrationDate());
}
private void assertUser(User actual, User expected) {
assertTrue(actual.getId() > 0);
assertEquals(actual.getName(), expected.getName());
assertEquals(actual.getRegistrationDate(), expected.getRegistrationDate());
}
}
Testing our RESTful services using web browser:

Retrieve user with id = 12
Retrieve user list Changing the representation of your resources from XML to JSON is very easy. No changes are required to be done in controllers or client side. You have to perform the following actions only: Add the following dependency to pom.xml: <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.8.5</version> <scope>runtime</scope> </dependency> Remove all JAXB annotations from data-type classes (User.java and UserList.java) Taking an arbitrary Java object returned from a controller handler method and converting it into a client-pleasing representation is a job for one of Spring’s HTTP message converters. Spring comes with a variety of message converters: XML, JSON, Atom, RSS, binary, String, etc (see all classes implementing HttpMessageConverter). You are done! IMPORTANT: Although Spring 3 supports validation of arguments and return types for Spring MVC controllers using JSR-303 (Bean validation), it doesn’t work in case of RESTful controllers (see also bugs SPR-6709 and SPR-6928). Also you can have a look at the following related articles: A Comparison of Spring MVC and JAX-RS (from InfoQ). Using Spring 3.0 MVC for RESTful web services (describes some existing issues along with solutions). Spring 3 Type Conversion and Validation (from SpringSource TeamBlog) rest-based services with spring Configure Maven to generate classes from XML Schema using JAXB








Retrieve user with id = 12

Retrieve user list Changing the representation of your resources from XML to JSON is very easy. No changes are required to be done in controllers or client side. You have to perform the following actions only: Add the following dependency to pom.xml: <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.8.5</version> <scope>runtime</scope> </dependency> Remove all JAXB annotations from data-type classes (User.java and UserList.java) Taking an arbitrary Java object returned from a controller handler method and converting it into a client-pleasing representation is a job for one of Spring’s HTTP message converters. Spring comes with a variety of message converters: XML, JSON, Atom, RSS, binary, String, etc (see all classes implementing HttpMessageConverter). You are done! IMPORTANT: Although Spring 3 supports validation of arguments and return types for Spring MVC controllers using JSR-303 (Bean validation), it doesn’t work in case of RESTful controllers (see also bugs SPR-6709 and SPR-6928). Also you can have a look at the following related articles: A Comparison of Spring MVC and JAX-RS (from InfoQ). Using Spring 3.0 MVC for RESTful web services (describes some existing issues along with solutions). Spring 3 Type Conversion and Validation (from SpringSource TeamBlog) rest-based services with spring Configure Maven to generate classes from XML Schema using JAXB
Девственность
Название: Девственность
Жанр: Документальный
Год выпуска: 2009
Производство: Россия
Режиссер: Виталий Манский
Продолжительность: 86 мин.
Закрытый показ (Первый Канал): Девственность (2009) + обсуждение – 154 мин.








How to generate equals(), hashCode(), toString() and compareTo() using Apache Commons Lang in Eclipse
Apache Commons project represents a set of reusable Java components. Apache Commons Lang is one of the Apache Commons components. It provides much needed additions to the standard JDK's java.lang package. One of its packages, org.apache.commons.lang3.builder contains a set of very useful builders that helps in creating consistent equals(), hashCode(), toString() and compareTo() methods.
In this post, I will show how to generate equals(), hashCode(), toString() and compareTo() methods using Apache Commons Lang builders in Eclipse. For demonstrations I will use the latest stable release - Apache Commons Lang 3.0. Note that Lang 3.0 uses a different package (org.apache.commons.lang3) than its predecessors (org.apache.commons.lang). All the examples presented in this post will work also with the previous Apache Commons Lang releases; just change the package name from lang3 to lang.
Native Support
Eclipse supports out of the box generation of equals(), hashCode() and toString() methods. But only the generation of toString() can be configured to use different builders. Below is shown how to configure Eclipse to use ToStringBuilder to generate toString() methods.
Prerequisites: Eclipse project is configured to include Apache Commons Lang jar in classpath. We have a class with 2 fields named string and number.
Open Generate toString() wizard (from menu select Source ->
Generate toString()…). Choose Custom toString() builder option from Code Style drop down and press Configure… button as it is shown below.
Using Browse… button select org.apache.commons.lang3.builder.ToStringBuilder as Builder Class and press OK.
Press OK. Eclipse will generate the toString() method. It should look similar to this one: @Override public String toString() { ToStringBuilder builder = new ToStringBuilder(this); builder.append("string", string); builder.append("number", number); return builder.toString(); } Eclipse will save your settings, so next time you will not have to repeat these steps again. Just open Generate toString() wizard and hit OK. Custom Templates As I mentioned earlier, only toString() generation can be customized in Eclipse. Still, we can configure Eclipse to generate equals(), hashCode() and compareTo() using Apache Commons Lang builders by using Eclipse templates. Templates are little pieces of code with defined placeholders. Each template has a name, which serves as a shortcut to the template itself. You type the name, press CTRL + SPACE and it will be expanded. In order to access Eclipse templates open Window ->
Preferences and select Java ->
Editor ->
Templates. Now you can create new templates, edit existing ones or import directly ready templates.
Following is a list of templates that will allow you to generate equals(), hashCode(), compareTo() and even toString() using Apache Commons Lang builders. hashCode() template @Override public int hashCode() { ${builderType:newType(org.apache.commons.lang3.builder.HashCodeBuilder)} ${builder:newName(builderType)} = new ${builderType}(); ${builder}.append(${field});${cursor} return ${builder}.toHashCode(); } This is how it will look like in Eclipse:
equals() template @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof ${enclosing_type})) { return false; } ${enclosing_type} other = (${enclosing_type}) obj; ${builderType:newType(org.apache.commons.lang3.builder.EqualsBuilder)} ${builder:newName(builderType)} = new ${builderType}(); ${builder}.append(${field}, other.${field});${cursor} return ${builder}.isEquals(); } compareTo() template @Override public int compareTo(${enclosing_type} o) { ${builderType:newType(org.apache.commons.lang3.builder.CompareToBuilder)} ${builder:newName(builderType)} = new ${builderType}(); ${builder}.append(${field}, o.${field});${cursor} return ${builder}.toComparison(); } toString() template @Override public String toString() { ${builderType:newType(org.apache.commons.lang3.builder.ToStringBuilder)} ${builder:newName(builderType)} = new ${builderType}(this, ${:newType(org.apache.commons.lang3.builder.ToStringStyle)}.${DEFAULT_STYLE}); ${builder}.append("${field}", ${field});${cursor} return ${builder}.toString(); } Also you can easily import all the above templates using Import… button from the following file eclipse-templates-apache-commons.xml. After you defined the templates, you can start using them through Content Assist (CTRL + SPACE). Start typing the name of template in editor and then press CTRL + SPACE. Choose the required template and press ENTER.
Customize the variables names and fields that should be included in the builder. Append more fields if it’s required. You have to get at the end something like this: @Override public int hashCode() { HashCodeBuilder builder = new HashCodeBuilder(); builder.append(number); builder.append(string); return builder.toHashCode(); } End.







Generate toString()…). Choose Custom toString() builder option from Code Style drop down and press Configure… button as it is shown below.

Using Browse… button select org.apache.commons.lang3.builder.ToStringBuilder as Builder Class and press OK.

Press OK. Eclipse will generate the toString() method. It should look similar to this one: @Override public String toString() { ToStringBuilder builder = new ToStringBuilder(this); builder.append("string", string); builder.append("number", number); return builder.toString(); } Eclipse will save your settings, so next time you will not have to repeat these steps again. Just open Generate toString() wizard and hit OK. Custom Templates As I mentioned earlier, only toString() generation can be customized in Eclipse. Still, we can configure Eclipse to generate equals(), hashCode() and compareTo() using Apache Commons Lang builders by using Eclipse templates. Templates are little pieces of code with defined placeholders. Each template has a name, which serves as a shortcut to the template itself. You type the name, press CTRL + SPACE and it will be expanded. In order to access Eclipse templates open Window ->
Preferences and select Java ->
Editor ->
Templates. Now you can create new templates, edit existing ones or import directly ready templates.

Following is a list of templates that will allow you to generate equals(), hashCode(), compareTo() and even toString() using Apache Commons Lang builders. hashCode() template @Override public int hashCode() { ${builderType:newType(org.apache.commons.lang3.builder.HashCodeBuilder)} ${builder:newName(builderType)} = new ${builderType}(); ${builder}.append(${field});${cursor} return ${builder}.toHashCode(); } This is how it will look like in Eclipse:

equals() template @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof ${enclosing_type})) { return false; } ${enclosing_type} other = (${enclosing_type}) obj; ${builderType:newType(org.apache.commons.lang3.builder.EqualsBuilder)} ${builder:newName(builderType)} = new ${builderType}(); ${builder}.append(${field}, other.${field});${cursor} return ${builder}.isEquals(); } compareTo() template @Override public int compareTo(${enclosing_type} o) { ${builderType:newType(org.apache.commons.lang3.builder.CompareToBuilder)} ${builder:newName(builderType)} = new ${builderType}(); ${builder}.append(${field}, o.${field});${cursor} return ${builder}.toComparison(); } toString() template @Override public String toString() { ${builderType:newType(org.apache.commons.lang3.builder.ToStringBuilder)} ${builder:newName(builderType)} = new ${builderType}(this, ${:newType(org.apache.commons.lang3.builder.ToStringStyle)}.${DEFAULT_STYLE}); ${builder}.append("${field}", ${field});${cursor} return ${builder}.toString(); } Also you can easily import all the above templates using Import… button from the following file eclipse-templates-apache-commons.xml. After you defined the templates, you can start using them through Content Assist (CTRL + SPACE). Start typing the name of template in editor and then press CTRL + SPACE. Choose the required template and press ENTER.

Customize the variables names and fields that should be included in the builder. Append more fields if it’s required. You have to get at the end something like this: @Override public int hashCode() { HashCodeBuilder builder = new HashCodeBuilder(); builder.append(number); builder.append(string); return builder.toHashCode(); } End.
How to register Infinispan listeners in Spring when using Infinispan as 2LC for Hibernate
In this post I will show how to register Infinispan listeners in Spring when Infinispan is used as second level cache (2LC) for Hibernate. So let’s start:
Annotate your entity classes as cacheable. Pay attention to the cache region name ("cache_name") specified in the region attribute of Cache annotation.
@Entity
@Cache(region = "cache_name", usage = CacheConcurrencyStrategy.TRANSACTIONAL)
@Cacheable
@Table(name = "ENTITY_TABLE")
public class MyEntity implements Serializable {
// entity fields
}
Write your custom InfinispanRegionFactory as it is shown below. It extends from Hibernate InfinispanRegionFactory and its logic is very simple. The only thing which it does is to register listeners after its start. Pay attention to the named cache ("cache_name") to which listeners are registered. It should be the same as the cache region name used by your entities.
public class CustomInfinispanRegionFactory extends InfinispanRegionFactory {
private Set<Object> listeners;
public CustomInfinispanRegionFactory() {
}
public CustomInfinispanRegionFactory(Properties props) {
super(props);
}
public void setListeners(Set<Object> listeners) {
this.listeners = listeners;
}
@Override
public void start(Settings settings, Properties properties) throws CacheException {
super.start(settings, properties);
for(Object listener : listeners) {
// add listener to named cache
getCacheManager().getCache("cache_name").addListener(listener);
// add listener to cache manager
getCacheManager().addListener(listener);
}
}
}
Write your cache Listener. You can find more information about Infinispan listeners here.
@Listener
public class TestCacheListener {
@CacheStarted
public void cacheStarted(Event event) {
System.out.println("Cache started. Details = " + event);
}
@CacheStopped
public void cacheStopped(Event event) {
System.out.println("Cache stopped. Details = " + event);
}
@CacheEntryCreated
@CacheEntryModified
@CacheEntryRemoved
public void handle(Event event) {
System.out.println("Cache entry modified. Details = " + event);
}
}
Configure Hibernate and Infinispan in Spring. Register your listener. You can find more information about using Infinispan as 2LC in Hibernate here.
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="org.zmeu.blog.persistence.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.infinispan.cfg">cache-config.xml</prop>
</props>
</property>
<property name="cacheRegionFactory" ref="cacheRegionFactory"/>
</bean>
<bean id="cacheRegionFactory" class="com.xtrader.persistence.cache.CustomInfinispanRegionFactory">
<property name="listeners">
<set>
<ref bean="listener"/>
</set>
</property>
</bean>
<bean id="listener" class="org.zmeu.blog.persistence.cache.TestCacheListener"/>
Define the named cache ("cache_name") inside Infinispan configuration cache (cache-config.xml).
<namedCache name="cache_name">
<!-- named cache configurations -->
</namedCache>
You are done!
For this example I used: Spring 3.0.5, Hibernate 3.6.5 and Infinispan 4.2.1.







How to extract type arguments from parameterized (generic) class
A nice thing about parameterized classes in Java is that you can extract and access information about class type arguments at runtime (for an explanation about parameters and arguments see Parameters and arguments). Let’s say that we have an abstract parameterized superclass that has a method which provides some common functionality to all its subclasses. And inside that method we wanted to know what is the class type argument specified by the subclass.
public abstract class GenericAbstractSuperclass<T> {
public void foo() {
// here we wanted to know what is the class type argument
}
}
public class GenericClass1 extends GenericAbstractSuperclass<Integer> {
// subclass methods
}
public class GenericClass2 extends GenericAbstractSuperclass<String> {
// subclass methods
}
In above example, method foo() has to access class type argument. In case of GenericClass1 it has to get Integer and in case of GenericClass2 it has to get String. Below is listed a utility class that can accomplish this.
/**
* Generics utility class.
*
* @author Andrei Zagorneanu
* @since 2011-07-31
* @see <a href="http://azagorneanu.blogspot.com">http://azagorneanu.blogspot.com</a>
*/
public class Generics {
private Generics() {
// empty, in order to avoid instantiation
}
public static <T> Class<T> extractTypeArgumentFromClass(Class<?> parameterizedClass)
throws IllegalArgumentException {
return extractTypeArgumentFromClass(parameterizedClass, 0);
}
public static <T> Class<T> extractTypeArgumentFromClass(Class<?> parameterizedClass,
int argumentNumber) throws IllegalArgumentException {
ParameterizedType parameterizedType = extractParameterizedTypeFromClass(parameterizedClass);
if (parameterizedType == null) {
throw new IllegalArgumentException(
"Class and any of its superclasses are not parameterized.");
}
return (Class<T>) getActualTypeArgument(parameterizedType, argumentNumber);
}
private static Type getActualTypeArgument(ParameterizedType parameterizedType,
int argumentNumber) throws IllegalArgumentException {
Type[] typeArguments = parameterizedType.getActualTypeArguments();
if (typeArguments.length == 0) {
throw new IllegalArgumentException("Class is not parameterized.");
}
if (argumentNumber < 0 || typeArguments.length <= argumentNumber) {
throw new IllegalArgumentException("Invalid argumentNumber.");
}
return typeArguments[argumentNumber];
}
public static ParameterizedType extractParameterizedTypeFromClass(Class<?> parameterizedClass) {
Type genericSuperclass = parameterizedClass.getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
return (ParameterizedType) genericSuperclass;
}
if (genericSuperclass != null) {
return extractParameterizedTypeFromClass((Class<?>) genericSuperclass);
}
return null;
}
public static <T> Class<T> extractTypeArgumentFromInterface(Class<?> parameterizedClass)
throws IllegalArgumentException {
return extractTypeArgumentFromInterface(parameterizedClass, 0);
}
public static <T> Class<T> extractTypeArgumentFromInterface(Class<?> parameterizedClass,
int argumentNumber) throws IllegalArgumentException {
ParameterizedType parameterizedType = extractParameterizedTypeFromInterface(parameterizedClass);
if (parameterizedType == null) {
throw new IllegalArgumentException(
"Class and any of its interfaces are not parameterized.");
}
return (Class<T>) getActualTypeArgument(parameterizedType, argumentNumber);
}
private static ParameterizedType extractParameterizedTypeFromInterface(
Class<?> parameterizedClass) {
Type[] genericInterfaces = parameterizedClass.getGenericInterfaces();
for (Type genericInterface : genericInterfaces) {
if (genericInterface instanceof ParameterizedType) {
return (ParameterizedType) genericInterface;
}
ParameterizedType parameterizedType = extractParameterizedTypeFromInterface((Class<?>) genericInterface);
if (parameterizedType != null) {
return parameterizedType;
}
}
return null;
}
}
This class provides methods for extracting type arguments from classes and from interfaces as well. The only use case which is not supported directly is when a class extends from a superclass that implements a parameterized interface. In this case, you will not be able to extract type argument from the class directly. Still, you can extract the class type argument using extractTypeArgumentFromInterface(parameterizedClass.getSuperclass()). Here, we first extracted the superclass and then we used it to extract the type argument from its interface.
Class source code can be found here. Unit tests source code can be found here. Unit tests represent also a good example of class usage.
Update (07-Aug-2011): Recently a new major release of Apache Commons Lang was released - Apache Commons Lang 3.0. Among new utility classes that were added, you will find a new TypeUtils class, which provides utility methods for working with generic types (including retrieval of type arguments from parameterized classes).







java.math.BigDecimal performance
These days I had to do some monetary calculations in Java. This reminded me again about primitive double type and that it is absolutely the worst thing you can use when dealing with money. As you know, primitive double don't necessarily give you the right value, only the value that can be stored in a binary number format (any decimal number is represented by an approximated value). Whilst, java.math.BigDecimal gives you the required precision, its performance is very poor comparable to primitive types.
Below are few simple tests that are measuring BigDecimal performance based on a simple computation x2 + y2 which is performed in a loop 250000 times. In order to exclude the JVM warm-up cost, each test was executed 10 times. The execution time was calculated as average of all executions except first execution (exec2 + exec3 + … + exec10) / 9.
Test BigDecimal computations (execution average time: ~ 767 ms)
BigDecimal bd = null;
for (double x = 0.5; x <= 500; x += 0.5) {
for (double y = 0.5; y <= 500; y += 0.5) {
bd = BigDecimal.valueOf(x).pow(2).add(BigDecimal.valueOf(y).pow(2));
}
}
We got around 0.003 ms per computation. Not bad, but wait to see how fast primitive double is. Next test will show us how much time we spend on creation of BigDecimal objects.
Test BigDecimal constructions (execution average time: ~ 468 ms)
for (double x = 0.5; x <= 500; x += 0.5) {
for (double y = 0.5; y <= 500; y += 0.5) {
BigDecimal.valueOf(x);
BigDecimal.valueOf(y);
}
}
As you can see, only construction of initial operands (x and y) took around 61% of computation time. We can assume that rest 39% are also spent on BigDecimal object creations (results of pow() and add() operations). Knowing that BigDecimal objects are immutable, let’s see how much we can gain by caching BigDecimal instances.
Test BigDecimal computations with cache (execution average time: ~ 309 ms)
BigDecimal bd = null;
for (double x = 0.5; x <= 500; x += 0.5) {
for (double y = 0.5; y <= 500; y += 0.5) {
BigDecimal bigDecimal1 = cache.get(x);
BigDecimal bigDecimal2 = cache.get(y);
bd = bigDecimal1.pow(2).add(bigDecimal2.pow(2));
}
}
Cache was prepared as follows:
Map<Double, BigDecimal> cache = new HashMap<Double, BigDecimal>();
for (double x = 0.5; x <= 500; x += 0.5) {
cache.put(x, BigDecimal.valueOf(x));
}
As you can see, caching BigDecimal gives a performance boost. Now it’s time to see how the primitive double type is performing.
Test double computations (execution average time: ~ 2 ms)
double d = 0.0;
for (double x = 0.5; x <= 500; x += 0.5) {
for (double y = 0.5; y <= 500; y += 0.5) {
d = x * x + y * y;
}
}
Computation speed is great but unfortunately floating point numbers cannot be used for monetary calculations.
Performance Improvement to BigDecimal
Java SE 6 Update 25 made some performance improvements for BigDecimal. Following is the excerpt from Java SE 6 Update 25 Release Notes:
Improvements have been made to class BigDecimal enhancing its performance by thirty percent. BigDecimal is enabled by specifying -XX:+AggressiveOpts command option.
I repeated all the above tests with -XX:+AggressiveOpts option. Below is the table with results:
TestAverage Exec TimePerformance Boost
Normal-XX:+AggressiveOpts
BigDecimal computations767 ms644 ms16%
BigDecimal constructions468 ms394 ms16%
BigDecimal computations with cache309 ms309 ms0%
double computations2 ms--
Results speak themselves, -XX:+AggressiveOpts option gave us 16% performance improvement. It’s not a 30% improvement but still it is something, if we take into account that we just added a JVM option. The most interesting thing is that we got 0% performance improvement for the test which uses cache and the performance improvement of BigDecimal computations test and BigDecimal constructions test are the same. This leads me to think that improvements were made mostly for BigDecimal objects creation.
Regarding BigDecimal I would like also to remind you about:
Never use BigDecimal(double) constructor. The recommended constructor is BigDecimal(String), or in case you want to convert an existing double into a BigDecimal you can use BigDecimal.valueOf(double) static method.
When dividing always specify a RoundingMode. Instead of divide(BigDecimal) use divide(BigDecimal, RoundingMode). This has to be done in order to avoid ArithmeticException. Below is an excerpt from BigDecimal javadoc:
In the case of divide, the exact quotient could have an infinitely long decimal expansion; for example, 1 divided by 3. If the quotient has a nonterminating decimal expansion and the operation is specified to return an exact result, an ArithmeticException is thrown.
At the end, I want to say that for my task I used neither double nor BigDecimal. I used primitive long type and I stored money as cents, pennies (or the equivalent, of course). The choice was done because of performance reasons. I had to do many very simple computations but very often.
Update (05-Aug-2011): Be aware of bug, recently discovered in Java 7 which is also applicable for Java 6 in case when the following JVM options are used: -XX:+OptimizeStringConcat or -XX:+AggressiveOpts. More information here.







Where to store JavaScript and CSS files for Blogger
If you are a Blogger user, then you already know that currently there is no possibility to upload your custom JavaScript and CSS files. You have to host your files somewhere else and then link them in your blog template. One of the places where you can host your custom JavaScript, CSS and any type of files is Google Code. Google Code, is a free platform to host Open Sources Projects.
You can just simply upload your files and hotlink to them. Main issue in this simple task is that it’s working for JavaScript files but it doesn’t work when hot linking to CSS or Image files. The reason is that, by default when we upload any file to Google Code, it is served as text-plain mime-type. This works with JavaScript files but not with CSS, Image files or HTML files.
Below is a small tutorial showing how to create a new project on Google Code, how to use an SVN client to upload new files to it and how to set the mime-type for these files.
Go to http://code.google.com/hosting/ and create a new Google Code project in case you don’t have one already.

Make sure that you have selected Subversion as Version Control system.
Note down your repository URL, username and password. We will need these details in the next steps when we will use an SVN client to upload files to repository.
Install an SVN client. In this example we are using TortoiseSVN. Right click where ever you are working on Windows Explorer and lunch TortoiseSVN Repo-browser.
Enter you repository URL, then username and password (from step no. 3).
Repo-browser lets you browse, add, remove and edit files from your SVN repository.
After you have uploaded the files to repository, you can set their mime-type. Right-click on a file and select Show properties from context-menu.
Using Properties dialog you can add, remove and edit file’s properties.

You are done uploading. Get the file URL by doing left click on the file you want to hot link from the repository browser and select and copy the URL. Just replace the https with http and you are done. Now you have got the URL to hot link. Use it where ever you like.









Make sure that you have selected Subversion as Version Control system.

Note down your repository URL, username and password. We will need these details in the next steps when we will use an SVN client to upload files to repository.

Install an SVN client. In this example we are using TortoiseSVN. Right click where ever you are working on Windows Explorer and lunch TortoiseSVN Repo-browser.

Enter you repository URL, then username and password (from step no. 3).

Repo-browser lets you browse, add, remove and edit files from your SVN repository.

After you have uploaded the files to repository, you can set their mime-type. Right-click on a file and select Show properties from context-menu.

Using Properties dialog you can add, remove and edit file’s properties.


You are done uploading. Get the file URL by doing left click on the file you want to hot link from the repository browser and select and copy the URL. Just replace the https with http and you are done. Now you have got the URL to hot link. Use it where ever you like.

Forex Mind Map
After studying Forex School of Pipsology from http://www.babypips.com/ I made a Forex mind map. It includes Forex Basics section and some topics from Elementary School section.

You can find the mind map here: https://sites.google.com/site/azagorneanu/mm/forex You can browse Forex Mind Map using one of the following:










You can find the mind map here: https://sites.google.com/site/azagorneanu/mm/forex You can browse Forex Mind Map using one of the following:


Java Applet and Java Web Start buttons
I want to say from the beginning that I'm not a designer and I never had such skills, but still I decided to make some buttons for Java Applet and Java Web Start. You can see below what I did:


The Java Coffee Cup logo is a registered trademark of Sun Microsystems, Inc. in the United States and other countries.









The Java Coffee Cup logo is a registered trademark of Sun Microsystems, Inc. in the United States and other countries.
Export FreeMind mind map as Java Applet
FreeMind is a free mind-mapping software written in Java. In this post I will show how to export FreeMind mind maps as Java Applet, describe issues which you can encounter during this process and give some hints on a how to better package exported mind maps.
Let’s start with creating a test mind map. Suppose we have the following mind map:

FreeMind has plenty of options for exporting mind maps. For example the image which you see above was created using Export as PNG option (File -> Export -> As PNG…). Your next question might be: Why to export mind maps as Java Applet if there are so many other options? Here is the answer. Even if FreeMind has many options for exporting mind maps, most of them are not suitable for publishing on the Internet (especially for big mind maps). Starting with FreeMind 0.9.0 two new export options were added: Flash and Java Applet. These two options can be used to bring mind maps into the Internet. The difference between these two is that Java Applet looks exactly like maps on the screen of FreeMind but needs longer to be loaded (This can be fixed by deploying the Java Applet using Java Web Start technology. I will describe how it can be done below.). Flash application is very fast but it has a totally different look and feel and doesn’t support rich formatted text. You can see here how it looks like:
There a two ways for exporting mind maps as Java Applet: Using FreeMind export menu. Go to File -> Export -> As Java Applet… and choose the destination file name, let’s say Test.html. After clicking OK go to the directory where you saved the file. You will see the Test.html file and a Test.html_files directory. Here, there is a small issue, at least in my case. In order to make it work, you have to edit Test.html file and specify the page title. Replace the tag <title/> with <title>Test Mind Map</title>. That’s it, save the file and open it in the browser. Now the applet should start. You will find quickly that images which are used in the mind map itself (inserted using option Insert -> Image…) are not displayed by the applet. This is because images were not exported together with the map. In order to fix this you have to follow the following rules: Store all the images used inside your mind map in one directory (e.g. files or images) which is located in the same directory with mind map file (*.mm). This will ensure that all the paths to images are relative (e.g. files/image1.png). After the export, manually copy the directory with all the images used in your mind map to same location where mind map file (*.mm) resides. In our case Test.html_files. Manually. As you can see from the previous option, there are many manual steps to do in order to make it work. Due to this you can consider to configure the FreeMind Browser Applet manually. This is not complicated at all. You can find preconfigured templates at $FREEMIND_HOME/browse where $FREEMIND_HOME is the home directory of FreeMind. The only thing you have to change is the following line: <param name="browsemode_initial_map" value="./freemind.mm"> Put your mind map file instead of freemind.mm and you are done. Also don’t forget about images. In case you are using images inside your mind map the procedure is the same one as described in previous topic. Now it’s time to deploy the Applet on Internet. First problem which you will encounter trying to deploy the Applet is what to do with the images. It’s not very comfortable to carry all these images one by one and upload them. In order to solve this problem, we can package our mind map file (*.mm) together with all the images as one jar file. Run the following command inside the directory where mind map file is located (we assume that directory with images is located also there): jar –cvf test-mm-freemind.jar * After this, change the HTML applet tag as follows: <applet code="freemind.main.FreeMindApplet.class" width="100%" height="100%" archive="https://sites.google.com/site/azagorneanu/freemind/freemind-browser.jar,https://sites.google.com/site/azagorneanu/mm/test/test-mm-freemind.jar"> <param name="type" value="application/x-java-applet;version=1.4"> <param name="scriptable" value="false"> <param name="modes" value="freemind.modes.browsemode.BrowseMode"> <param name="browsemode_initial_map" value="jar:https://sites.google.com/site/azagorneanu/mm/test/test-mm-freemind.jar!/test.mm"> <param name="initial_mode" value="Browse"> <param name="selection_method" value="selection_method_direct"> <p style="text-align:center;font-weight:bold;text-decoration:underline;"> FreeMind Browser Java Applet. You have to install Java Plug-in in order to see it. </p> </applet> For including an Applet into a Google Sites page you can use Embed Gadget (Insert -> More Gadgets -> Featured -> Embed Gadget) and paste the above snippet into. As I mentioned above it is possible to deploy FreeMind Browser Applet using Java Web Start. This can give you a speed boost in case you are experiencing problems with Applets. Doing this is very easy and requires only the configuration of one XML file with JNLP (Java Network Launching Protocol) extension. Below you can see how test-mm-freemind.jnlp file looks like: <?xml version="1.0" encoding="utf-8"?> <jnlp spec="1.0+" codebase="https://sites.google.com/site/azagorneanu/mm/test/" href="test-mm-freemind.jnlp"> <information> <title>Test FreeMind MindMap</title> <vendor>FreeMind & Andrei Zagorneanu</vendor> <description>Test MindMap by Andrei Zagorneanu</description> <description kind="short"> Test FreeMind MindMap [http://freemind.sourceforge.net/] prepared by Andrei Zagorneanu [http://azagorneanu.blogspot.com/] </description> <homepage href="http://azagorneanu.blogspot.com/"/> <icon href="https://sites.google.com/site/azagorneanu/freemind/freemind-icon.png" width="128" height="128"/> </information> <resources> <j2se version="1.4+" /> <jar href="https://sites.google.com/site/azagorneanu/freemind/freemind-browser.jar" /> <jar href="https://sites.google.com/site/azagorneanu/mm/test/test-mm-freemind.jar" /> </resources> <applet-desc name="FreeMind Browser" width="1200" height="700" main-class="freemind.main.FreeMindApplet"> <param name="type" value="application/x-java-applet;version=1.4" /> <param name="scriptable" value="false" /> <param name="modes" value="freemind.modes.browsemode.BrowseMode" /> <param name="browsemode_initial_map" value="jar:https://sites.google.com/site/azagorneanu/mm/test/test-mm-freemind.jar!/test.mm" /> <param name="initial_mode" value="Browse" /> <param name="selection_method" value="selection_method_direct" /> </applet-desc> </jnlp> Next, this file has to be uploaded along with other jar files and then used inside a link (anchor) as follows: <a href="/site/azagorneanu/mm/test/test-mm-freemind.jnlp">Browse using Java Web Start</a> After clicking on link, choose Open option or save the file to your computer and then open it. The FreeMind browser should start. Here https://sites.google.com/site/azagorneanu/mm/test you can find deployed both versions (Applet and Java Web Start) of our Test mind map. You can browse Test Mind Map using one of the following:

Make sure that you have installed Java Plug-in for your browser. In case your browser is 32-bit (x86) you have to install a version of Java also for 32-bit. For example for Firefox 4 you have to install a 32-bit version of Java. For a 64-bit browser you will need a 64-bit java. You can download latest java from http://java.com/.








FreeMind has plenty of options for exporting mind maps. For example the image which you see above was created using Export as PNG option (File -> Export -> As PNG…). Your next question might be: Why to export mind maps as Java Applet if there are so many other options? Here is the answer. Even if FreeMind has many options for exporting mind maps, most of them are not suitable for publishing on the Internet (especially for big mind maps). Starting with FreeMind 0.9.0 two new export options were added: Flash and Java Applet. These two options can be used to bring mind maps into the Internet. The difference between these two is that Java Applet looks exactly like maps on the screen of FreeMind but needs longer to be loaded (This can be fixed by deploying the Java Applet using Java Web Start technology. I will describe how it can be done below.). Flash application is very fast but it has a totally different look and feel and doesn’t support rich formatted text. You can see here how it looks like:

There a two ways for exporting mind maps as Java Applet: Using FreeMind export menu. Go to File -> Export -> As Java Applet… and choose the destination file name, let’s say Test.html. After clicking OK go to the directory where you saved the file. You will see the Test.html file and a Test.html_files directory. Here, there is a small issue, at least in my case. In order to make it work, you have to edit Test.html file and specify the page title. Replace the tag <title/> with <title>Test Mind Map</title>. That’s it, save the file and open it in the browser. Now the applet should start. You will find quickly that images which are used in the mind map itself (inserted using option Insert -> Image…) are not displayed by the applet. This is because images were not exported together with the map. In order to fix this you have to follow the following rules: Store all the images used inside your mind map in one directory (e.g. files or images) which is located in the same directory with mind map file (*.mm). This will ensure that all the paths to images are relative (e.g. files/image1.png). After the export, manually copy the directory with all the images used in your mind map to same location where mind map file (*.mm) resides. In our case Test.html_files. Manually. As you can see from the previous option, there are many manual steps to do in order to make it work. Due to this you can consider to configure the FreeMind Browser Applet manually. This is not complicated at all. You can find preconfigured templates at $FREEMIND_HOME/browse where $FREEMIND_HOME is the home directory of FreeMind. The only thing you have to change is the following line: <param name="browsemode_initial_map" value="./freemind.mm"> Put your mind map file instead of freemind.mm and you are done. Also don’t forget about images. In case you are using images inside your mind map the procedure is the same one as described in previous topic. Now it’s time to deploy the Applet on Internet. First problem which you will encounter trying to deploy the Applet is what to do with the images. It’s not very comfortable to carry all these images one by one and upload them. In order to solve this problem, we can package our mind map file (*.mm) together with all the images as one jar file. Run the following command inside the directory where mind map file is located (we assume that directory with images is located also there): jar –cvf test-mm-freemind.jar * After this, change the HTML applet tag as follows: <applet code="freemind.main.FreeMindApplet.class" width="100%" height="100%" archive="https://sites.google.com/site/azagorneanu/freemind/freemind-browser.jar,https://sites.google.com/site/azagorneanu/mm/test/test-mm-freemind.jar"> <param name="type" value="application/x-java-applet;version=1.4"> <param name="scriptable" value="false"> <param name="modes" value="freemind.modes.browsemode.BrowseMode"> <param name="browsemode_initial_map" value="jar:https://sites.google.com/site/azagorneanu/mm/test/test-mm-freemind.jar!/test.mm"> <param name="initial_mode" value="Browse"> <param name="selection_method" value="selection_method_direct"> <p style="text-align:center;font-weight:bold;text-decoration:underline;"> FreeMind Browser Java Applet. You have to install Java Plug-in in order to see it. </p> </applet> For including an Applet into a Google Sites page you can use Embed Gadget (Insert -> More Gadgets -> Featured -> Embed Gadget) and paste the above snippet into. As I mentioned above it is possible to deploy FreeMind Browser Applet using Java Web Start. This can give you a speed boost in case you are experiencing problems with Applets. Doing this is very easy and requires only the configuration of one XML file with JNLP (Java Network Launching Protocol) extension. Below you can see how test-mm-freemind.jnlp file looks like: <?xml version="1.0" encoding="utf-8"?> <jnlp spec="1.0+" codebase="https://sites.google.com/site/azagorneanu/mm/test/" href="test-mm-freemind.jnlp"> <information> <title>Test FreeMind MindMap</title> <vendor>FreeMind & Andrei Zagorneanu</vendor> <description>Test MindMap by Andrei Zagorneanu</description> <description kind="short"> Test FreeMind MindMap [http://freemind.sourceforge.net/] prepared by Andrei Zagorneanu [http://azagorneanu.blogspot.com/] </description> <homepage href="http://azagorneanu.blogspot.com/"/> <icon href="https://sites.google.com/site/azagorneanu/freemind/freemind-icon.png" width="128" height="128"/> </information> <resources> <j2se version="1.4+" /> <jar href="https://sites.google.com/site/azagorneanu/freemind/freemind-browser.jar" /> <jar href="https://sites.google.com/site/azagorneanu/mm/test/test-mm-freemind.jar" /> </resources> <applet-desc name="FreeMind Browser" width="1200" height="700" main-class="freemind.main.FreeMindApplet"> <param name="type" value="application/x-java-applet;version=1.4" /> <param name="scriptable" value="false" /> <param name="modes" value="freemind.modes.browsemode.BrowseMode" /> <param name="browsemode_initial_map" value="jar:https://sites.google.com/site/azagorneanu/mm/test/test-mm-freemind.jar!/test.mm" /> <param name="initial_mode" value="Browse" /> <param name="selection_method" value="selection_method_direct" /> </applet-desc> </jnlp> Next, this file has to be uploaded along with other jar files and then used inside a link (anchor) as follows: <a href="/site/azagorneanu/mm/test/test-mm-freemind.jnlp">Browse using Java Web Start</a> After clicking on link, choose Open option or save the file to your computer and then open it. The FreeMind browser should start. Here https://sites.google.com/site/azagorneanu/mm/test you can find deployed both versions (Applet and Java Web Start) of our Test mind map. You can browse Test Mind Map using one of the following:


Make sure that you have installed Java Plug-in for your browser. In case your browser is 32-bit (x86) you have to install a version of Java also for 32-bit. For example for Firefox 4 you have to install a 32-bit version of Java. For a 64-bit browser you will need a 64-bit java. You can download latest java from http://java.com/.
Generat în 0.829 secunde. Thumbnail Screenshots by Thumbshots


