Skip to content

Quarkus CXF Extension to support SOAP based web services.

License

Notifications You must be signed in to change notification settings

neXus1987/quarkiverse-cxf

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

85 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CXF Extension for Quarkus

All Contributors

Build Maven Central License

SOAP (Simple Object Access Protocol) is a normalized exchange protocol based on XML, predating the era of REST services.

This extension enables you to develop web services that consume and produce SOAP payloads using the Apache CXF libraries.

Contributors ✨

Thanks goes to these wonderful people (emoji key):


shumonsharif

💻 🚧

dufoli

💻 🚧

dufgui

💻 🚧

This project follows the all-contributors specification. Contributions of any kind welcome!

Configuration

After configuring quarkus BOM:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-bom</artifactId>
            <version>${insert.newest.quarkus.version.here}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

You can just configure the quarkus-cxf extension by adding the following dependency:

<dependency>
    <groupId>io.quarkiverse.cxf</groupId>
    <artifactId>quarkus-cxf</artifactId>
    <version>${latest.release.version}</version>
</dependency>

Creating a SOAP Web service

In this example, we will create an application to manage a list of fruits.

First, let's create the Fruit bean as follows:

package org.acme.cxf;

import java.util.Objects;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlType(name = "Fruit")
@XmlRootElement
public class Fruit {

    private String name;

    private String description;

    public Fruit() {
    }

    public Fruit(String name, String description) {
        this.name = name;
        this.description = description;
    }

    public String getName() {
        return name;
    }

    @XmlElement
    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    @XmlElement
    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Fruit)) {
            return false;
        }

        Fruit other = (Fruit) obj;

        return Objects.equals(other.getName(), this.getName());
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.getName());
    }
}

Now, create the org.acme.cxf.FruitWebService class as follows:

package org.acme.cxf;

import java.util.Set;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

@WebService
public interface FruitWebService {

    @WebMethod
    Set<Fruit> list();

    @WebMethod
    Set<Fruit> add(Fruit fruit);

    @WebMethod
    Set<Fruit> delete(Fruit fruit);
}

Then, create the org.acme.cxf.FruitWebServiceImpl class as follows:

package org.acme.cxf;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Set;

import javax.jws.WebService;

@WebService(endpointInterface = "org.acme.cxf.FruitWebService")
public class FruitWebServiceImpl implements FruitWebService {

    private Set<Fruit> fruits = Collections.newSetFromMap(Collections.synchronizedMap(new LinkedHashMap<>()));

    public FruitWebServiceImpl() {
        fruits.add(new Fruit("Apple", "Winter fruit"));
        fruits.add(new Fruit("Pineapple", "Tropical fruit"));
    }

    @Override
    public Set<Fruit> list() {
        return fruits;
    }

    @Override
    public Set<Fruit> add(Fruit fruit) {
        fruits.add(fruit);
        return fruits;
    }

    @Override
    public Set<Fruit> delete(Fruit fruit) {
        fruits.remove(fruit);
        return fruits;
    }
}

The implementation is pretty straightforward and you just need to define your endpoints using the application.properties.

quarkus.cxf.path=/cxf
quarkus.cxf.endpoint."/fruit".implementor=org.acme.cxf.FruitWebServiceImpl

The following sample curl command can be used to test your Fruit service.

curl -X POST "http://localhost:8080/cxf/fruit" \
 -H 'Content-Type: text/xml' \
 -H 'SOAPAction:' \
 -d '
 <soapenv:Envelope 
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:cxf="http://cxf.acme.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <cxf:list/>
   </soapenv:Body>
</soapenv:Envelope>'

Creating a SOAP Client

In order to support a SOAP client, register the endpoint URL and the service endpoint interface (same as the server) with the following configuration:

quarkus.cxf.endpoint."/fruit".client-endpoint-url=http://localhost:8080/
quarkus.cxf.endpoint."/fruit".service-interface=org.acme.cxf.FruitWebService

Then inject the client as shown below to use it. Note that the Quarkus container must instantiate the client, ie. the client must be injected in a class which is managed and instantiated by the container. If you need a main, you can use the QuarkusMain annotation (cf https://quarkus.io/guides/lifecycle).

public class MySoapClient {

    @Inject
    FruitWebService clientService;

    public int getCount() {
        return clientService.count();
    }
}

If MySoapClient is not handled by the container but is instantiated by a main you have to use:

public class MySoapClient {

    FruitWebService clientService = CDI.current().select(FruitWebService.class).get();;

    public int getCount() {
        return clientService.count();
    }
}

Native Mode Limitations

  • The native mode is currently in beta (java 8 and java 11 are both supported). Kindly open an issue if you have an issue.

Advanced configuration

Interceptors and features can be added to client/server thanks to :

  • annotation
  • configuration file

On cxf website,a full list of Cxf embeded interceptors and Cxf embeded features are available, but you can implement a custom one.

Annotation

Annotations can be put on the service interface or implementor class.

@org.apache.cxf.feature.Features (features = {"org.apache.cxf.feature.LoggingFeature"})
@org.apache.cxf.interceptor.InInterceptors (interceptors = {"com.example.Test1Interceptor" })
@org.apache.cxf.interceptor.InFaultInterceptors (interceptors = {"com.example.Test2Interceptor" })
@org.apache.cxf.interceptor.OutInterceptors (interceptors = {"com.example.Test1Interceptor" })
@org.apache.cxf.interceptor.InFaultInterceptors (interceptors = {"com.example.Test2Interceptor","com.example.Test3Intercetpor" })
@WebService(endpointInterface = "org.apache.cxf.javascript.fortest.SimpleDocLitBare",
            targetNamespace = "uri:org.apache.cxf.javascript.fortest")
public class SayHiImplementation implements SayHi {
   public long sayHi(long arg) {
       return arg;
   }
   //...
}

Configuration

Else, you can use quarkus configuration file. Feature and interceptor will be try with CDI first and if no bean found, the constructor with no param will be used.

quarkus.cxf.endpoint."/greeting".features=org.apache.cxf.feature.LoggingFeature
quarkus.cxf.endpoint."/greeting".in-interceptors=com.example.MyInterceptor
quarkus.cxf.endpoint."/greeting".out-interceptors=com.example.MyInterceptor
quarkus.cxf.endpoint."/greeting".in-fault-interceptors=com.example.MyInterceptor
quarkus.cxf.endpoint."/greeting".out-fault-interceptors=com.example.MyInterceptor

About

Quarkus CXF Extension to support SOAP based web services.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 100.0%