Wednesday, July 13, 2016

What is OSGI EE ? (22/250-2016)

OSGI EE - provides support for

  • JPA
  • JNDI
  • WEB (HTTP)
  • JTA
  • JDBC
  • CDI and 
  • EJB
  • This is implemented by Apache ARIES project
  • And OPS4J PAX - OPS4J
What is an OSGI EE Container - 
  • OSGI Services (Java Interfaces)
  • JPA, JTA OSGI Contianer
  • Web OSGI Container
  • Blueprint (IOC) to configure services, beans and access services
  • JNDI Wrapper
  • SPIFly  - http://aries.apache.org/modules/spi-fly.html

What is Karaf ? (21/250-2016)

Karaf - Birthdate - 16th of June 2010

● Platform running on OSGI (Apache Felix, Eclipse Equinox)

● Provides a lightweight container where

  • Applications, 
  • Integration projects
  • Web Service, 
  • JMS Brokers
  • Java applications can be deployed

● Used by JBoss Fuse, ServiceMix, Geronimo projects

Karaf consists of components




What is OSGI (20/250 - 2016)

OSGi (Open Service Gateway Initiative) -  * Java Framework / Develop modular software programs and libraries
Part 1 - * Specification for modular components - bundles / plug-ins
Part 2 - * JVM level registry - that bundles can use to publish / * discover and bind to services in a SOA.

Modularity
* Total control over library versions and dependencies- different versions of the same library will happliy co-exist in the same container.
* Quick Hot Deployment - restart / refresh operations
* Fully inspect - what packages and versions are used.
* Deploy exactly the modules and framework that is needed and no more
References:
* http://stackoverflow.com/questions/7490166/osgi-benefits-over-java-ee
* http://bit.ly/29E6uye - 

Thursday, June 16, 2016

How to increase heap size in JBoss EAP?

goto -->

C:\Users\ujjal\installs\jbdevstudio9\runtimes\jboss-eap\bin

open --> standalone.conf.bat
update -->

set "JAVA_OPTS=-Xms2G -Xmx2G -XX:MaxPermSize=512M"

Saturday, June 11, 2016

Dont Follow Passion - Follow Opportunity


Stop searching for your passion | Terri Trespicio | TEDxKC

https://www.youtube.com/watch?v=6MBaFL7sCb8

* Look for Problems that needs solving
* Dont wait - just start doing
* You
-------------------------------------------------------------------------------------------------

To find work you love, don't follow your passion | Benjamin Todd | TEDxYouth@Tallinn

https://www.youtube.com/watch?v=MKlx1DLa9EA


Wednesday, June 1, 2016

Kill Windows service based on the PID



Find the Service Name:


Find the PID

c:\>sc queryex "JbossSS"


Kill the service with the PID:
open cmd and run as admin.. then run taskkill with the PID

c:\>taskkill /F /PID <<4024>>

---------------------------------------------------------------
Reference:
http://www.dba-oracle.com/t_windows_kill_service_sc_queryx_taskkill.htm

Thursday, May 19, 2016

LDAP Authentication in JbossFuse (17/250-2016)

Step1: Add WSS4JInInterceptor & JAASLoginInterceptor to cxf:endpoint


<cxf:cxfEndpoint id="ridpEndpoint" address="XXXX" serviceClass="xxxx" wsdlURL="xxx">
    <cxf:inInterceptors>
 <bean id="wss4jInInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
  <property name="properties">
   <map>
    <entry key="passwordType" value="PasswordText" />
    <entry key="action" value="UsernameToken" />
   </map>
  </property>
 </bean>
 <ref component-id="authenticationInterceptor"/>
    </cxf:inInterceptors>
    <cxf:properties>
         <entry key="ws-security.validate.token" value="false"/>
    </cxf:properties>
</cxf:cxfEndpoint>

<bean id="authenticationInterceptor" class="org.apache.cxf.interceptor.security.JAASLoginInterceptor">
      <property name="contextName" value="karaf"/>
</bean>

Within the cxf:inInterceptor, two more interceptors are added.


WSS4JInInterceptor - the Java class to implement the Interceptor is mentioned over here. 
The passwordType and action is defined over here.
The entry in the properties - security action - UsernameToken is mandatory.

ws-security.validate.token - set to false.

