Servlet Component
The servlet: component provides HTTP based endpoints for consuming HTTP requests that arrive at a HTTP endpoint that is bound to a published Servlet.
Maven users will need to add the following dependency to their pom.xml for this component:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-servlet</artifactId>
<version>x.x.x</version>
<\!-\- use the same version as your Camel core version \-->
</dependency>
![]() | Stream Servlet is stream based, which means the input it receives is submitted to Camel as a stream. That means you will only be able to read the content of the stream once. If you find a situation where the message body appears to be empty or you need to access the data multiple times (eg: doing multicasting, or redelivery error handling) you should use Stream caching or convert the message body to a String which is safe to be read multiple times. |
URI format
You can append query options to the URI in the following format, ?option=value&option=value&...
Options
Name |
Default Value |
Description |
httpBindingRef |
null |
Reference to an org.apache.camel.component.http.HttpBinding in the Registry. A HttpBinding implementation can be used to customize how to write a response. |
matchOnUriPrefix |
false |
Whether or not the CamelServlet should try to find a target consumer by matching the URI prefix, if no exact match is found. |
servletName |
CamelServlet |
Specifies the servlet name that the servlet endpoint will bind to. This name should match the name you define in web.xml file. |
Message Headers
Camel will apply the same Message Headers as the HTTP component.
Camel will also populate all request.parameter and request.headers. For example, if a client request has the URL, http://myserver/myserver?orderid=123, the exchange will contain a header named orderid with the value 123.
Usage
You can consume only from endpoints generated by the Servlet component. Therefore, it should be used only as input into your Camel routes. To issue HTTP requests against other HTTP endpoints, use the HTTP Component
Using multiple Camel applications in the same servlet container
If you use multiple Camel applications in the same servlet container, then there will be an issue when using the default servlet name, as it would not be able to properly differentiate between multiple Camel applications.
So in those situations you must define a custom and unique servlet name in each of your Camel application, eg in the web.xml define:
<servlet>
<servlet-name>MySerlvet</servlet-name>
<servlet-class>org.apache.camel.component.servlet.CamelHttpTransportServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
And in your Camel endpoints then include the servlet name as well
<route>
<from uri="servlet://foo?servletName=MyServlet"/>
...
</route>
Sample
In this sample, we define a route that exposes a HTTP service at http://localhost:8080/camel/services/hello.
First, you need to publish the CamelHttpTransportServlet through the normal Web Container, or OSGi Service.
Use the Web.xml file to publish the CamelHttpTransportServlet as follows:
<web-app>
<servlet>
<servlet-name>CamelServlet</servlet-name>
<display-name>Camel Http Transport Servlet</display-name>
<servlet-class>org.apache.camel.component.servlet.CamelHttpTransportServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CamelServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
Then you can define your route as follows:
from("servlet:).process(new Processor() {
public void process(Exchange exchange) throws Exception {
String contentType = exchange.getIn().getHeader(Exchange.CONTENT_TYPE, String.class);
String path = exchange.getIn().getHeader(Exchange.HTTP_PATH, String.class);
assertEquals("Get a wrong content type", CONTENT_TYPE, contentType);
String charsetEncoding = exchange.getIn().getHeader(Exchange.HTTP_CHARACTER_ENCODING, String.class);
assertEquals("Get a wrong charset name from the message heaer", "UTF-8", charsetEncoding);
assertEquals("Get a wrong charset naem from the exchange property", "UTF-8", exchange.getProperty(Exchange.CHARSET_NAME));
exchange.getOut().setHeader(Exchange.CONTENT_TYPE, contentType + "; charset=UTF-8");
exchange.getOut().setHeader("PATH", path);
exchange.getOut().setBody("<b>Hello World</b>");
}
});
![]() | Specify the relative path for camel-servlet endpoint Since we are binding the Http transport with a published servlet, and we don't know the servlet's application context path, the camel-servlet endpoint uses the relative path to specify the endpoint's URL. A client can access the camel-servlet endpoint through the servlet publish address: ("http://localhost:8080/camel/services") + RELATIVE_PATH("/hello"). |
Sample when using Spring 3.x
See Servlet Tomcat Example
Sample when using Spring 2.x
When using the Servlet component in a Camel/Spring application it's often required to load the Spring ApplicationContext after the Servlet component has started. This can be accomplished by using Spring's ContextLoaderServlet instead of ContextLoaderListener. In that case you'll need to start ContextLoaderServlet after CamelHttpTransportServlet like this:
<web-app>
<servlet>
<servlet-name>CamelServlet</servlet-name>
<servlet-class>
org.apache.camel.component.servlet.CamelHttpTransportServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>SpringApplicationContext</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<web-app>
Sample when using OSGi
From Camel 2.6.0, you can publish the CamelHttpTransportServlet as an OSGi service with help of SpringDM like this.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<bean id="camelServlet" class="org.apache.camel.component.servlet.CamelHttpTransportServlet">
</bean>
<!--
Enlist it in OSGi service registry
This will cause two things:
1) As the pax web whiteboard extender is running the CamelServlet will
be registered with the OSGi HTTP Service
2) It will trigger the HttpRegistry in other bundles so the servlet is
made known there too
-->
<osgi:service ref="camelServlet">
<osgi:interfaces>
<value>javax.servlet.Servlet</value>
<value>org.apache.camel.component.http.CamelServlet</value>
</osgi:interfaces>
<osgi:service-properties>
<entry key="alias" value="/camel/services" />
<entry key="matchOnUriPrefix" value="true" />
<entry key="servlet-name" value="CamelServlet"/>
</osgi:service-properties>
</osgi:service>
</beans>
Then use this service in your camel route like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<osgi:reference id="servletref" interface="org.apache.camel.component.http.CamelServlet">
<osgi:listener bind-method="register" unbind-method="unregister">
<ref bean="httpRegistry"/>
</osgi:listener>
</osgi:reference>
<bean id="httpRegistry" class="org.apache.camel.component.servlet.DefaultHttpRegistry"/>
<bean id="servlet" class="org.apache.camel.component.servlet.ServletComponent">
<property name="httpRegistry" ref="httpRegistry" />
</bean>
<bean id="servletProcessor" class="org.apache.camel.itest.osgi.servlet.ServletProcessor" />
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="servlet:///hello"/>
<process ref="servletProcessor"/>
</route>
</camelContext>
</beans>
For versions prior to Camel 2.6 you can use an Activator to publish the CamelHttpTransportServlet on the OSGi platform
import java.util.Dictionary;
import java.util.Hashtable;
import org.apache.camel.component.servlet.CamelHttpTransportServlet;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.osgi.context.BundleContextAware;
public final class ServletActivator implements BundleActivator, BundleContextAware {
private static final transient Logger LOG = LoggerFactory.getLogger(ServletActivator.class);
private static boolean registerService;
/**
* HttpService reference.
*/
private ServiceReference httpServiceRef;
/**
* Called when the OSGi framework starts our bundle
*/
public void start(BundleContext bc) throws Exception {
registerServlet(bc);
}
/**
* Called when the OSGi framework stops our bundle
*/
public void stop(BundleContext bc) throws Exception {
if (httpServiceRef != null) {
bc.ungetService(httpServiceRef);
httpServiceRef = null;
}
}
protected void registerServlet(BundleContext bundleContext) throws Exception {
httpServiceRef = bundleContext.getServiceReference(HttpService.class.getName());
if (httpServiceRef != null && !registerService) {
LOG.info("Register the servlet service");
final HttpService httpService = (HttpService)bundleContext.getService(httpServiceRef);
if (httpService != null) {
final HttpContext httpContext = httpService.createDefaultHttpContext();
final Dictionary<String, String> initParams = new Hashtable<String, String>();
initParams.put("matchOnUriPrefix", "false");
initParams.put("servlet-name", "CamelServlet");
httpService.registerServlet("/camel/services", new CamelHttpTransportServlet(), initParams, httpContext );
registerService = true;
}
}
}
public void setBundleContext(BundleContext bc) {
try {
registerServlet(bc);
} catch (Exception e) {
LOG.error("Cannot register the servlet, the reason is " + e);
}
}
}
See Also