Saturday, August 9, 2014

OSGi: the gateway into micro-services architecture

The terms "modularity" and "microservices architecture" pop up quite often these days in context of building scalable, reliable distributed systems. Java platform itself is known to be weak with regards to modularity (Java 9 is going to address that by delivering project Jigsaw), giving a chance to frameworks like OSGi and JBoss Modules to emerge.

When I first heard about OSGi back in 2007, I was truly excited about all those advantages Java applications might benefit of by being built on top of it. But very quickly the frustration took place instead of excitement: no tooling support, very limited set of compatible libraries and frameworks, quite unstable and hard to troubleshoot runtime. Clearly, it was not ready to be used by average Java developer and as such, I had to put it on the shelf. With years, OSGi has matured a lot and gained a widespread community support.

The curious reader may ask: what are the benefits of using modules and OSGi in particular? To name just a few problems it helps to solve:

  • explicit (and versioned) dependency management: modules declare what they need (and optionally the version ranges)
  • small footprint: modules are not packaged with all their dependencies
  • easy release: modules can be developed and released independently
  • hot redeploy: individual modules may be redeployed without affecting others

In today's post we are going to take a 10000 feet view on a state of the art in building modular Java applications using OSGi. Leaving aside discussions how good or bad OSGi is, we are going to build an example application consisting of following modules:

  • data access module
  • business services module
  • REST services module
Apache OpenJPA 2.3.0 / JPA 2.0 for data access (unfortunately, JPA 2.1 is not yet supported by OSGi implementation of our choice), Apache CXF 3.0.1 / JAX-RS 2.0 for REST layer are two main building blocks of the application. I found Christian Schneider's blog, Liquid Reality, to be invaluable source of information about OSGi (as well as many other topics).

In OSGi world, the modules are called bundles. Bundles manifest their dependencies (import packages) and the packages they expose (export packages) so other bundles are able to use them. Apache Maven supports this packaging model as well. The bundles are managed by OSGi runtime, or container, which in our case is going to be Apache Karaf 3.0.1 (actually, it is the single thing we need to download and unpack).

Let me stop talking and better show some code. We are going to start from the top (REST) and go all the way to the bottom (data access) as it would be easier to follow. Our PeopleRestService is a typical example of JAX-RS 2.0 service implementation:

package com.example.jaxrs;

import java.util.Collection;

import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import com.example.data.model.Person;
import com.example.services.PeopleService;

@Path( "/people" )
public class PeopleRestService {
    private PeopleService peopleService;
        
    @Produces( { MediaType.APPLICATION_JSON } )
    @GET
    public Collection< Person > getPeople( 
            @QueryParam( "page") @DefaultValue( "1" ) final int page ) {
        return peopleService.getPeople( page, 5 );
    }

    @Produces( { MediaType.APPLICATION_JSON } )
    @Path( "/{email}" )
    @GET
    public Person getPerson( @PathParam( "email" ) final String email ) {
        return peopleService.getByEmail( email );
    }

    @Produces( { MediaType.APPLICATION_JSON  } )
    @POST
    public Response addPerson( @Context final UriInfo uriInfo,
            @FormParam( "email" ) final String email, 
            @FormParam( "firstName" ) final String firstName, 
            @FormParam( "lastName" ) final String lastName ) {
        
        peopleService.addPerson( email, firstName, lastName );
        return Response.created( uriInfo
            .getRequestUriBuilder()
            .path( email )
            .build() ).build();
    }
    
    @Produces( { MediaType.APPLICATION_JSON  } )
    @Path( "/{email}" )
    @PUT
    public Person updatePerson( @PathParam( "email" ) final String email, 
            @FormParam( "firstName" ) final String firstName, 
            @FormParam( "lastName" )  final String lastName ) {
        
        final Person person = peopleService.getByEmail( email );
        
        if( firstName != null ) {
            person.setFirstName( firstName );
        }
        
        if( lastName != null ) {
            person.setLastName( lastName );
        }

        return person;              
    }
    
    @Path( "/{email}" )
    @DELETE
    public Response deletePerson( @PathParam( "email" ) final String email ) {
        peopleService.removePerson( email );
        return Response.ok().build();
    }
    
