Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Now, that the schema/namespaces are declared, we can start to create beans reference or import resources add addtional stuffs like import resources, beans reference, ... that our routing engine will use.

...

We will use the CXF framework to deploy the reportincident webservice and run it into the OSGI platform.

To work with it, resources (= spring beans) declared in CXF project must be imported using the command statement import resource.

Code Block
...
 <import resource="classpath:META-INF/cxf/cxf.xml" />
 <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
 <import resource="classpath:META-INF/cxf/cxf-extension-http.xml" />
 <import resource="classpath:META-INF/cxf/osgi/cxf-extension-osgi.xml" /> 
...

...

Remark : for the purpose of this tutorial, we have packaged this configuration into the camel-spring file but it could be defined in a separate xml file with by example the component /endpoint bean that Camel will use to communicate with CXF bus. This allows you to separate routing from parameters to be provided to configure endpoints.

The camel CXF endpoint is configurated like this :

Code Block

...
	<!-- webservice endpoint --> 
	<cxf:cxfEndpoint id="reportIncident"
		address="/camel-example/incident" (1)
		serviceClass="org.apache.camel.example.reportincident.ReportIncidentEndpoint" (2)
		xmlns:s="http://reportincident.example.camel.apache.org"> (3)
	</cxf:cxfEndpoint>
...

Remarks :
(1) - the address corresponds to the URI address of the web services,
(2) - the serviceClass is the name of the class used work with the webservices and deployed in the bundle reportincident.webservice
(3) - xmlns:s is the namespace of the reportincident webservice (see reportincident.webservice)

2) Queueing Queuing engine

No matter if the incidents come from a webservice or a files , but before to process and save them in the database, we will put
our messages in the queue of a queue manager. The queue manager used here is ActiveMQ.
Like CXF, we will use spring xml file to deploy ActiveMq into the server and configure it. This will be done in two steps

...

