[Wildfly-Camel] XML to DB Data Conversion Small Tutorial

December 15, 2014

wildfly Camel

In one of my previous posts[1], I explain how you can install Apache Camel[2] on top of Wildfly[3].

In that small tutorial, I am not going to reinvent the wheel. I am just going to explain how you can transform/convert data stored in XML format and upload it to a database of your choice  – In this example H2[4] was the chosen default database -.

Note: H2 is not recommended to be used in production. I would rather recommend you to look at  postgresq[5], MongoDB[6], MariaDB[7], etc… instead.

This example named “camel-jpa”  is coming from the ones provided with the wildfly-camel project[8]

First of all here is the tree of that project :


[fhornain@localhost camel-jpa]$ tree
.
├── pom.xml
└── src
├── main
│   ├── java
│   │   └── org
│   │       └── wildfly
│   │           └── camel
│   │               └── examples
│   │                   └── jpa
│   │                       ├── CustomerRepository.java
│   │                       ├── JpaRouteBuilder.java
│   │                       ├── model
│   │                       │   ├── Customer.java
│   │                       │   └── package-info.java
│   │                       ├── Resources.java
│   │                       └── SimpleServlet.java
│   ├── resources
│   │   ├── META-INF
│   │   │   └── persistence.xml
│   │   └── org
│   │       └── wildfly
│   │           └── camel
│   │               └── examples
│   │                   └── jpa
│   │                       └── model
│   │                           └── jaxb.index
│   └── webapp
│       └── WEB-INF
│           ├── beans.xml
│           ├── customers.jsp
│           ├── customer.xml
│           └── jboss-web.xml
└── test
└── java
└── org
└── wildfly
└── camel
└── examples
└── jpa
└── JPAIntegrationTest.java

26 directories, 14 files

And here is the pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
 #%L
 Wildfly Camel :: Example :: Camel JPA
 %%
 Copyright (C) 2013 - 2014 RedHat
 %%
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 
 http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 #L%
 -->


<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/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <parent>
 <groupId>org.wildfly.camel</groupId>
 <artifactId>wildfly-camel-example</artifactId>
 <version>2.0.0.CR1</version>
 </parent>

 <name>Wildfly Camel :: Example :: Camel JPA</name>

 <artifactId>example-camel-jpa</artifactId>
 <packaging>war</packaging>

 <dependencies>

 <!-- Provided -->
 <dependency>
 <groupId>org.apache.camel</groupId>
 <artifactId>camel-core</artifactId>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>org.apache.camel</groupId>
 <artifactId>camel-cdi</artifactId>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>org.apache.camel</groupId>
 <artifactId>camel-jpa</artifactId>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>org.apache.camel</groupId>
 <artifactId>camel-jaxb</artifactId>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>javax.enterprise</groupId>
 <artifactId>cdi-api</artifactId>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>org.hibernate.javax.persistence</groupId>
 <artifactId>hibernate-jpa-2.1-api</artifactId>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>org.jboss.spec.javax.servlet</groupId>
 <artifactId>jboss-servlet-api_3.1_spec</artifactId>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>org.jboss.spec.javax.ejb</groupId>
 <artifactId>jboss-ejb-api_3.2_spec</artifactId>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>org.jboss.spec.javax.transaction</groupId>
 <artifactId>jboss-transaction-api_1.1_spec</artifactId>
 <scope>provided</scope>
 </dependency>

 <!-- Test Scope -->
 <dependency>
 <groupId>org.wildfly.camel</groupId>
 <artifactId>example-camel-common</artifactId>
 <version>${project.version}</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.jboss.arquillian.junit</groupId>
 <artifactId>arquillian-junit-container</artifactId>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.wildfly</groupId>
 <artifactId>wildfly-arquillian-container-remote</artifactId>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-simple</artifactId>
 <scope>test</scope>
 </dependency>
 </dependencies>

 <!-- Build -->
 <build>
 <plugins>
 <plugin>
 <groupId>org.wildfly.plugins</groupId>
 <artifactId>wildfly-maven-plugin</artifactId>
 <executions>
 <execution>
 <id>wildfly-deploy</id>
 <phase>integration-test</phase>
 <goals>
 <goal>deploy</goal>
 </goals>
 </execution>
 </executions>
 </plugin>
 </plugins>
 </build>

 <!-- Profiles -->
 <profiles>
 <profile>
 <id>ts.all</id>
 <activation>
 <property>
 <name>ts.all</name>
 </property>
 </activation>
 <properties>
 <jboss.home>${basedir}/../target/wildfly-${version.wildfly}</jboss.home>
 </properties>
 </profile>
 </profiles>
</project>

As you can see the project in based on a MVC pattern and is composed of four directories but for the time being we will only cover three of them.
That is to say :

- camel-jpa/src/main/java
- camel-jpa/src/main/resources
- camel-jpa/src/main/webapp

