Camel and Wicket Playing Together
Every day, just when you think you've achieved your client's integration, the client’s system crashes and you have no idea why. What do you do?
Join the DZone community and get the full member experience.
Join For Freeimagine this scenario: you're responsible for integrating your company’s system with an old system from one of your clients. every day, just when you think you've achieved it, the client’s system crashes and you have no idea why. you are so disappointed that you don’t even want to get a drink with your friends anymore — you just want to stay home thinking of ways to solve the problem. well, that was my story...until i found apache camel and apache wicket.
apache camel is a lightweight integration framework. sometimes, the facing problem is not just about integration, but about showing the user results as well.
apache wicket is a web component-based framework on which you can write web pages very easily using only java and html.
in this article, i will show you how i used these two amazing tools to solve my problem, get my life back on track, and start drinking beer again. really. they're that good.
getting started
to start, i'll use maven to manage the dependencies.
creating an application in wicket using maven is pretty easy. i just needed to find the correct archetype ( this page helps a lot), and i was ready. running this command will create a new project for me, and i can import it into my favorite ide as a maven project:
mvn archetype:generate -darchetypegroupid=org.apache.wicket -darchetypeartifactid=wicket-archetype-quickstart -darchetypeversion=8.0.0-m2 -dgroupid=com.avenuecode -dartifactid=wicket-camel -darchetyperepository=https://repository.apache.org/ -dinteractivemode=false
i selected the options following this picture:
this step could take a while since it will download some dependencies.
to test the recently created application, i ran the
com.avenuecode.start
class as a java application and access
http://localhost:8080
in my browser. the result was:
ok, i have a web application working! now, it’s time to integrate it with camel.
integrating wicket and camel
to use the best of the two frameworks, i’ll need a third and well-known framework: spring. wicket came with its own spring version, but i faced some compatibility issues here, so i just excluded these dependencies and used a compatible version. in this example, using wicket version 8.0.0-m2 and camel version 2.16.0, i’ll use spring version 4.3.3.release.
adding spring dependency and removing the spring itself in
pom.xml
(i need this dependency because wicket contains specific code for spring, we just need another version):
<dependencies>
...
<!-- integrate wicket with spring -->
<dependency>
<groupid>org.apache.wicket</groupid>
<artifactid>wicket-spring</artifactid>
<version>${wicket.version}</version>
<exclusions>
<exclusion>
<groupid>org.springframework</groupid>
<artifactid>spring</artifactid>
</exclusion>
</exclusions>
</dependency>
...
</dependencies>
add the dependencies for spring:
<dependencies>
...
<!-- spring framework -->
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-core</artifactid>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-context</artifactid>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-web</artifactid>
<version>${spring.version}</version>
</dependency>
...
</dependencies>
camel dependencies:
<dependencies>
...
<!-- camel -->
<dependency>
<groupid>org.apache.camel</groupid>
<artifactid>camel-core</artifactid>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupid>org.apache.camel</groupid>
<artifactid>camel-spring</artifactid>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupid>org.apache.camel</groupid>
<artifactid>camel-http</artifactid>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupid>org.apache.camel</groupid>
<artifactid>camel-tagsoup</artifactid>
<version>${camel.version}</version>
</dependency>
...
</dependencies>
to better organize our
pom.xml
, we’ll add these properties:
<properties>
...
<camel.version>2.16.0</camel.version>
<spring.version>4.3.3.release</spring.version>
...
</properties>
saving
pom.xml
will organize the dependencies in the ide.
in case this doesn’t happen automatically, you should update the project inside the ide.
a good way to see if it's working is to run the
com.avenuecode.start
class again and access
http://localhost:8080
. i saw the same page, so i’m good.
configuring spring
the dependencies are fine, but i needed to do a few more steps to really use spring in wicket.
first, i needed to create the file
applicationcontext.xml
in
web-inf
folder. this is what it looks like:
the content for
applicationcontext.xml
is something like this:
<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-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:component-scan base-package="com.avenuecode.bean" />
</beans>
i needed to add this content to
web.xml
, as well:
<web-app>
...
<!-- the springwebapplicationfactory will need access to a spring application
context, configured like this... -->
<context-param>
<param-name>contextconfiglocation</param-name>
<param-value>/web-inf/applicationcontext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.contextloaderlistener</listener-class>
</listener>
...
</web-app>
the last step is to “turn on” spring in our wicket application, adding this line in
init()
method in
com.avenuecode.wicketapplication
:
public void init() {
super.init();
...
getcomponentinstantiationlisteners().add(new springcomponentinjector(this));
...
}
now, how can i tell if it’s working? as i added com.avenuecode.bean in the component-scan, spring will search in this package for spring beans. so i can create one bean to test it:
package com.avenuecode.bean;
import org.springframework.stereotype.component;
@component
public class hellobean {
public string gethello() {
return "hello, spring!";
}
}
and then change the
com.avenuecode.homepage
to use this bean:
package com.avenuecode;
import org.apache.wicket.markup.html.webpage;
import org.apache.wicket.markup.html.basic.label;
import org.apache.wicket.request.mapper.parameter.pageparameters;
import org.apache.wicket.spring.injection.annot.springbean;
import com.avenuecode.bean.hellobean;
public class homepage extends webpage {
private static final long serialversionuid = 1l;
@springbean
private hellobean hellobean;
public homepage(final pageparameters parameters) {
super(parameters);
add(new label("version", hellobean.gethello()));
// todo add your page's components here
}
}
note that
hellobean
is annotated with
@springbean
. this is the annotation that wicket uses to use the beans in spring.
now let’s check back and see if it’s working. i ran the
com.avenuecode.start
, and looked at the bottom of the page. it’s showing
"hello, spring!"
instead of the wicket version, and spring and wicket are working well together!
ok, wicket and spring are running. now, what about camel?
to set up camel, i needed to add a
camel-context.xml
file in the same folder as
applicationcontext.xml
,
web-inf
. in this file, i’ll tell camel where the folder is to scan that contains the routes to execute. here is an example:
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring-2.15.2.xsd">
<camelcontext xmlns="http://camel.apache.org/schema/spring">
<packagescan>
<package>com.avenuecode.route</package>
</packagescan>
</camelcontext>
</beans>
to configure camel in spring, i just added
<import resource="camel-context.xml" />
into
applicationcontext.xml
.
<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-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<import resource="camel-context.xml" />
<context:component-scan base-package="com.avenuecode.bean" />
</beans>
to see everything working (at least to see it working on the console), i also changed the root level from
warn
to
info
inside
log4j2.xml
, like this:
...
<root level="info">
<appenderref ref="console"/>
</root>
...
the last step was to create a camel route to move from a specific directory to another one.
package com.avenuecode.route;
import org.apache.camel.builder.routebuilder;
public class fileroutebuilder extends routebuilder {
@override
public void configure() throws exception {
from("file:src/data")
.log("message received!")
.to("file:target/messages");
}
}
running
com.avenuecode.start
again, i could see camel in action. then, i moved a file to the directory
src/data
. the file was moved to
target/messages
, and the console displayed the message: "message received!"
file in
src/data
folder:
the file should be moved to
target/messages
:
and the console:
time to solve the problem!
the problem is pretty similar to what i did before now. the system receives a file in an ftp server and needs to move it to a local folder to be processed. but to make it easier to show, i’ll continue working with local folders, using
src/in
and
target/out
. i’ll create another route to process this file, and store the status in memory so i can show it.
to store the status, i can simply create a spring bean:
package com.avenuecode.bean;
import org.springframework.stereotype.component;
@component
public class filestatus {
private string status = "undefined";
public void ok() {
this.status = "ok";
}
public void error() {
this.status = "error";
}
public string getstatus() {
return status;
}
public void setstatus(string status) {
this.status = status;
}
}
and the route:
package com.avenuecode.route;
import org.apache.camel.exchange;
import org.apache.camel.processor;
import org.apache.camel.builder.routebuilder;
import org.springframework.beans.factory.annotation.autowired;
import com.avenuecode.bean.filestatus;
public class processfileroutebuilder extends routebuilder {
@autowired
private filestatus filestatus;
@override
public void configure() throws exception {
from("file:src/in").process(new processor() {
@override
public void process(exchange exchange) throws exception {
string message = exchange.getin().getbody(string.class);
if (message.tolowercase().contains("error")) {
filestatus.error();
} else {
filestatus.ok();
}
}
}).log("message processed!").to("file:target/out");
}
}
running
com.avenuecode.start
showed in the console what’s happened. if i put a file inside
data/in
, it will show “message processed!” and the status will be changed in memory. but i can’t show the console to the user, right?
creating a page to show the status of the route
i used our initial page, just changing some code in
com.avenuecode.homepage
:
package com.avenuecode;
import org.apache.wicket.markup.html.webpage;
import org.apache.wicket.markup.html.basic.label;
import org.apache.wicket.request.mapper.parameter.pageparameters;
import org.apache.wicket.spring.injection.annot.springbean;
import com.avenuecode.bean.filestatus;
public class homepage extends webpage {
private static final long serialversionuid = 1l;
@springbean
private filestatus filestatus;
public homepage(final pageparameters parameters) {
super(parameters);
add(new label("status", filestatus.getstatus()));
}
}
and the
homepage.html
file:
<!doctype html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<title>integration status</title>
</head>
<body>
<h1>integration status</h1>
<table border="1">
<tr>
<th>integration</th>
<th>status</th>
</tr>
<tr>
<td>system x in folder "src/in"</td>
<td><label wicket:id="status"/></td>
</tr>
</table>
</body>
</html>
showing the results
running
com.avenuecode.start
and accessing
http://localhost:8080
showed this page:
the status
undefined
is because the system hasn't processed any files yet. i can create an example file, called
file1.txt
with random content and move to
src/in
, and access
http://localhost:8080
again.
after moving to
src/in
, i can check the status. the file was received successfully and i didn't have any errors!
creating a
file2.txt
with some error content, i could check the whole power of the integration!
and now i can check if there are any errors in the integration whenever i want!
conclusion
it didn't take much effort to integrate camel and wicket. it’s a simple integration with fantastic results! try it yourself! this was just one example, but hopefully, it conveyed an idea of just how useful these tools can be.
the code used here is available on github for further reference. enjoy!
Published at DZone with permission of Luis Felipe Volpato Alves. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Auditing Tools for Kubernetes
-
Logging Best Practices Revisited [Video]
-
Effortlessly Streamlining Test-Driven Development and CI Testing for Kafka Developers
-
What Is Test Pyramid: Getting Started With Test Automation Pyramid
Comments