301.7. 例
Camel 2.7 以降では、Spring Web アプリケーションで サーブレット を使用する方が簡単です。詳細は、サーブレット Tomcat の例 を参照してください。
このサンプルでは、http://localhost:8080/camel/services/hello で HTTP サービスを公開するルートを定義します。
最初に、通常の Web コンテナーまたは OSGi サービスを介して CamelHttpTransportServlet を公開する必要があります。Web.xml
ファイルを使用して、次のように CamelHttpTransportServlet を公開します。
<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>
次に、次のようにルートを定義できます。
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>"); } });
camel-servlet エンドポイントの相対パスを指定する
HTTP トランスポートを公開されたサーブレットにバインドしていて、サーブレットのアプリケーションコンテキストパスがわからないため、camel-servlet
エンドポイントは相対パスを使用してエンドポイントの URL を指定します。クライアントは、サーブレット公開アドレス ("http://localhost:8080/camel/services") + RELATIVE_PATH("/hello") を介して
、camel-servlet
エンドポイントにアクセスできます。
301.7.1. Spring 3.x 使用時のサンプル
サーブレット Tomcat の例 を参照してください。
301.7.2. Spring 2.x 使用時のサンプル
Camel/Spring アプリケーションで Servlet コンポーネントを使用する場合、多くの場合、Servlet コンポーネントの開始 後に Spring ApplicationContext をロードする必要があります。これは、ContextLoaderListener
の代わりに Spring の ContextLoaderServlet
を使用することで実現できます。その場合、次のように CamelHttpTransportServlet の後に ContextLoaderServlet
を開始する必要があります。
<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>
301.7.3. OSGi 使用時のサンプル
Camel 2.6.0 から、次のように Blueprint を使用して CamelHttpTransportServlet を OSGi サービスとして公開できます。
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> <bean id="camelServlet" class="org.apache.camel.component.servlet.CamelHttpTransportServlet" /> <!-- 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 --> <service ref="camelServlet"> <interfaces> <value>javax.servlet.Servlet</value> <value>org.apache.camel.http.common.CamelServlet</value> </interfaces> <service-properties> <entry key="alias" value="/camel/services" /> <entry key="matchOnUriPrefix" value="true" /> <entry key="servlet-name" value="CamelServlet" /> </service-properties> </service> </blueprint>
次に、このサービスを Camel ルートで次のように使用します。
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> <reference id="servletref" ext:proxy-method="classes" interface="org.apache.camel.http.common.CamelServlet"> <reference-listener ref="httpRegistry" bind-method="register" unbind-method="unregister" /> </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.example.servlet.ServletProcessor" /> <camelContext xmlns="http://camel.apache.org/schema/blueprint"> <route> <!-- Notice how we can use the servlet scheme which is that reference above --> <from uri="servlet://hello" /> <process ref="servletProcessor" /> </route> </camelContext> </blueprint>
Camel 2.6 より前のバージョンでは、Activator
を使用して、OSGi プラットフォームで CamelHttpTransportServlet を公開できます。
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 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); } } }
301.7.4. Spring-Boot での使用
Camel 2.19.0 以降、camel-servlet-starter ライブラリーは /camel/*
コンテキストパスの下のすべての残りのエンドポイントを自動的にバインドします。次の表は、camel-servlet-starter ライブラリーで使用できる追加の設定プロパティーをまとめたものです。Camel サーブレットの自動マッピングも無効にすることができます。
Spring-Boot プロパティー | デフォルト | 説明 |
---|---|---|
camel.component.servlet.mapping.enabled |
| サーブレットコンポーネントの Spring Web コンテキストへの自動マッピングを有効にします |
camel.component.servlet.mapping.context-path |
| 自動マッピングのためにサーブレットコンポーネントによって使用されるコンテキストパス |
camel.component.servlet.mapping.servlet-name |
| Camel サーブレットの名前 |