We have to tell WSS4J not to authenticate the UsernameToken itself, but just to process it and store it for later authentication via the JAASLoginInterceptor. This is done by setting the JAX-WS property "ws-security.validate.token" to "false". 


JAASLoginInterceptor -  it is necessary to set the "contextName" attribute of the JAASLoginInterceptor, which references the JAAS Context Name to use. It is also possible to define how to retrieve roles as part of the authentication process, by default CXF assumes that javax.security.acl.Group Objects are interpreted as "role" Principals. 


Step2: Using JAAS LoginModules in Apache CXF

Validating a Username + Password to LDAP / Active Directory  - 

2.1 com.sun.security.auth.module.LdapLoginModule - copy the xml(blueprint) below - and create a new file, and place the file in the deploy folder of Jboss Fuse Installation.


<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0"
  xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">

  <jaas:config name="karaf" rank="1">
    <jaas:module className="org.apache.karaf.jaas.modules.ldap.LDAPLoginModule"
                 flags="required">
      initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
      connection.username=uid=admin,ou=system
      connection.password=secret
      connection.protocol=
      connection.url=ldap://localhost:10389
      user.base.dn=ou=users,ou=system
      user.filter=(uid=%u)
      user.search.subtree=true
      role.base.dn=ou=roles,ou=system
      role.name.attribute=cn
      role.filter=(member=uid=%u)
      role.search.subtree=true
      authentication=simple
    </jaas:module>
  </jaas:config>
</blueprint>

or 

2.2 org.eclipse.jetty.plus.jaas.spi.LdapLoginModule - Available via the org.eclipse.jetty/jetty-plus dependency. This login module is useful as it's easy to retrieve roles associated with the authenticated user.


sun {
 com.sun.security.auth.module.LdapLoginModule REQUIRED
 userProvider="ldap://localhost:portno/"
 authIdentity="cn={USERNAME},ou=users,dc=example,dc=com"
 useSSL=false
 debug=true;
};

jetty {
    org.eclipse.jetty.plus.jaas.spi.LdapLoginModule required
    debug="true"
    contextFactory="com.sun.jndi.ldap.LdapCtxFactory"
    hostname="localhost"
    port="portno"
    bindDn="uid=admin,dc=example,dc=com"
    bindPassword="ldap_su"
    authenticationMethod="simple"
    forceBindingLogin="false"
    userBaseDn="ou=users,dc=example,dc=com"
    userRdnAttribute="cn"
    userIdAttribute="cn"
    userPasswordAttribute="userPassword"
    userObjectClass="inetOrgPerson"
    authenticated="true";
};







Friday, May 13, 2016

Force Fuse to use TLS1.2 (16/250-2016)

Add the attribute secureSocketProtocol="TLSv1.2" in tlsClientParamaters under the conduit tag

<http:conduit name="https://.*/.*">
<http:tlsClientParameters disableCNCheck="true" secureSocketProtocol="TLSv1.2">


1)mvn clean install

Optional
2)mvn -Pserver -Djavax.net.debug=all (Run server)
3)mvn -Psecure.client -Djavax.net.debug=all (client)

Add "javax.net.debug=all" in system.properties in fuse/etc to start the server in all debug logging.




What is a nonce? (15/250-2016)

In cryptography, a nonce is an arbitrary number that may only be used once.
It is often a random or pseudo-random number issued in an authentication protocol to ensure that old communications cannot be reused in replay attacks.

May include 

  • timestamp (requires clock synchronization between organizations)







Reference:
https://en.wikipedia.org/wiki/Cryptographic_nonce

Wednesday, May 11, 2016