Like CXF, ActiveMq can be installed in the infrastructure using a spring.xml configuration file. So, create the file }} activemq-broker.xml in the directory {{src/main/resources/META-INF/spring and add the following lines.

Code Block

<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:amq="http://activemq.apache.org/schema/core"
  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-2.5.xsd
       http://activemq.apache.org/schema/core
       http://activemq.apache.org/schema/core/activemq-core.xsd
       http://camel.apache.org/schema/spring
       http://camel.apache.org/schema/spring/camel-spring.xsd
       http://www.springframework.org/schema/osgi
       http://www.springframework.org/schema/osgi/spring-osgi.xsd">

    <!-- Allows us to use system properties as variables in this configuration file -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>

    <broker xmlns="http://activemq.apache.org/schema/core" brokerName="default" dataDirectory="${servicemix.base}/data/activemq/default" useShutdownHook="false">

        <!-- Destination specific policies using destination names or wildcards -->
        <destinationPolicy>
            <policyMap>
                <policyEntries>
                    <policyEntry queue=">" memoryLimit="5mb"/>
                    <policyEntry topic=">" memoryLimit="5mb">
                        <subscriptionRecoveryPolicy>
                            <lastImageSubscriptionRecoveryPolicy/>
                        </subscriptionRecoveryPolicy>
                    </policyEntry>
                </policyEntries>
            </policyMap>
        </destinationPolicy>

        <!-- Use the following to configure how ActiveMQ is exposed in JMX -->
        <managementContext>
            <managementContext createConnector="false"/>
        </managementContext>

        <!-- The store and forward broker networks ActiveMQ will listen to -->
        <networkConnectors>
            <!-- by default just auto discover the other brokers -->
            <networkConnector name="default-nc" uri="multicast://default"/>
            <!-- Example of a static configuration:
            <networkConnector name="host1 and host2" uri="static://(tcp://host1:61616,tcp://host2:61616)"/>
            -->
        </networkConnectors>

        <persistenceAdapter>
            <amqPersistenceAdapter syncOnWrite="false" directory="${servicemix.base}/data/activemq/default" maxFileLength="20 mb"/>
        </persistenceAdapter>

        <!-- Use the following if you wish to configure the journal with JDBC -->
        <!--
        <persistenceAdapter>
            <journaledJDBC dataDirectory="${activemq.base}/data" dataSource="#postgres-ds"/>
        </persistenceAdapter>
        -->

        <!-- Or if you want to use pure JDBC without a journal -->
        <!--
        <persistenceAdapter>
            <jdbcPersistenceAdapter dataSource="#postgres-ds"/>
        </persistenceAdapter>
        -->

        <!--  The maximum about of space the broker will use before slowing down producers -->
        <systemUsage>
            <systemUsage>
                <memoryUsage>
                    <memoryUsage limit="20 mb"/>
                </memoryUsage>
                <storeUsage>
                    <storeUsage limit="1 gb" name="foo"/>
                </storeUsage>
                <tempUsage>
                    <tempUsage limit="100 mb"/>
                </tempUsage>
            </systemUsage>
        </systemUsage>


        <!-- The transport connectors ActiveMQ will listen to -->
        <transportConnectors>
            <transportConnector name="openwire" uri="tcp://localhost:61616" discoveryUri="multicast://default"/>
            <transportConnector name="stomp" uri="stomp://localhost:61613"/>
        </transportConnectors>

    </broker>

    <bean id="activemqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:61616" />
    </bean>

    <bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactoryBean">
        <property name="maxConnections" value="8" />
        <property name="maximumActive" value="500" />
        <property name="transactionManager" ref="transactionManager" />
        <property name="connectionFactory" ref="activemqConnectionFactory" />
        <property name="resourceName" value="activemq.default" />
    </bean>

    <bean id="resourceManager" class="org.apache.activemq.pool.ActiveMQResourceManager" init-method="recoverResource">
          <property name="transactionManager" ref="transactionManager" />
          <property name="connectionFactory" ref="activemqConnectionFactory" />
          <property name="resourceName" value="activemq.default" />
    </bean>

    <osgi:reference id="transactionManager" interface="javax.transaction.TransactionManager" />

    <osgi:service ref="pooledConnectionFactory">
        <osgi:interfaces>
            <value>javax.jms.ConnectionFactory</value>
        </osgi:interfaces>
        <osgi:service-properties>
            <entry key="name" value="default"/>
        </osgi:service-properties>
    </osgi:service>

</beans>

At the bundle startup, Spring will instantiate the beans declared and in consequence start the queueing queuing engine. We haven't changed the content of the file corresponding to what is proposed in the ServiceMix distribution but you can use here the same technic technique described for the Datasource and add properties that you configure through by example a org.apache.activemq.config.etc file.

Code Block

    ...
    <transportConnectors>
        <transportConnector name="${name}" uri="${uri}" discoveryUri="${discoveryUri}"/>
    </transportConnectors>
    
    <!-- here is the list of values defined as default but can be overidded in the file org.apache.activemq.config.etc -->
    <osgix:cm-properties id="confs" persistent-id="org.apache.activemq.config.etc">
        <prop key="name">openwire</prop>
        <prop key="uri">tcp://localhost:61616</prop>
        <prop key="discoveryUri">multicast://default</prop>
    </osgix:cm-properties>
    ...
Tip

The activeMq broker can also be integrated differently because the ServiceMix4 distribution (and not ServiceMix Kernel) proposes it in standard with additional commands that you can use from the console to :

Available commands in activemq:
browse Display selected messages in a specified destination
bstat Displays useful broker statistics
create-broker Creates a broker instance.
destroy-broker Destroys a broker instance.
list Lists all available brokers in the specified JMX context
purge Delete selected destination's messages that matches the message selector
query Display selected broker component's attributes and statistics

The pom.xml file must be modified to add properties required by Spring blueprint. So add the following lines :

Code Block

...
    <instructions>
      <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
      <DynamicImport-Package>*</DynamicImport-Package>
      <Include-Resource>src/main/resources</Include-Resource> (1)
      <Spring-Context>*;publish-context:=false;create-asynchronously:=true</Spring-Context> (2)
      <Private-Package></Private-Package>
      <Import-Package> (3)
	javax.transaction,
	org.apache.activemq,
        org.apache.activemq.pool,
	org.springframework.beans.factory.config,
	*
       </Import-Package>
    </instructions>
...

Remarks :
(1) - Include-Resource will allow to add to the jar generated the spring files of the directory src/main/resources/META-INF/spring
(2) - The Spring-Context tag allows to provide specific information used by Spring blueprint service to load the application context and how to load it. The asterisk means that all the spring xml files will be processed
(3) - The list of classes to be used is dependent of the queue engine use as implementation. This list must be reviewed when switching from ActiveMq to IBM WebSphere MQ, Tibco, ...

b) Camel ActiveMq component

...

First, create a spring DSL file osgi-queuingservice.xml in the directory {{src/main/resources/META-INF-spring}}directory containing the following information :

...

(2) Our camel component will be exposed on the OSGI registry as an org.apache.camel.Component and has a reference to the ActiveMQComponent, JMSComponent

Adapt Next adapt the POM.xml file like this to instruct the felix plugin how to generate the MANIFEST.MF file

Code Block

...
			<plugin>
				<groupId>org.apache.felix</groupId>
				<artifactId>maven-bundle-plugin</artifactId>
				<version>${felix-version}</version>
				<configuration>
					<manifestLocation>META-INF</manifestLocation>
					<instructions>
						<Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
						<Import-Package>
						    org.apache.activemq.camel.component,
						    org.apache.camel,
						    *</Import-Package>
					    <Include-Resource>src/main/resources</Include-Resource>
					    <Spring-Context>*;publish-context:=false;create-asynchronously:=true</Spring-Context>
					    <Private-Package></Private-Package>
					</instructions>
				</configuration>
			</plugin>
...

Remark that we import here the org.apache.activemq.camel.component class and not the ActiveMQComponent java class.

All the infrastructure is in place, so we can start to describe the beans that we will use

3) Beans reference

4) Routing

...