DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • Spring, IoC Containers, and Static Code: Design Principles
  • Spring IoC Container With XML
  • Building Microservices With[out] Spring Boot
  • Docker and Kubernetes Transforming Modern Deployment

Trending

  • Agile Estimation: Techniques and Tips for Success
  • Development of Custom Web Applications Within SAP Business Technology Platform
  • Hugging Face Is the New GitHub for LLMs
  • Continuous Integration vs. Continuous Deployment
  1. DZone
  2. Software Design and Architecture
  3. Cloud Architecture
  4. Exporting Camel Endpoints as OSGi Services

Exporting Camel Endpoints as OSGi Services

John Georgiadis user avatar by
John Georgiadis
·
Jun. 16, 14 · Interview
Like (0)
Save
Tweet
Share
7.94K Views

Join the DZone community and get the full member experience.

Join For Free

Access to OSGi services through a bus

It is often useful to proxy calls to OSGi services through a service bus.

The bus could be used to log incoming calls, adapt/filter the call arguments and the result, transparently forward requests to a remote OSGi container, broadcast to several remote containers or forward to the more powerful Fabric8 endpoints.

Exporting a regular interface to a Camel endpoint is key to this functionality.


Figure 1: Direct service binding


Figure 2: Binding to a Camel proxy

Camel Bean Invocation

Camel allows to wrap calls to interfaces in BeanInvocation objects within Exchanges and then send them through endpoints such as JMS, HTTP, etc.

Camel supports 3 approaches to bean invocation:

  • The bean component which invokes a bean in the bean registry (e.g. Blueprint)
  • POJO producing where proxies that automate the bean invocation are injected through annotations.
  • Spring remoting where the proxies used in POJO producing are created explicitly.

Spring Remoting

We’ll employ Spring remoting to explicitly create service proxies linked to Camel endpoints and export these proxies as OSGi services in the Blueprint container.

Given the following interface:

interface TaskManager {
    Task save(Task task);
    void delete(String id);
    Task find(String id);
}

The Blueprint container implementing the TaskManager service makes it available through Camel endpoint activemq:queue:io.modio.blog.osgi.camel.proxy:

<blueprint default-activation="eager"
    xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     
    <bean id="taskManager"
        class="io.modio.blog.osgi.camel.proxy.impl.TaskManagerImpl"/>
 
    <camelContext id="camelContext"
        xmlns="http://camel.apache.org/schema/blueprint">
        <route>
            <from uri="activemq:queue:io.modio.blog.osgi.camel.proxy"/>
            <to uri="bean:taskManager"/>
        </route>
    </camelContext>
 
</blueprint>

The proxy to the TaskManager service can be in the same or a different Blueprint container:

<blueprint default-activation="eager"
    xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 
    <camelContext id="camelContext"
        xmlns="http://camel.apache.org/schema/blueprint">
        <proxy id="taskManagerProxy"
            serviceUrl="activemq:queue:io.modio.blog.osgi.camel.proxy"
            serviceInterface="io.modio.blog.osgi.camel.proxy.TaskManager"/>
    </camelContext>
     
    <service interface="io.modio.blog.osgi.camel.proxy.TaskManager"
        ref="taskManagerProxy"/>
 
</blueprint>

Alternatively if the proxy is defined outside the camel context then the blueprint container and camel context ID need to be set explicitly and afterPropertiesSet() needs to be called:

<blueprint default-activation="eager"
    xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 
    <camelContext id="camelContext"
        xmlns="http://camel.apache.org/schema/blueprint">
    </camelContext>
     
    <bean id="taskManagerProxyFactory" init-method="afterPropertiesSet"
        class="org.apache.camel.blueprint.CamelProxyFactoryBean">
        <property name="serviceUrl"
             value="activemq:queue:io.modio.blog.osgi.camel.proxy"/>
        <property name="serviceInterface"
            value="io.modio.blog.osgi.camel.proxy.TaskManager"/>
        <property name="camelContextId" value="camelContext"/>
        <property name="blueprintContainer" ref="blueprintContainer"/>
    </bean>
    
    <service interface="io.modio.blog.osgi.camel.proxy.TaskManager">
        <bean factory-ref="taskManagerProxyFactory" factory-method="getObject"/>
    </service>
 
</blueprint>

The Blueprint container on the consuming side is:

<blueprint default-activation="eager"
    xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 
    <reference id="taskManager"
        interface="io.modio.blog.osgi.camel.proxy.TaskManager"/>
     
    <bean id="driver" class="io.modio.blog.osgi.camel.proxy.Driver">
        <property name="taskManager" ref="taskManager"/>
    </bean>
         
</blueprint>

Blueprint service reference semantics

As powerful as it is, this technique also has a notable side effect. Placing the proxy in a different Blueprint container than the service implementation breaks the semantics of Blueprint service references: the proxy service may be available while the real service may be not.

This will affect both the bootstrapping of the service consumer Blueprint container and the semantics of the calls to the service when the underlying service is not available:

   Direct Service Binding Binding to a Camel Proxy 
 Service is unavailable during initialization phase.

The blueprint container initialization will block until the required service becomes available.
The blueprint container will complete initialization and bind to the proxy.
 Service becomes unavailable after initialization phase. Call to the service reference will block until the service becomes available again or a timeout occurs in which case a ServiceUnavailableException exception is thrown.
The blueprint container will call the proxy. The behavior of the call will depend on the Camel routing setup. E.g.
  • An asynchronous call that posts to a queue will complete (however the message will be left in the queue until the backend service is available to consume it).
  • A synchronous call that posts to a queue expecting a reply will block.
  • A call that delegates to a REST API that is not available, will result in an exception.

Blueprint's approach to service references has received a lot of criticism recently in favor of declarative services (DS). E.g. check the discussions regarding the migration of Fabric8 from Blueprint to DS or the (expected?) migration of Apache Karaf core 4.x from Blueprint to DS. However, in this particular case, DS is also affected because communication through the bus bypasses the OSGi service lookup.
Container Spring Framework

Published at DZone with permission of John Georgiadis. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Spring, IoC Containers, and Static Code: Design Principles
  • Spring IoC Container With XML
  • Building Microservices With[out] Spring Boot
  • Docker and Kubernetes Transforming Modern Deployment

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: