Servlet — provides support for HTTP endpoints that are published as servlets
The servlet: component provides HTTP-based endpoints for consuming HTTP requests that arrive at a HTTP endpoint, and this endpoint is bound to a published Servlet.
![]() | Important |
---|---|
You can only consume from endpoints generated by the Servlet component. Therefore, it should only be used as input into your Apache Camel routes. To issue HTTP requests against other HTTP endpoints, use the HTTP component. |
The URI format of a Servlet endpoint is:
servlet://relative_path
[?options
]
You can append query options to the URI in the following format,
?option=value&option=value&...
Maven users will need to add the following dependency to their
pom.xml
for this component:
Example 8. Adding the servlet dependency
<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>
Table 31, “Servlet endpoint options” lists the options for a Servlet endpoint.
Table 31. Servlet endpoint options
Name | Default | Description |
---|---|---|
httpBindingRef
| null | Specifies a reference to an
org.apache.camel.component.http.HttpBinding in the
registry. You can use an HttpBinding implementation to
customize how to write a response. |
matchOnUriPrefix
|
false
| Specifies whether the CamelServlet should try to find a
target consumer by matching the URI prefix when no exact match is
found. |
servletName
| null | Specifies the servlet name that the endpoint will bind to. If no servlet name is specified, the endpoint binds to the first published Servlet. |
Apache Camel applies the same Message Headers as the HTTP component.
Apache Camel also populates 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.
If you put the Camel JARs such as camel-core
,
camel-servlet
, etc. in the boot classpath of
your application server (eg usually in its lib directory), then mind
that the servlet mapping list is now shared between multiple
deployed Camel application in the app server.
Mind that putting Camel JARs in the boot classpath of the application server is generally not best practice!
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>
From Apache Camel 2.11 onwards Camel will detect this duplicate and fail to start the application. You can control to ignore this duplicate by setting the servlet init-parameter ignoreDuplicateServletName to true as follows:
<servlet> <servlet-name>CamelServlet</servlet-name> <display-name>Camel Http Transport Servlet</display-name> <servlet-class>org.apache.camel.component.servlet.CamelHttpTransportServlet</servlet-class> <init-param> <param-name>ignoreDuplicateServletName</param-name> <param-value>true</param-value> </init-param> </servlet>
But its strongly advised to use unique servlet-name for each Camel application to avoid this duplication clash, as well any unforeseen side-effects.
![]() | Important |
---|---|
From Apache Camel 2.7 onwards its easier to use Servlet in Spring web applications. See Servlet Tomcat Example for details. |
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:///hello?matchOnUriPrefix=true").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_URI, String.class); path = path.substring(path.lastIndexOf("/")); assertEquals("Get a wrong content type", CONTENT_TYPE, contentType); // assert camel http header String charsetEncoding = exchange.getIn().getHeader(Exchange.HTTP_CHARACTER_ENCODING, String.class); assertEquals("Get a wrong charset name from the message heaer", "UTF-8", charsetEncoding); // assert exchange charset 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>"); } });
![]() | Note |
---|---|
Since we are binding the Http transport with a published
servlet, and we don't know the servlet's application context
path, the |
The standalone Apache Camel package contains a demonstration of how to
deploy the Servlet component in the Tomcat Web container. The
demonstration is located in the
examples/camel-example-servlet-tomcat
directory.
When deploying a Servlet component in the Web container, it is
necessary to create a Spring application context explicitly by
creating a Spring ContextLoaderListener
instance
in the WEB-INF/web.xml
file.
For example, to create a Spring application context that loads
Spring definitions (including the camelContext
and
route definitions) from the camel-config.xml
file,
define a web.xml
file as follows:
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>My Web Application</display-name> <!-- location of spring xml files --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:camel-config.xml</param-value> </context-param> <!-- the listener that kick-starts Spring --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Camel servlet --> <servlet> <servlet-name>CamelServlet</servlet-name> <servlet-class>org.apache.camel.component.servlet.CamelHttpTransportServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Camel servlet mapping --> <servlet-mapping> <servlet-name>CamelServlet</servlet-name> <url-pattern>/camel/*</url-pattern> </servlet-mapping> </web-app>
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>
From Apache 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> <!-- notice how we can use the servlet scheme which is that osgi:reference above --> <from uri="servlet:///hello"/> <process ref="servletProcessor"/> </route> </camelContext> </beans>
Alternatively - pre 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) { // create a default context to share between registrations final HttpContext httpContext = httpService.createDefaultHttpContext(); // register the hello world servlet final Dictionary<String, String> initParams = new Hashtable<String, String>(); initParams.put("matchOnUriPrefix", "false"); initParams.put("servlet-name", "CamelServlet"); httpService.registerServlet("/camel/services", // alias new CamelHttpTransportServlet(), // register servlet initParams, // init params httpContext // http context ); registerService = true; } } } public void setBundleContext(BundleContext bc) { try { registerServlet(bc); } catch (Exception e) { LOG.error("Cannot register the servlet, the reason is " + e); } } }