Troubleshooting - com.ctc.wstx.exc.WstxIOException: Invalid UTF-8 start byte 0x8b (at char #2, byte #-1) (14/250-2016)


Error:
org.apache.cxf.workqueue.AutomaticWorkQueueImpl$AWQThreadFactory$1.run(AutomaticWorkQueueImpl.java:353)[118:org.apache.cxf.cxf-core:3.0.4.redhat-620133]
 at java.lang.Thread.run(Thread.java:745)[:1.7.0_79]
Caused by: com.ctc.wstx.exc.WstxIOException: Invalid UTF-8 start byte 0x8b (at char #2, byte #-1)
 at com.ctc.wstx.stax.WstxInputFactory.doCreateSR(WstxInputFactory.java:550)[112:woodstox-core-asl:4.4.1]

Scenario:

SOAPUI --> ESB --> Backend Service Provider
ESB invokes the backend Service Provider, but fails when the service provider sends a response back to ESB.

Caused By:

By default SOAP UI is set to "Accept compressed responses from host". Since client mentions that it can accept GZIP format of the response, the service provider sends the response in a GZIP format.




Analysis:

SOAPUI mentions that it can accept compressed response message, but ESB is not able to handle the GZIP format of the response from the backend service provider.

Resolution:
In ESB, in the producer cxf endpoint (which goes out to the backend service), we have to mention in the InInterceptor to unzip the response from the Backend Service Provider.





Troubleshooting - javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target (13/250-2016)

Exception
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Scenario:
This exception occurs when trying to invoke a webservice with a privateKey (JKS file).

Cause:
The provider of the service expects the JKS file to also contain the public certificate

Resolution:

1. Download the public certificate from the webservice endpoint.
    a. open the endpoint in browser
    b. click on "view site information"
    c. click on details --> view certificate --> Certificate - details --> copy to file --> Export fileformat base64.

2. User the keytool to import the public certificate into the jks file (the private certificate)

keytool -import -alias symantec -keystore symantec_vip.jks -trustcacerts -file D:\installs\JFuse6.2_Dev\jboss-fuse-6.2.0.redhat-133\etc\vip_cert.cer

3. Resume testing.

Tuesday, May 10, 2016

Troubleshooting Bundle not Starting- (12/250-2016)


1. Feature or Bundle not installed 
JBossFuse:karaf@root> osgi:install MyBundleURL
JBossFuse:karaf@root> dev:dynamic-import <<bundle_id>>
JBossFuse:karaf@root> osgi:resolve <<bundle_id>>
JBossFuse:karaf@root> packages:imports <<bundle_id>>

2. Import-Package header is incomplete

Import package can be verified by using below commands on JBoss Fuse.
>>imports <bundle-id>
>>headers <bundle-id>


References:
https://access.redhat.com/documentation/en-US/Red_Hat_JBoss_Fuse/6.0/html/Deploying_into_the_Container/files/ch12s04.html

Wednesday, February 24, 2016

Connecting Canon MX490 to Google Cloud Printer

Connect the printer to the Google Cloud Print web service
  • Click the setup button
  • Select webservice setup
  • Connection setup
  • Google Cloud Print
  • Register for Google Cloud Print
  • A paper will be printed with a url (goo.gl/printer/......)
  • goto your browser - type in the url - this will register the printer to the google user

Share the Printer
  • https://www.google.com/cloudprint?user=0#printers
  • select the desired printer
  • add the desired user to the list of users who can use the printer

Monday, February 22, 2016

Apache Camle & Dozer - Java Bean to Bean mapper using Dozer. (11/250-2016)

Using dozer for Java Bean to Bean mapping in Apache Camel - makes life extremely simple to recursively copy data from one object to another.
The below steps will help to quickly add a dozer mapping file in OSGI Blueprint xml
  • In the blueprint.xml add the bean definitions below
    Note - the name of the camel context should be same as the argument index="0"

<bean id="dozerConverterLoader"
  class="org.apache.camel.converter.dozer.DozerTypeConverterLoader">
  <argument index="0" ref="abcdCamelContext" />
  <argument index="1" ref="abcMapper" />
</bean>
<bean id="abcMapper" class="org.apache.camel.converter.dozer.DozerBeanMapperConfiguration" />


  • Inside the route include the sample code to invoke the dozer mapping file.
  • Also mention the expected source object / destination object

<camelContext id="abcdCamelContext" xmlns="http://camel.apache.org/schema/blueprint">
  <route>
    <from uri="direct:test" />
    .....
<to uri="dozer:submitRequest?mappingFile=mapping/abcd.xml&amp;sourceModel=com.abcd.SourceReq&amp;targetModel=com.abcd.DestReq" />
    .....
  </route>
</camelContext>


  • Mapping file - location - under src/main/resources

<mappings xmlns="http://dozer.sourceforge.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://dozer.sourceforge.net  http://dozer.sourceforge.net/schema/beanmapping.xsd">
  
  <mapping wildcard="false">
    <class-a>com.abcd.SourceReq</class-a>
    <class-b>com.abcd.DestReq</class-b>
    
    <field>
      <a>caseNumberSrc</a>
      <b>caseNumberDest</b>
    </field>
  </mapping>
</mappings>


  • Sample Source Object - SourceReq

public class SourceReq {
 
 String caseNumberSrc;
 
 public String getCaseNumberSrc() {
  return caseNumberSrc;
 }
 public void setCaseNumberSrc(String caseNumberSrc) {
  this.caseNumberSrc = caseNumberSrc;
 }

}


  • Sample Destination Object - DestReq

public class DestReq {

 String caseNumberDest;

 public String getCaseNumberDest() {
  return caseNumberDest;
 }

 public void setCaseNumberDest(String caseNumberDest) {
  this.caseNumberDest = caseNumberDest;
 }
}


Saturday, February 13, 2016

Apache Camel - Synchronicity & Threading (9/250-2016)

A service can be called synchronously as well as asynchronously
After the service is invoked - the consumer can use multiple / single thread to complete the operation.

The factors which affect the threading model 

  • Component - which starts the process - whether it is fire and forget or request/reply messaging style
  • EIP - some support parallel processing (concurrency)
  • Configured Synchronicity - some components can be configure to be sync/async
  • Transactions - if a route is transacted -- the transactional context is limited to run within one thread only.
  • MEP (Message Exchange Pattern) - information in the exchange telling InOnly / OutOnly / InOut
Different scenarios discussed in the book - 
  • Async caller - Camel uses only one thread 
    • template.sendBody = InOnly Msg
    • caller sending InOnly Msg
    • single thread - pros
      • simple
      • support transaction propagation
    • cons
      • consumer threads can be overloaded by number of incoming messages
  • Sync Called - Camel uses multi thread
    • template.requestBody = InOutBody
  • Async caller - Camel uses only one thread
  • Sync caller - Camel uses multi thread

References: 

Apache Camel - How to use concurrency with WIPs? (8/250-2016)

Parallel Processing - 
EIPs in Camel that support concurrency - you can turn on parallel processing to use thread pool profiles to apply a matching thread pool (see pg 330 of Camel in Action)
  • Aggregate
  • Multicast -   (see pg 327 of   Camel in Action)
    • parallel processing of multiple routes - best used when multiple routes interacts with multiple systems
    • send copies of the msg to multiple routes
    • aggregate data after all execution complets
  • RecipientList
  • Splitter
  • Threads
  • WireTap
Custom Thread Pool - (see pg 320 of Camel in Action)

  • create thread pools using java.util.concurrent.Executors 
  • ExecutorService threadpool = Executors.newCachedThreadPool
    • the thread pool will grow and shrink - no upper bound - very aggressive
  • ExecutorService threadpool = Executors.newFixedThreadPool(20)


Staged Event Driven Architecture (SEDA) -  (see pg 322 of Camel in Action)

  •  breaks down complex application into statges using internal queues - to handover messages between routes.
  • eg:
from("file:\\...").to("seda:test")...from("seda:test?concurrentConsumers=20")

  • 20  

Thursday, February 11, 2016

Concurrency / Java Thread Pools and Apache Camel - (7/250-2016)


Concurrency - is multitasking.
Camel leverages concurrency features from Java - Thread Pools
  • Applications are generally bound by IO or CPU - Integration applications are generally bound by IO. Use concurrency only if applications are bound by IO
  • The example below shows the usage of concurrency in Camel - default pool size is 10.
  • The example can be changed with Custom Thread pools - and providing the number of threads in the pool.
Example:
<split streaming="true" parallelProcessing="true">
    <tokenize token="\n"/>
   <bean beanType="xxx.XyzService" method="testMeth"/>
</split>

  • There are situations where some applications (external systems) dont allow concurrency / allow till only a certain number of concurrent messages - check SLA first.
Thread Pools
  • java.util.concurrent package has the concurrency API - Java 1.5 onward.
  • Clients for this api are both Camel End users and Camel as well.
  • class ThreadPoolExecutor implements ExecutorService - provides thread pool with the options.
    • corePoolSize
    • maximumPoolSize
    • keepAliveTime
    • unit
    • rejected
    • workQueue
    • threadFactory
  • Managing Thread Pools
    • Shutdown
    • Management
    • Unique Thread names
    • Activity Logging
  • Ensure to Use human understandable thread names
Camel & Thread pools

  • Thread pools are not used directly but via configurations of thread pool profiles.
  • one default profiles and multiple custom profiles
    • poolSize
    • maxPoolSize
    • keepAliveTime
    • maxQueueSize
    • rejectedPolicy - Abot, CallerRuns, DiscardOldest, Discard
      • CallerRuns - will use the caller thread to execute the task
Example Default Thread Pool Profile:-
<camelContext .... >
    <threadPoolProfile id="testdefaultProfile" defaultProfile="true" maxPoolSize="50"/>
</camelContext>

Example Configuring the Custom Thread Pool Profile:-
  • Created using the ThreadPoolProfileSupport class -  "xyzPool" - this name will be referred later. (see pg 327 of   Camel in Action )
  • Set maxPoolSize to - say 100
  • register the ThreadPoolProfile to the context
  • all other options will be inherited from the default profile
  • in the camel route refer to the threadPool using the name "xyzPool"
    • .split(...).streaming().executorServiceRef("xyzPool").bean(...)
  • in spirng
    • <camelContext ....> 
      • <threadPoolProfile id="xyzPool" maxPoolSize="100"/>
    • </camelContext>


Custom Thread Pool

  • Java DSL - using ThreadPoolBuilder  (see pg 328 of   Camel in Action )
  • Spring - using <threadPool> tag
  • both uses the camelContext to refer to the defaultProfile as a base line

Camel will first check for Custom Thread Pool --> Custom Thread Pool Profile  --> Default

Executor Service Strategy (see pg 329 of   Camel in Action )
org.apache.camel.spi.ExecutorServiceStrategy is a pluggable API for thread pool providers.
  • default - DefaultExecutorServiceStrategy - creates thread pools using concurrency API in Java
  • custom - ExecutorServiceStrategy
    • USECASE - Custom Camel component - and you need to run a scheduled background task - recommended to use the ScheduledExecutorService.





Apache Camel - What is SEDA? How can I add concurrency in SEDA? (8/250-2016)

SEDA - Staged Event Driven Architecture - breaks donw complex application into statges using internal queues - to handover messages between routes.

DIRECT - is similar to SEDA component - but it is fully synchronized and acts as a direct call.

Ex.

from("file:\\...")
.to("seda:test")
...

from("seda:test?concurrentConsumers=20")
....
....


In this case -  20 threads will be created and the processing will be fast.



Friday, February 5, 2016

Apache Camel - How to trigger Compensation Handler? (7/250-2016)





Compensation handler in camel is based on the concept of Unit of Work — group together multiple tasks as a single unit — mimicking transnational boundaries.
  • org.apache.camel.spi.UnitOfWork Interface represents UnitOfWork in Camel.
  • Exchange has exactly one UnitOfWork (private to Exchange — not shared with others) — accessed from exchange using method — getUnitOfWork
  • Camel will automatically inject a new UnitOfWork into Exchange — using internal processor UnitOfWorkProcessor — involved in start of every route
  • At the end of the route, the processor invokes registered Synchronization callback

Synchronization (a callback)
  • org.apache.camel.spi.Synchronization Interface is used to represent Synchronization.
  • used to execute custom logic — after processing — using the methods below.
onComplete
onFailure
  • An exchange can add multiple callBacks.
  • If there is an error while processing callBack — Camel will log in WARN level and continue to next callback.
Synchronization is added / removed to the UnitOfWork using the methods below — using a processor.
addSynchronization
removeSynchronization
done — invoked when UnitOfWork is complete
OR
addOnCompletetion
This is a method on the exchange — it creates a new thread — and is the preferred method for compensation handling.
addOnCompletion can be written in Java DSL as well as Spring DSL.
It can be route / context scoped.

References:

Friday, January 29, 2016

Apache Camel - How to create a Datasource in Camel - OSGI Blueprint DSL? (6/250-2016)


  • Create a Fuse project (archtype contract first) and name it Datasource - this is the Datasource project which will be deployed independently
  • In the blueprint.xml add the code below
<cm:property-placeholder persistent-id="configuration" update-strategy="reload" />

  <bean id="dbcp" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver"/>
    <property name="url" value="${db.jdbc.url}"/>
    <property name="username" value="${db.jdbc.username}"/>
    <property name="password" value="${db.jdbc.password}"/>
  </bean>  

  <service interface="javax.sql.DataSource" ref="dbcp">
    <service-properties>
      <entry key="osgi.jndi.service.name" value="jdbc/DBDS"/>
      <entry key="datasource.name" value="DBDS"/>
    </service-properties>
  </service>

  • Configuration - this needs to be saved as configuration.cfg and places under <installs-dir>/etc
db.datasource=DBDS
db.jndi.datasource=jdbc/DBDS
db.jdbc.username=abcd
db.jdbc.password=abcd
db.jdbc.url=jdbc:db2://<ip-address>:<port>/<databasename>


  • Dependency to be added in pom.xml

<modelVersion>4.0.0</modelVersion>
<groupId>com.test.ds</groupId>
<artifactId>datasource</artifactId>
<name>DataSource</name>
<version>1.0.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<dependencies>
    <dependency>
 <groupId>commons-dbcp</groupId>
 <artifactId>commons-dbcp</artifactId>
 <version>1.4</version>
    </dependency>
</dependencies>

  • Once the Datasource project is ready the Datasource object can be used in beans across several projects
  • Create a new Fuse project - name it TestDB (archtype - contract first)
  • In the blueprint add the code below

<bean id="SomeBean" class="com.some.bean.SomeBean">
    <property name="dataSource">
        <reference filter="(datasource.name=DBDS)" interface="javax.sql.DataSource" />
    </property>
</bean>

  • the datasource name is registered as "DBDS" - and this is referred from the bean "SomeBean"

public class SomeBean{
        private DataSource dataSource = null;
 public DataSource getDataSource() {
  return dataSource;
 }
 public void setDataSource(DataSource dataSource) {
  this.dataSource = dataSource;
 }
 
 public String testDBConnection()
 {
  //in this bean u can access the datasource and get connection
  DataSource ds = getDataSource();
  if(ds != null)
  {
   Connection conn = ds.getConnection()
  }
 }
} 


  • Once the datasource is accessable from a bean - life is simple and we can do any kind of DB queries
  • While testing in JBoss Fuse - please install features mentioned below
    • osgi:install wrap:mvn:commons-dbcp/commons-dbcp/1.4




Wednesday, January 27, 2016

Apache Camel - What is a Dynamic Router EIP? (5/250 - 2016)

The Dynamic Router from the EIP patterns allows you to route messages while avoiding the dependency of the router on all possible destinations while maintaining its efficiency.

Dynamic router is similar to Routing Slip - the difference being
1. Routing Slip - the decision is made before hand
2. Dynamic Router (Dynamic Routing Slip) - the decision is based on the fly - Provide logic - using Java code/query Database /rules Engine  - to route msg to particular destination

Example:

Spring DSL


<bean id="myBean" class="xyz.DynamicRouterAnnotationBean"/>
<camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="direct:start"/>
            <bean ref="myBean" method="route"/>
            <to uri="mock:result"/>
        </route>
        <route>
            <from uri="direct:a"/>
    <log message="in direct:a"/>
        </route>
        <route>
            <from uri="direct:b"/>
    <log message="in direct:b"/>
        </route>
        <route>
            <from uri="direct:c"/>
    <log message="in direct:c"/>
        </route>
        <route>
            <from uri="direct:d"/>
    <log message="in direct:c"/>
        </route>
</camelContext>

Java Bean

public class DynamicRouterAnnotationBean {
    @DynamicRouter
    public String route(String body, @Header(Exchange.SLIP_ENDPOINT) String previous) {
    System.out.println("**************route, body-"+body+", previous-"+previous);
        if (previous == null) {
            // 1st time
            return "direct://a";
        } else if ("direct://a".equals(previous)) {
            // 2nd time -
            return "direct://b";
        } else if ("direct://b".equals(previous)) {
            // 2nd time -
            return "direct://d,direct://c";
        } else if ("direct://c".equals(previous)) {
        // 3rd time - transform the message body using the simple language
            return "direct://d";
        } else if ("direct://d".equals(previous)) {
            // 3rd time - transform the message body using the simple language
            return "language://simple:Bye ${body}";
        } else {
            // no more, so return null to indicate end of dynamic router
            return null;
        }
    }
}
  • From the camel route "direct:start", we call the method "route" in the bean DynamicRouterAnnotationBean. 
  • The method "route" has an annotation @DynamicRouter which tells camel that this is not a regular java bean, but follows EIPs
  • the route method will then be invoked repeatedly until it returns "null"
  • you can return multiple endpoints using delimeter


Output

**************route, body-Camel, previous-null
2016-01-27 11:17:14,910 [                     main] INFO  route2                         - in direct:a
**************route, body-Camel, previous-direct://a
2016-01-27 11:17:14,914 [                     main] INFO  route3                         - in direct:b
**************route, body-Camel, previous-direct://b
2016-01-27 11:17:14,925 [                     main] INFO  route5                         - in direct:d
2016-01-27 11:17:14,928 [                     main] INFO  route4                         - in direct:c
**************route, body-Camel, previous-direct://c
2016-01-27 11:17:14,930 [                     main] INFO  route5                         - in direct:d
**************route, body-Camel, previous-direct://d
**************route, body-Bye Camel, previous-language://simple:Bye%20$%7Bbody%7D



References:
http://camel.apache.org/dynamic-router.html
https://github.com/camelinaction/camelinaction

Apache Camel - What is a Routing Slip? (4/250 for 2016)

The Routing Slip from the EIP patterns allows you to route a message consecutively through a series of processing steps where the sequence of steps is not known at design time and can vary for each message.







References:

http://camel.apache.org/routing-slip.html

Monday, January 18, 2016

Jboss Fuse / Apache Camel - How to enable ws-security? (3/250 - 2016)


Dependencies to be added in pom.xml
<dependency>
   <groupId>org.apache.wss4j</groupId>
   <artifactId>wss4j-bindings</artifactId>
   <version>2.0.3</version>
  </dependency>
  <dependency>
   <groupId>org.apache.wss4j</groupId>
   <artifactId>wss4j-policy</artifactId>
   <version>2.0.3</version>
  </dependency>
  <dependency>
   <groupId>org.apache.wss4j</groupId>
   <artifactId>wss4j-ws-security-common</artifactId>
   <version>2.0.3</version>
  </dependency>
  <dependency>
   <groupId>org.apache.wss4j</groupId>
   <artifactId>wss4j-ws-security-dom</artifactId>
   <version>2.0.3</version>
  </dependency>
  <dependency>
   <groupId>org.apache.wss4j</groupId>
   <artifactId>wss4j-ws-security-policy-stax</artifactId>
   <version>2.0.3</version>
  </dependency>
  <dependency>
   <groupId>org.apache.wss4j</groupId>
   <artifactId>wss4j-ws-security-stax</artifactId>
   <version>2.0.3</version>
  </dependency>


Features to be installed in Fuse:

features:install wss4j
features:install cxf-wssecurity


Update Bluerpint with the code place- 
  <http:conduit name="https://.*/.*">
  <http:tlsClientParameters disableCNCheck="true">
   <sec:trustManagers>
    <sec:keyStore type="JKS" file="etc/uatesb.jks" password="password" />
   </sec:trustManagers>
   <sec:keyManagers keyPassword="password">
    <sec:keyStore type="JKS" file="etc/uatesb.jks" password="password" />
   </sec:keyManagers>

   <sec:cipherSuitesFilter>
    <sec:include>.*_EXPORT_.*</sec:include>
    <sec:include>.*_EXPORT1024_.*</sec:include>
    <sec:include>.*_WITH_DES_.*</sec:include>
    <sec:include>.*_WITH_AES_.*</sec:include>
    <sec:include>.*_WITH_NULL_.*</sec:include>
    <sec:exclude>.*_DH_anon_.*</sec:exclude>
   </sec:cipherSuitesFilter>
  </http:tlsClientParameters>
  <http:client AutoRedirect="true" Connection="Keep-Alive" />
 </http:conduit>


Based on the requirement add Inbound / Outbound Interceptors within the consumer / producer endpoints.

<cxf:inInterceptors>
 <bean id="wss4jInInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
  <property name="properties">
   <map>
    <entry key="passwordType" value="PasswordText" />
    <entry key="action" value="UsernameToken" />
    <entry key="passwordCallbackRef">
     <bean class="com.dummy.handler.PasswordCallback">
      <property name="passwordMap">
       <map>
        <entry key="${datapower.user.id}" value="${datapower.user.password}" />
        <entry key="${esb.user.id}" value="${esb.user.password}" />
       </map>
      </property>
     </bean>
    </entry>
   </map>
  </property>
 </bean>
</cxf:inInterceptors>



<cxf:outInterceptors>
 <bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
  <property name="properties">
   <map>
    <entry key="user" value="wesb" />
    <entry key="passwordCallbackRef">
    <bean id="passwordCallback" class="com.dummy.handler.PasswordCallback">
     <property name="passwordMap">
      <map>
       <entry key="${datapower.user.id}" value="${datapower.user.password}" />
       <entry key="${esb.user.id}" value="${esb.user.password}" />
      </map>
     </property>
    </bean>
    </entry>
    <entry key="action" value="UsernameToken Timestamp" />
    <entry key="passwordType" value="PasswordDigest" />
    <entry key="mustUnderstand" value="${secureEnable}" />
   </map>
  </property>
 </bean>
</cxf:outInterceptors>



The PasswordCallback Impl

public class PasswordCallback implements CallbackHandler {

 private static Logger logger = Logger.getLogger(PasswordCallback.class);
 private Map<String, String> passwordMap;

 public Map<String, String> getPasswordMap() {
  return passwordMap;
 }

 public void setPasswordMap(Map<String, String> passwordMap) {
  this.passwordMap = passwordMap;
 }

 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
  WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
  if (pc.getIdentifier() != null && passwordMap != null) {
   if ("wesb".equals(pc.getIdentifier())) {
    try {
     pc.setPassword((DummyEncryptDecrypter.decrypt(passwordMap.get(pc.getIdentifier()))));
    } catch (DummyCipherException e) {

     e.printStackTrace();
     logger.error("Error in decrypt password for id " + pc.getIdentifier());
     throw new UnsupportedCallbackException(null, "Error in decrypt password for id " + pc.getIdentifier());
    }
   } else {
    pc.setPassword(passwordMap.get(pc.getIdentifier()));
   }
  }
 }
}



DummyEncryptDecrypter

public class DummyEncryptDecrypter {

 Cipher cipher;

 private final static String IV = "password12345678";
 private final static String AES_CBC = "AES/CBC/PKCS5Padding";
 
 private static Logger logger = Logger.getLogger(DummyEncryptDecrypter.class);
 
 static SecretKeySpec key = new SecretKeySpec(IV.getBytes(), "AES");

 /**
  * Decrypt
  * 
  * @param cipherText
  * @return
  * @throws DummyCipherException
  */
 public static  String decrypt(String cipherText) throws DummyCipherException  {
  if(cipherText==null){
   return "";
  }
  AlgorithmParameterSpec paramSpec = new IvParameterSpec(
    IV.getBytes());

  Cipher cipher = null;
  byte[] output = null;
  byte[] decrypted = null;
  try {
   cipher = Cipher.getInstance(AES_CBC);
   cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
   output = new BASE64Decoder().decodeBuffer(cipherText);
   decrypted = cipher.doFinal(output);
  } catch (Exception e) {
   logger.error("Exception while decrypt ");

   throw new DummyCipherException(e.getMessage(), e);
  }
  String palintText = new String(decrypted);
  return palintText;
 }

 /**
  * Encrypt
  * 
  * @param painText
  * @return
  * @throws DummyCipherException
  */
 public static String encrypt(String painText) throws DummyCipherException {

  if(painText==null){
   return "";
  }
  AlgorithmParameterSpec paramSpec = new IvParameterSpec(
    IV.getBytes());

  Cipher cipher = null;
  byte[] ecrypted = null;
  String output = null;

  try {
   cipher = Cipher.getInstance(AES_CBC);
   cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
   ecrypted = cipher.doFinal(painText.getBytes());
   output = new BASE64Encoder().encode(ecrypted);
  } catch (Exception e) {
   logger.error("Exception while encrypting the string "+e.getMessage());
   throw new DummyCipherException(e.getMessage(), e);
  } 
  return output;

 }
 
 public static void main(String arg[]) throws DummyCipherException{
  String s = "xxxxxxxxxx";
  System.out.println(new DummyEncryptDecrypter().decrypt(s));
  System.out.println(new DummyEncryptDecrypter().encrypt("password"));
 }
}


DummyCipherException 
public class DummyCipherException extends Exception {

 private static final long serialVersionUID = 1L;
 public DummyCipherException(String message) {
  super(message);
 }
 public DummyCipherException(String message, Exception e) {
  super(message, e);
 }
}

Configuration File
datapower.user.password=xxxx
datapower.user.id=xxxx
keystore.password=xxxx
secureEnable=false
esb.user.id=xxxx
esb.user.password=xxxx