Hello Community, I apologize for the long post upon list entry, but I thought this might be interesting.
I was working on a use case that involves running Camel inside an OSGi Container and for configuration I am using Apache Aries 1.0.0. As i have a HTTP Service already running and need to support HTTP posts, I figured using the servlet component would make sense. This having said, trying to use the configuration found here (http://camel.apache.org/servlet.html) doesn't work out of the box. The main reason seems to be that CamelServlet is a class rather than an interface, so it can't be registered as an OSGi service easily. Googling around indicated that using the attribute "ext:classes" on the blueprint reference should do the trick, but I got errors from Blueprint not being able to create the service proxy. I stepped back and tried to understand what *should* happen and came up with a solution / workaround that I thought was worth sharing. 1. I need to gain access to the CamelServlet by OSGI means. 2. I need to stick a HTTP Registry into that servlet. 3. I need to define an endpoint that wires the Registry and the Servlet together. First, I have defined an Interface CamelServletProvider that has merely one method: public interface CamelServletProvider { public CamelServlet getCamelServlet(); } with an associated implementation: public class CamelServletProviderImpl implements CamelServletProvider { private CamelServlet camelServlet = null; public void setCamelServlet(CamelServlet camelServlet) { this.camelServlet = camelServlet; } @Override public CamelServlet getCamelServlet() { return camelServlet; } } The idea for this class is, that it lives alongside the CamelServlet and a CamelServletProvider is registered as an OSGi Service like this: <?xml version="1.0" encoding="UTF-8" standalone="no"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" "> <bean id="camelServlet" class="org.apache.camel.component.servlet.CamelHttpTransportServlet" /> <bean id="servletProvider" class="de.woq.camel.sib.servlet.internal.CamelServletProviderImpl"> <property name="camelServlet" ref="camelServlet" /> </bean> <service ref="camelServlet" interface="javax.servlet.Servlet" > <service-properties> <entry key="alias" value="/camel/services" /> <entry key="matchOnUriPrefix" value="true" /> <entry key="servlet-name" value="CamelServlet"/> <entry key="osgi.web.contextpath" value="/camel/services" /> </service-properties> </service> <service ref="servletProvider" interface="de.woq.camel.sib.servlet.CamelServletProvider"> <service-properties> <entry key="servlet-name" value="CamelServlet"/> </service-properties> </service> </blueprint> Now we have a bundle that exposes a Camel Servlet as HTTP transport which I can use in endpoints to come in another bundle. To make this work I need a HTTP Registry, that I can stick into Blueprint and that reacts to CamelServletProviders coming and going. The DefaultHTTPRegistry in Camel reacts to javax.servlet.Servlet. I have simply cloned the DefaultHTTPRegistry and made it react to CamelServletProviders: public class CamelServletHTTPRegistry implements HttpRegistry { private static final transient Logger LOG = LoggerFactory.getLogger( CamelServletHTTPRegistry.class); private static HttpRegistry singleton; private final Set<HttpConsumer> consumers; private final Set<CamelServlet> providers; public CamelServletHTTPRegistry() { consumers = new HashSet<HttpConsumer>(); providers = new HashSet<CamelServlet>(); } /** * Lookup or create a HttpRegistry */ public static synchronized HttpRegistry getSingletonHttpRegistry() { if (singleton == null) { singleton = new CamelServletHTTPRegistry(); } return singleton; } @Override public void register(HttpConsumer consumer) { LOG.debug("Registering consumer for path {} providers present: {}", consumer.getPath(), providers.size()); consumers.add(consumer); for (CamelServlet provider : providers) { provider.connect(consumer); } } @Override public void unregister(HttpConsumer consumer) { LOG.debug("Unregistering consumer for path {} ", consumer.getPath()); consumers.remove(consumer); for (CamelServlet provider : providers) { provider.disconnect(consumer); } } @SuppressWarnings("rawtypes") public void register(CamelServletProvider provider, Map properties) { LOG.info("Registering provider through OSGi service listener {}", properties); try { CamelServlet camelServlet = provider.getCamelServlet(); camelServlet.setServletName((String) properties.get("servlet-name")); register(camelServlet); } catch (ClassCastException cce) { LOG.info("Provider is not a Camel Servlet"); } } public void unregister(CamelServletProvider provider, Map<String, Object> properties) { LOG.info("Deregistering provider through OSGi service listener {}", properties); try { CamelServlet camelServlet = provider.getCamelServlet(); unregister((CamelServlet)provider); } catch (ClassCastException cce) { LOG.info("Provider is not a Camel Servlet"); } } @Override public void register(CamelServlet provider) { LOG.debug("Registering CamelServlet with name {} consumers present: {}", provider.getServletName(), consumers.size()); providers.add(provider); for (HttpConsumer consumer : consumers) { provider.connect(consumer); } } @Override public void unregister(CamelServlet provider) { providers.remove(provider); } public void setServlets(List<Servlet> servlets) { providers.clear(); for (Servlet servlet : servlets) { if (servlet instanceof CamelServlet) { providers.add((CamelServlet) servlet); } } } } The trick here is in the register / unregister method reacting to the CamelServletProvider interface. Now I was able to stick all of that together in a bundle configuration: <?xml version="1.0" encoding="UTF-8" standalone="no"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:camel="http://camel.apache.org/schema/blueprint" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint-2.10.3.xsd "> <!-- Get an instance of the registry --> <bean id="httpRegistry" class="de.woq.camel.sib.http.CamelServletHTTPRegistry" /> <!-- Get hold of the Servlet Provider by its interface and servlet name --> <reference interface="de.woq.camel.sib.servlet.CamelServletProvider" filter="(servlet-name=CamelServlet)" timeout="1000"> <reference-listener ref="httpRegistry" bind-method="register" unbind-method="unregister" /> </reference> <!-- Create the servlet component --> <bean id="servlet" class="org.apache.camel.component.servlet.ServletComponent"> <property name="httpRegistry" ref="httpRegistry" /> </bean> <camel:camelContext> <!-- Just convenience to stick file into a directory and have them posted to a URL. --> <!-- /camel/services was the root context of my transport service above --> <camel:route> <camel:from uri="file:///tmp/woq-in" /> <camel:to uri="http://localhost:8080/camel/services/test" /> </camel:route> <!-- The actual route --> <camel:route> <!-- Three /// are important, otherwise the endpoint will be registered with path "/" --> <camel:from uri="servlet:///test" /> <camel:to uri="file:///tmp/woq-out" /> </camel:route> </camel:camelContext> </blueprint> If you think this is usefull, I am happy to stick it in the wiki rather than in the user's list. Best regards Andreas Andreas Gies WoQ Way of Quality UG Geschäftsführer & CTO eMail: andr...@wayofquality.de Tel DE: +49 151 23470823 Tel UK: +44 755 1381918 Fax: +49 1805 006534 2114 Amtsgericht Landshut: HRB 8352 Ust.-Id.: DE274771254 Haftungsausschluss Diese Email kann vertrauliche und/oder rechtlich geschützte Informationen enthalten und ist ausschließlich für den/die benannten Adressaten bestimmt. Sollten Sie nicht der beabsichtigte Empfänger sein oder diese Email irrtümlich erhalten haben, ist es Ihnen nicht gestattet diese Mail oder einen Teil davon ohne unsere Erlaubnis zu verbreiten, zu kopieren, unbefugt weiterzuleiten oder zu behalten. Informieren Sie bitte sofort den Absender telefonisch oder per Email und löschen Sie diese Email und alle Kopien aus Ihrem System. Wir haften nicht für die Unversehrtheit von Emails, nachdem sie unseren Einflussbereich verlassen haben. Disclaimer This email may contain confidential and/or privileged information and is intended solely for the attention and use of the named addressee(s). If you are not the intended recipient, or a person responsible for delivering it to the intended recipient, you are not authorized to and must not disclose, copy, distribute, or retain this message or any part of it without our authority. Please contact the sender by call or reply email immediately and destroy all copies and the original message. We are not responsible for the integrity of emails after they have left our sphere of control.