Indeed, the project can be then cut in two parts.

The first part which is taking care of the content routing and the transformation of information of the following XML data sample.


<?xml version="1.0" encoding="UTF-8"?>
<cus:customer xmlns:cus="http://org/wildfly/camel/examples/jpa/model/Customer"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://org/wildfly/camel/examples/jpa/model/Customer">
<cus:firstName>John</cus:firstName>
<cus:lastName>Doe</cus:lastName>
<cus:dateOfBirth>1975-12-25</cus:dateOfBirth>
</cus:customer>

Note : You can retrieve these data in the camel-jpa/src/main/webapp/WEB-INF/customer.xml xml file.
The Second part which transcribes the content of the database in a web page.  – See below – We will call it the servlet[12] part.

Note: This outcome can be found at http://localhost:8080/example-camel-jpa/customers

Screenshot from 2014-12-15 13:37:35

 

 

 


First part of the Project (Content routing and transformation of information)

Here the idea is to unmarshall[11] or deserialize the content of the XML file through Camel Route (Here implemented in the JpaRouteBuilder.java) to an Entity Bean (here in Customer.java) which will then persisted to the H2 Database.

In the camel-jpa/src/java you have got : JpaRouteBuilder.java which is where the Camel route is going to be implemented.


/*
* #%L
* Wildfly Camel :: Example :: Camel JPA
* %%
* Copyright (C) 2013 - 2014 RedHat
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package org.wildfly.camel.examples.jpa;

import javax.ejb.Startup;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.transaction.UserTransaction;

import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.cdi.ContextName;
import org.apache.camel.component.jpa.JpaEndpoint;
import org.apache.camel.model.dataformat.JaxbDataFormat;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.wildfly.camel.examples.jpa.model.Customer;

@Startup
@ApplicationScoped
@ContextName("jpa-cdi-context")
public class JpaRouteBuilder extends RouteBuilder {

@Inject
private EntityManager em;

@Inject
UserTransaction userTransaction;

@Override
public void configure() throws Exception {

// Configure our JaxbDataFormat to point at our 'model' package
JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
jaxbDataFormat.setContextPath(Customer.class.getPackage().getName());

EntityManagerFactory entityManagerFactory = em.getEntityManagerFactory();

// Configure a JtaTransactionManager by looking up the JBoss transaction manager from JNDI
JtaTransactionManager transactionManager = new JtaTransactionManager();
transactionManager.setUserTransaction(userTransaction);
transactionManager.afterPropertiesSet();

// Configure the JPA endpoint to use the correct EntityManagerFactory and JtaTransactionManager
JpaEndpoint jpaEndpoint = new JpaEndpoint();
jpaEndpoint.setCamelContext(getContext());
jpaEndpoint.setEntityType(Customer.class);
jpaEndpoint.setEntityManagerFactory(entityManagerFactory);
jpaEndpoint.setTransactionManager(transactionManager);

/*
* Simple route to consume customer record files from directory input/customers,
* unmarshall XML file content to a Customer entity and then use the JPA endpoint
* to persist the it to the 'ExampleDS' datasource (see standalone.camel.xml for datasource config).
*/
from("file://{{jboss.server.data.dir}}/customers")
.unmarshal(jaxbDataFormat)
.to(jpaEndpoint)
.to("log:input?showAll=true");
}
}

In addition to that, We will use JaxbDataFormat to point at our 'model' package in camel-jpa/src/main/java/org/wildfly/camel/examples/jpa/model/package-info.java


@javax.xml.bind.annotation.XmlSchema(namespace = "http://org/wildfly/camel/examples/jpa/model/Customer", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.wildfly.camel.examples.jpa.model;


 

Second part of the Project

In that part of that project,  the idea is to transcribes the content of the database in a web page through a Servlet[12].

In the camel-jpa/src/java you have got : CustomerRepository.java which is only there to send back customer information from the Database to the Servlet SimpleServlet.java


/*
 * #%L
 * Wildfly Camel :: Example :: Camel JPA
 * %%
 * Copyright (C) 2013 - 2014 RedHat
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package org.wildfly.camel.examples.jpa;

import java.util.List;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;

import org.wildfly.camel.examples.jpa.model.Customer;

public class CustomerRepository {
    
    @Inject
    private EntityManager em;

    /**
     * Find all customer records
     *
     * @return A list of customers
     */
    public List<Customer> findAllCustomers() {

        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
        CriteriaQuery<Customer> query = criteriaBuilder.createQuery(Customer.class);
        query.select(query.from(Customer.class));

        return em.createQuery(query).getResultList();
    }
}</pre>
<pre>

Entity Manager which is going to use details defined in your camel-jpa/src/main/resources/META-INF/persistence.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!--
#%L
Wildfly Camel :: Example :: Camel JPA
%%
Copyright (C) 2013 - 2014 RedHat
%%
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
#L%
-->
<persistence version="2.0"
 xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
 http://java.sun.com/xml/ns/persistence
 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
 <persistence-unit name="camel">
 <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
 <class>org.wildfly.camel.examples.jpa.model.Customer</class>
 <properties>
 <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
 <property name="hibernate.show_sql" value="true"/>
 </properties>
 </persistence-unit>