    public void setPeopleService( final PeopleService peopleService ) {
        this.peopleService = peopleService;
    }
}

As we can see, there is nothing here telling us about OSGi. The only dependency is the PeopleService which somehow should be injected into the PeopleRestService. How? Typically, OSGi applications use blueprint as the dependency injection framework, very similar to old buddy, XML based Spring configuration. It should be packaged along with application inside OSGI-INF/blueprint folder. Here is a blueprint example for our REST module, built on top of Apache CXF 3.0.1:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
    xmlns:cxf="http://cxf.apache.org/blueprint/core"
    xsi:schemaLocation="
        http://www.osgi.org/xmlns/blueprint/v1.0.0 
        http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
        http://cxf.apache.org/blueprint/jaxws 
        http://cxf.apache.org/schemas/blueprint/jaxws.xsd
        http://cxf.apache.org/blueprint/jaxrs 
        http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
        http://cxf.apache.org/blueprint/core 
        http://cxf.apache.org/schemas/blueprint/core.xsd">

    <cxf:bus id="bus">
        <cxf:features>
            <cxf:logging/>
        </cxf:features>       
    </cxf:bus>

    <jaxrs:server address="/api" id="api">
        <jaxrs:serviceBeans>
            <ref component-id="peopleRestService"/>
        </jaxrs:serviceBeans>
        <jaxrs:providers>
            <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
        </jaxrs:providers>
    </jaxrs:server>
    
    <!-- Implementation of the rest service -->
    <bean id="peopleRestService" class="com.example.jaxrs.PeopleRestService">
        <property name="peopleService" ref="peopleService"/>
    </bean>         
    
    <reference id="peopleService" interface="com.example.services.PeopleService" />
</blueprint>

Very small and simple: basically the configuration just states that in order for the module to work, the reference to the com.example.services.PeopleService should be provided (effectively, by OSGi container). To see how it is going to happen, let us take a look on another module which exposes services. It contains only one interface PeopleService:

package com.example.services;

import java.util.Collection;

import com.example.data.model.Person;

public interface PeopleService {
    Collection< Person > getPeople( int page, int pageSize );
    Person getByEmail( final String email );
    Person addPerson( final String email, final String firstName, final String lastName );
    void removePerson( final String email );
}

And also provides its implementation as PeopleServiceImpl class:

package com.example.services.impl;

import java.util.Collection;

import org.osgi.service.log.LogService;

import com.example.data.PeopleDao;
import com.example.data.model.Person;
import com.example.services.PeopleService;

public class PeopleServiceImpl implements PeopleService {
    private PeopleDao peopleDao;
    private LogService logService;
 
    @Override
    public Collection< Person > getPeople( final int page, final int pageSize ) {        
        logService.log( LogService.LOG_INFO, "Getting all people" );
        return peopleDao.findAll( page, pageSize );
    }

    @Override
    public Person getByEmail( final String email ) {
        logService.log( LogService.LOG_INFO, 
            "Looking for a person with e-mail: " + email );
        return peopleDao.find( email );        
    }

    @Override
    public Person addPerson( final String email, final String firstName, 
            final String lastName ) {
        logService.log( LogService.LOG_INFO, 
            "Adding new person with e-mail: " + email );
        return peopleDao.save( new Person( email, firstName, lastName ) );
    }

    @Override
    public void removePerson( final String email ) {
        logService.log( LogService.LOG_INFO, 
            "Removing a person with e-mail: " + email );
        peopleDao.delete( email );
    }
    
    public void setPeopleDao( final PeopleDao peopleDao ) {
        this.peopleDao = peopleDao;
    }
    
    public void setLogService( final LogService logService ) {
        this.logService = logService;
    }
}

And this time again, very small and clean implementation with two injectable dependencies, org.osgi.service.log.LogService and com.example.data.PeopleDao. Its blueprint configuration, located inside OSGI-INF/blueprint folder, looks quite compact as well:

