javajax-rscxfapache-karaf

Karaf, cxf and jax-rs - No services have been found


When I install and start the bundle, nothing happens, no output to the console and bundle:list reports it as "Active". I've tried using blueprint-web feature and I was getting No resource classes found exception in logs.

My setup:

<dependencies>
   <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-frontend-jaxrs</artifactId>
      <version>${cxf.version}</version>
   </dependency>
   <dependency>
      <groupId>javax.ws.rs</groupId>
      <artifactId>jsr311-api</artifactId>
      <version>1.1.1</version>
   </dependency>
   <dependency>
      <groupId>org.osgi</groupId>
      <artifactId>osgi.core</artifactId>
      <version>8.0.0</version>
      <scope>provided</scope>
   </dependency>
   <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-transports-http-jetty</artifactId>
      <version>${cxf.version}</version>
   </dependency>
   <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-transports-http</artifactId>
      <version>${cxf.version}</version>
   </dependency>
</dependencies>

I'm using maven bundle plugin:

<plugin>
      <artifactId>maven-bundle-plugin</artifactId>
      <extensions>true</extensions>
      <configuration>
         <instructions>
            <Embed-Dependency>*;scope=compile|runtime;inline=false;artifactId=*</Embed-Dependency>
            <Embed-Transitive>true</Embed-Transitive>
            <Bundle-SymbolicName>${pom.groupId}.${pom.artifactId}</Bundle-SymbolicName>
            <Bundle-Name>${pom.name}</Bundle-Name>
            <Bundle-Version>${pom.version}</Bundle-Version>
            <Export-Package>my.base.package.*</Export-Package>
            <Import-Package>javax.ws.rs.*
                            javax.jws.*
                            *
            </Import-Package>
         </instructions>
      </configuration>
   </plugin>

OSGI-INF/blueprint.xml:

    <cxf:bus>
        <cxf:features>
            <cxf:logging/>
        </cxf:features>
    </cxf:bus>

    <jaxrs:server id="myService" address="/test">
        <jaxrs:serviceBeans>
            <ref component-id="myServiceBean" />
        </jaxrs:serviceBeans>
    </jaxrs:server>

    <bean id="myServiceBean" class="my.base.package.impl.MyServiceImpl"/>

MyServiceImpl.java

@Path("/")
public class MyServiceImpl implements MyService{
    public AccountStorageServiceImpl() {
        System.out.println("MyService starting...");
    }

    @Path("/hello")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Override
    public String hello() {
        return "Hello World!";
    }
}

I had annotations in the interface at first but moved to the impl class hoping it would help(it didn't). Is there some additional configuration/feature that I'm missing?


Solution

  • As is turns out, project setup is not as hard as it seemed to be. Only one dependency is required:

            <dependency>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-rt-frontend-jaxrs</artifactId>
                <version>${cxf.version}</version>
                <scope>compile</scope>
            </dependency>
    

    And the annotations can be on the interface, should also add annotation @Resource for it to get picked up by cxf:

    @Resource
    @Path("/")
    public interface MyService {
        @Path("/hello")
        @GET
        @Produces(MediaType.APPLICATION_JSON)
        String hello();
    }
    

    (annotations should be from javax.*)

    Complete setup in case someone stumbles upon this question:

    1. feature:repo-add cxf
    2. feature:install cxf blueprint-web
    3. bundle:install {bundle}
    4. bundle:start {bundle-number}

    Complete maven-bundle plugin config:

    <plugin>
       <groupId>org.apache.felix</groupId>
       <artifactId>maven-bundle-plugin</artifactId>
       <version>5.1.9</version>
       <extensions>true</extensions>
       <configuration>
          <instructions>
             <Embed-Dependency>*;scope=compile|runtime;inline=false;artifactId=*</Embed-Dependency>
             <Embed-Transitive>false</Embed-Transitive>
             <Bundle-SymbolicName>${pom.groupId}.${pom.artifactId}</Bundle-SymbolicName>
             <Bundle-Name>${pom.name}</Bundle-Name>
             <Bundle-Version>${pom.version}</Bundle-Version>
             <Export-Package>my.package.*</Export-Package>
             <Import-Package>*</Import-Package>
          </instructions>
       </configuration>
    </plugin>