</persistence>

Note : ExampleDS should be the default datasource set in your Wildfly instance. – see for instance your /wildfly-8.1.0.Final/standalone/configuration/standalone-camel.xml configuration file in your wildfly instance with the additional Camel Patches[1]

Finally here is the Servlet [12] implementation  : SimpleServlet.java:

/*
 * #%L
 * Wildfly Camel :: Example :: Camel JPA
 * %%
 * Copyright (C) 2013 - 2014 RedHat
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package org.wildfly.camel.examples.jpa;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

import javax.inject.Inject;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.wildfly.camel.examples.jpa.model.Customer;

@SuppressWarnings("serial")
@WebServlet(name = "HttpServiceServlet", urlPatterns = { "/customers/*" }, loadOnStartup = 1)
public class SimpleServlet extends HttpServlet {

    static Path CUSTOMERS_PATH = new File(System.getProperty("jboss.server.data.dir")).toPath().resolve("customers");
    
    @Inject
    private CustomerRepository customerRepository;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);

        // Copy WEB-INF/customer.xml to the data dir
        ServletContext servletContext = config.getServletContext();
        try {
            InputStream input = servletContext.getResourceAsStream("/WEB-INF/customer.xml");
            Path xmlPath = CUSTOMERS_PATH.resolve("customer.xml");
            Files.copy(input, xmlPath);
        } catch (IOException ex) {
            throw new ServletException(ex);
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
         * Simple servlet to retrieve all customers from the in memory database for
         * output and display on customers.jsp
         */

        List<Customer> customers = customerRepository.findAllCustomers();

        request.setAttribute("customers", customers);
        request.getRequestDispatcher("/WEB-INF/customers.jsp").forward(request, response);
    }
}

Object which will be called by the camel-jpa/src/main/webapp/WEB-INF/customers.jsp JSP file when you will access to the following URL  : http://localhost:8080/example-camel-jpa/customers

<%--
 #%L
 Wildfly Camel :: Example :: Camel JPA
 %%
 Copyright (C) 2013 - 2014 RedHat
 %%
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 #L%
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:forEach var="customer" items="${customers}">
 ${customer.firstName} ${customer.lastName}
</c:forEach>

Now up, you can compile you code using the following command at the root of your project /camel-jpa :


[fhornain@localhost camel-jpa]$ mvn clean package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Wildfly Camel :: Example :: Camel JPA 2.0.0.CR1
[INFO] ------------------------------------------------------------------------
[INFO]
.......................
.......................
.......................
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.491s
[INFO] Finished at: Mon Dec 15 15:10:01 CET 2014
[INFO] Final Memory: 36M/333M
[INFO] ------------------------------------------------------------------------

and then deploy your code to your wildfly instance[1] with its additional camel patches.


[fhornain@localhost target]$ pwd
/camel-jpa/target
[fhornain@localhost target]$ cp -pR example-camel-jpa-2.0.0.CR1.war /wildfly-8.1.0.Final/standalone/deployments/

Then, you can play with the example.

You should have a customer directory in /wildfly-8.1.0.Final/standalone/data

Directory

 

 

 

 

 

 

Do a copy/paste of the the camel-jpa/src/main/webapp/WEB-INF/customer.xml xml file in that directory /wildfly-8.1.0.Final/standalone/data.


[fhornain@localhost WEB-INF]$ pwd

/camel-jpa/src/main/webapp/WEB-INF

[fhornain@localhost WEB-INF]$ cp -pR customer.xml /wildfly-8.1.0.Final/standalone/data/customers

You should now see an additional customer in the following web page : http://localhost:8080/example-camel-jpa/customers

New Web screenshot

N.B. if you are looking for certified and supported enterprise solutions please consider Red Hat JBoss EAP[8] or Red Hat JBoss Fuse[9]

Kind Regards

Frederic

[1] https://fhornain.wordpress.com/2014/12/14/wildfly-extras-wildfly-and-apache-camel/

[2] https://camel.apache.org/

[3] http://wildfly.org/

[4] http://www.h2database.com/html/main.html

[5] http://www.postgresql.org/

[6] http://www.mongodb.org/

[7] https://mariadb.org/

[8] https://github.com/wildfly-extras/wildfly-camel

[9] http://www.redhat.com/en/technologies/jboss-middleware/application-platform

[10] http://www.redhat.com/en/technologies/jboss-middleware/fuse

[11] http://en.wikipedia.org/wiki/Marshalling_%28computer_science%29

[12] http://en.wikipedia.org/wiki/Java_Servlet

 

 

 

 

 

 

 

 

 

 

 

Leave a comment