<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 
        http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
        
    <service ref="peopleService" interface="com.example.services.PeopleService" />        
    <bean id="peopleService" class="com.example.services.impl.PeopleServiceImpl">
        <property name="peopleDao" ref="peopleDao" />    
        <property name="logService" ref="logService" />
    </bean>
    
    <reference id="peopleDao" interface="com.example.data.PeopleDao" />
    <reference id="logService" interface="org.osgi.service.log.LogService" />
</blueprint>

The references to PeopleDao and LogService are expected to be provided by OSGi container at runtime. Hovewer, PeopleService implementation is exposed as service and OSGi container will be able to inject it into PeopleRestService once its bundle is being activated.

The last piece of the puzzle, data access module, is a bit more complicated: it contains persistence configuration (META-INF/persistence.xml) and basically depends on JPA 2.0 capabilities of the OSGi container. The persistence.xml is quite basic:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    version="2.0">
 
    <persistence-unit name="peopleDb" transaction-type="JTA">
        <jta-data-source>
        osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=peopleDb)
        </jta-data-source>       
        <class>com.example.data.model.Person</class>
        
        <properties>
            <property name="openjpa.jdbc.SynchronizeMappings" 
                value="buildSchema"/>         
        </properties>        
    </persistence-unit>
</persistence>

Similarly to the service module, there is an interface PeopleDao exposed:

package com.example.data;

import java.util.Collection;

import com.example.data.model.Person;

public interface PeopleDao {
    Person save( final Person person );
    Person find( final String email );
    Collection< Person > findAll( final int page, final int pageSize );
    void delete( final String email ); 
}

With its implementation PeopleDaoImpl:

package com.example.data.impl;

import java.util.Collection;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;

import com.example.data.PeopleDao;
import com.example.data.model.Person;

public class PeopleDaoImpl implements PeopleDao {
    private EntityManager entityManager;
 
    @Override
    public Person save( final Person person ) {
        entityManager.persist( person );
        return person;
    }
 
    @Override
    public Person find( final String email ) {
        return entityManager.find( Person.class, email );
    }
 
    public void setEntityManager( final EntityManager entityManager ) {
        this.entityManager = entityManager;
    }
 
    @Override
    public Collection< Person > findAll( final int page, final int pageSize ) {
        final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
     
        final CriteriaQuery< Person > query = cb.createQuery( Person.class );
        query.from( Person.class );
     
        return entityManager
            .createQuery( query )
            .setFirstResult(( page - 1 ) * pageSize )
            .setMaxResults( pageSize ) 
            .getResultList();
    }
 
    @Override
    public void delete( final String email ) {
        entityManager.remove( find( email ) );
    }
}

Please notice, although we are performing data manipulations, there is no mention of transactions as well as there are no explicit calls to entity manager's transactions API. We are going to use the declarative approach to transactions as blueprint configuration supports that (the location is unchanged, OSGI-INF/blueprint folder):

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"  
    xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.1.0"
    xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         
    xsi:schemaLocation="
        http://www.osgi.org/xmlns/blueprint/v1.0.0 
        http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
    
    <service ref="peopleDao" interface="com.example.data.PeopleDao" />
    <bean id="peopleDao" class="com.example.data.impl.PeopleDaoImpl">
     <jpa:context unitname="peopleDb" property="entityManager" />
     <tx:transaction method="*" value="Required"/>
    </bean>
    
    <bean id="dataSource" class="org.hsqldb.jdbc.JDBCDataSource">
       <property name="url" value="jdbc:hsqldb:mem:peopleDb"/>
    </bean>
    
    <service ref="dataSource" interface="javax.sql.DataSource"> 
        <service-properties> 
            <entry key="osgi.jndi.service.name" value="peopleDb" /> 
        </service-properties> 
    </service>     
</blueprint>

One thing to keep in mind: the application doesn't need to create JPA 2.1's entity manager: the OSGi runtime is able do that and inject it everywhere it is required, driven by jpa:context declarations. Consequently, tx:transaction instructs the runtime to wrap the selected service methods inside transaction.

Now, when the last service PeopleDao is exposed, we are ready to deploy our modules with Apache Karaf 3.0.1. It is quite easy to do in three steps:

  • run the Apache Karaf 3.0.1 container
    bin/karaf (or bin\karaf.bat on Windows)
    
  • execute following commands from the Apache Karaf 3.0.1 shell:
    feature:repo-add cxf 3.0.1
    feature:install http cxf jpa openjpa transaction jndi jdbc
    install -s mvn:org.hsqldb/hsqldb/2.3.2
    install -s mvn:com.fasterxml.jackson.core/jackson-core/2.4.0
    install -s mvn:com.fasterxml.jackson.core/jackson-annotations/2.4.0
    install -s mvn:com.fasterxml.jackson.core/jackson-databind/2.4.0
    install -s mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/2.4.0
    install -s mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/2.4.0
    
  • build our modules and copy them into Apache Karaf 3.0.1's deploy folder (while container is still running):
    mvn clean package
    cp module*/target/*jar apache-karaf-3.0.1/deploy/
    
When you run the list command in the Apache Karaf 3.0.1 shell, you should see the list of all activated bundles (modules), similar to this one:

Where module-service, module-jax-rs and module-data correspond to the ones we are being developed. By default, all our Apache CXF 3.0.1 services will be available at base URL http://:8181/cxf/api/. It is easy to check by executing cxf:list-endpoints -f command in the Apache Karaf 3.0.1 shell.

Let us make sure our REST layer works as expected by sending couple of HTTP requests. Let us create new person:

curl http://localhost:8181/cxf/api/people -iX POST -d "firstName=Tom&lastName=Knocker&email=a@b.com"

HTTP/1.1 201 Created
Content-Length: 0
Date: Sat, 09 Aug 2014 15:26:17 GMT
Location: http://localhost:8181/cxf/api/people/a@b.com
Server: Jetty(8.1.14.v20131031)

And verify that person has been created successfully:

curl -i http://localhost:8181/cxf/api/people

HTTP/1.1 200 OK
Content-Type: application/json
Date: Sat, 09 Aug 2014 15:28:20 GMT
Transfer-Encoding: chunked
Server: Jetty(8.1.14.v20131031)

[{"email":"a@b.com","firstName":"Tom","lastName":"Knocker"}]

Would be nice to check if database has the person populated as well. With Apache Karaf 3.0.1 shell it is very simple to do by executing just two commands: jdbc:datasources and jdbc:query peopleDb "select * from people".

Awesome! I hope this quite introductory blog post opens yet another piece of interesting technology you may use for developing robust, scalable, modular and manageable software. We have not touched many, many things but these are here for you to discover. The complete source code is available on GitHub.

Note to Hibernate 4.2.x / 4.3.x users: unfortunately, in the current release of Apache Karaf 3.0.1 the Hibernate 4.3.x does work properly at all (as JPA 2.1 is not yet supported) and, however I have managed to run with Hibernate 4.2.x, the container often refused to resolve the JPA-related dependencies.

14 comments:

Unknown said...

Great post! Didn't even know about OSGi. Very interesting, I'll definitely try this out.
Cheer!

Andriy Redko said...

Thanks a lot, Guillaume! I am very glad you found it interesting! It would be my pleasure to assist you if you have any questions or need help!

Best Regards,
Andriy Redko

Bharatkumar Patel said...

Hi, Thanks for such a nice and simple tutorial. I have tried same example to deploy on Talend which uses karaf container, for some reason I am not able to see the services. Could you please let me know if you have any idea please. Thanking you in advance.

Andriy Redko said...

Hi Bharatkumar,

Thanks a lot for your comment. Sure, it would be my pleasure to help you out. Could you please post a version of Karaf you are using?
Thanks!

Best Regards,
Andriy Redko

Bharatkumar Patel said...

Hi Andriy,

Thank you for quick reply.I am using talend 6.1.0 community edition which has karaf version 4.0.2. I have deployed example bundles without any error and started successfully but when try to find endpoints karaf command service:list-endpoints / calling services via browser, getting 'No Services Found'. Please find snippet as below. Thank you very much !

______ __ __
/_ __/__ _/ /__ ___ ___/ /
/ / / _ `/ / -_) _ \/ _ /
/_/ \_,_/_/\__/_//_/\_,_/
(version 6.1.0)

Hit '' for a list of available commands
and '[cmd] --help' for help on a specific command.
Hit '' or 'system:shutdown' to shutdown the TRUN.

karaf@trun()> version
4.0.2

Andriy Redko said...

Hi Bharatkumar,

It turns out that moving the project to Karaf 4.x is a real challenge! Nonetheless, I have created a branch for you, https://github.com/reta/osgi-services/tree/karaf-4.x, which basically adapts the sampleto Karaf 4.x, I tested it on 4.0.2 and 4.0.3, seems to work perfectly. Please give it a try!

As a side note, there is new module extracted out from module-data, module-ds. I run into an issue that it is not possible to define datasource and entity manager in the same blueprint :-( But it is not a big deal I think :)

Let me know if it works for you!
Thanks!

Best Regards,
Andriy Redko

Bharatkumar Patel said...

Hi Andriy,

Thanks for the reply. Appreciated. Yes, I see your test code is working perfectly fine in standalone Karaf. As I mentioned I am trying to run same sample code in talend which uses karaf container and facing issue there. I guess there is some conflict with jar dependencies. While running in talend -6.1.0 version, I am getting following error.

C:\>curl http://localhost:8040/services/api/people -iX POST -d "firstName=Tom&lastName=Knocker&email=a@b.com"
HTTP/1.1 500 Server Error
Date: Tue, 15 Dec 2015 11:07:49 GMT
Content-Type: text/html; charset=ISO-8859-1
Cache-Control: must-revalidate,no-cache,no-store
Content-Length: 4809
Connection: close
Server: Jetty(9.2.10.v20150310)

Reason:
Server Errorjava.lang.ClassCastException: org.apache.aries.transaction.internal.AriesPlatformTransactionManager cannot be cast to javax.transaction.TransactionManager
at Proxy2ebaa715_bcc4_468f_971a_739c8ae217f6.getStatus(Unknown Source)
at org.apache.aries.transaction.TransactionAttribute$4.begin(TransactionAttribute.java:80)
at org.apache.aries.transaction.TxInterceptorImpl.preCall(TxInterceptorImpl.java:58)
at org.apache.aries.blueprint.proxy.Collaborator.preInvoke(Collaborator.java:76)
at Proxy8622764e_040e_4dbe_8249_fb752055c436.save(Unknown Source)
at Proxyad638f98_1525_4dcd_a752_9f20441987b3.save(Unknown Source)
at com.example.services.impl.PeopleServiceImpl.addPerson(PeopleServiceImpl.java:30)
at Proxy54c8529b_ae85_484a_ab2c_d28e7a3de83c.addPerson(Unknown Source)
at com.example.jaxrs.PeopleRestService.addPerson(PeopleRestService.java:47)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)

Thanks for the help. Good stuff, Keep posting !

Andriy Redko said...

Hi Bharatkumar,

That's a very weird error, I have downloaded Talend platform 6.1.0, and tried everything myself, works perfectly fine:

karaf@trun()> version
4.0.2

curl http://localhost:8040/services/api/people -iX POST -d "firstName=Tom&lastName=Knocker&email=a@b.com" --user karaf:karaf
HTTP/1.1 201 Created
Date: Tue, 15 Dec 2015 19:56:56 GMT
Location: http://localhost:8040/services/api/people/a@b.com
Date: Tue, 15 Dec 2015 19:56:56 GMT
Content-Length: 0
Server: Jetty(9.2.10.v20150310)

By any chance, does it help to restart the container?
Thanks.

Best Regards,
Andriy Redko

Bharatkumar Patel said...
This comment has been removed by the author.
Bharatkumar Patel said...

Thanks Andriy, I believe may be I am missing some features to turn on/install in Talend container. Anyways I will give it a try again. Thanks for your help.

Andriy Redko said...

Hi Bharatkumar,

Sure, give it a try. If you still have the problem nonetheless, it would be great if you could share your Talend / Karaf container with me (dropbox or something), so I can reproduce the issue and help you with that. Not sure it is an option for you though. Please let me know!

Thanks and good luck!

Best Regards,
Andriy Redko

Bharatkumar Patel said...

Hi Andriy,

Thanks ! Is is possible get the list of features with version to turn on/install in talend karaf to run example successfully ? I see you have already specified list of features in your blog and github. Just wondering if different features to turn on/install while running on Talend container. Please let me know which JDK version are you using ?
Thank you very much Andriy!

Andriy Redko said...

Hi Bharatkumar,

Sure, the only difference between plain Karaf and Talend installation, I skipped feature:repo-add cxf 3.1.4 and used the default one, which is 3.1.3. But this should not cause the transaction manager issues. Here is what I have:

pax-jetty | 9.2.10.v20150310 |
pax-http-jetty | 4.2.2 |
pax-http | 4.2.2 |

cxf-specs | 3.1.3 |
cxf-jaxb | 3.1.3 |
cxf-abdera | 3.1.3 |
wss4j | 2.1.3 |
cxf-core | 3.1.3 |
cxf-commands | 3.1.3 |
cxf-wsdl | 3.1.3 |
cxf-ws-policy | 3.1.3 |
cxf-ws-addr | 3.1.3 |
cxf-ws-rm | 3.1.3 |
cxf-ws-mex | 3.1.3 |
cxf-ws-security | 3.1.3 |
cxf-rt-security | 3.1.3 |
cxf-rt-security-saml | 3.1.3 |
cxf-http | 3.1.3 |
cxf-http-jetty | 3.1.3 |
cxf-bindings-soap | 3.1.3 |
cxf-jaxws | 3.1.3 |
cxf-jaxrs | 3.1.3 |
cxf-rs-security-xml | 3.1.3 |
cxf-databinding-aegis | 3.1.3 |
cxf-databinding-jaxb | 3.1.3 |
cxf-databinding-xmlbeans | 3.1.3 |
cxf-features-clustering | 3.1.3 |
cxf-features-logging | 3.1.3 |
cxf-features-throttling | 3.1.3 |
cxf-features-metrics | 3.1.3 |
cxf-bindings-corba | 3.1.3 |
cxf-bindings-coloc | 3.1.3 |
cxf-bindings-object | 3.1.3 |
cxf-transports-local | 3.1.3 |
cxf-transports-jms | 3.1.3 |
cxf-transports-udp | 3.1.3 |
cxf-javascript | 3.1.3 |
cxf-frontend-javascript | 3.1.3 |
cxf-xjc-runtime | 3.1.3 |
cxf | 3.1.3 |

aries-proxy | 4.0.2 |
aries-blueprint | 4.0.2 |
feature | 4.0.2 |
shell | 4.0.2 |
shell-compat | 4.0.2 |
deployer | 4.0.2 |
bundle | 4.0.2 |
config | 4.0.2 |
diagnostic | 4.0.2 |
instance | 4.0.2 |
jaas | 4.0.2 |
log | 4.0.2 |
package | 4.0.2 |
service | 4.0.2 |
system | 4.0.2 |
http | 4.0.2 |
jetty | 9.2.10.v20150310 |
kar | 4.0.2 |
webconsole | 4.0.2 |
ssh | 4.0.2 |
management | 4.0.2 |
eventadmin | 4.0.2 |
jasypt-encryption | 4.0.2 |
wrap | 0.0.0 |
tesb-aux-common | 6.1.0 |
tesb-aux-client-rest | 6.1.0 |
transaction-api | 1.2.0 |
transaction | 1.3.0 |
persistence-api | 2.1.0 |
jpa | 2.2.0 |
hibernate | 4.3.6.Final |
jndi | 4.0.2 |
jdbc | 4.0.2 |

Hope it helps!

Best Regards,
Andriy Redko

Bharatkumar Patel said...

Hi Andriy,

Thanks for reply. I have got it worked ! I believe it was problem of Jar conflict. Above mentioned classcastExceptiion went away once I reinstall JDK-8. Earlier I have JDK-7 and JDK-8 two Java installed on my box. I have un installed both and then reinstalled JDK-8 then it started working... Thanks Andriy for your help and time. Keep posting !! Good stuff.

Regards,

Bharatkumar Patel