Skip to content

Commit

Permalink
Jakarta flavor of CXF #5
Browse files Browse the repository at this point in the history
* poerting bootique-cxf-jakarta-core
  • Loading branch information
andrus committed Mar 28, 2024
1 parent da792d7 commit 48beded
Show file tree
Hide file tree
Showing 30 changed files with 1,509 additions and 1 deletion.
75 changes: 75 additions & 0 deletions bootique-cxf-jakarta-core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<!--
Licensed to ObjectStyle LLC under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ObjectStyle LLC licenses
this file to you under the Apache License, Version 2.0 (the
“License”); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
“AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->


# bootique-cxf-core

Provides and configures core CXF components, such as Bus, Extensions, Configurer, Features, Interceptors etc.
It allows you to configure and extend CXF via Guice dependency injection.
This module is not intended to be used by itself, rather in the conjunction with [JAX-WS Server](../bootique-cxf-jaxws-server), [JAX-WS Client](../bootique-cxf-jaxws-client) or [JAX-RS Server](../bootique-cxf-jaxrs) modules.

### Providing CXF features
A [Feature](http://cxf.apache.org/docs/features.html) in CXF is a way of adding capabilities to a Server, Client or Bus. For example, you could add the ability to log messages for each of these objects, by configuring them with a LoggingFeature.
You can provide them in your application module:
```java
class App implements Module {
public void config(Binder binder) {
CxfModule.extend(binder)
.addFeature(LoggingFeature.class)
.addFeature(new GZIPFeature());
}
}
```
### Providing CXF Bus interceptors

[Interceptors](http://cxf.apache.org/docs/interceptors.html) are the fundamental processing unit inside CXF. When a service is invoked, an InterceptorChain is created and invoked. Each interceptor gets a chance to do what they want with the message. This can include reading it, transforming it, processing headers, validating the message, etc.
```java
class App implements Module {
public void config(Binder binder) {
CxfModule.extend(binder)
.contributeBusInterceptors()
.addInInterceptor(new LoggingInInterceptor())
.addOutInterceptor(GZIPOutInterceptor.class);
}
}
```
Bus interceptors will be used both in clients and server endpoints. If you want to provide client-only or server-only interceptors, check [client](../bootique-cxf-jaxws-client) and [server](../bootique-cxf-jaxws-server) modules.

## Advanced configuration
### Providing extensions
CXF uses extensions mechanism to provide core internal components. You can use Guice binding to override any of them:
```java
class App implements Module {
public void config(Binder binder) {
binder.bind(WSDLManager.class).to(CustomWSDLManager.class);
}
}
```

### Configuring beans
CXF provides mechanism for configuring internally created beans. Those implement `org.apache.cxf.configuration.Configurable` interface and include such entities, as `EndpointImpl`, `ServiceImpl`, `HTTPConduit` etc. You can provide your own custom configurer in a module:
```java
class App implements Module {
public void config(Binder binder) {
CxfModule.extend(binder)
.addCustomConfigurer(HTTPConduit.class, CustomHTTPConduitConfigurer.class);
}
}
```

73 changes: 73 additions & 0 deletions bootique-cxf-jakarta-core/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>bootique-cxf-parent</artifactId>
<groupId>io.bootique.cxf</groupId>
<version>3.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>bootique-cxf-jakarta-core</artifactId>

<name>bootique-cxf-jakarta-core: Apache CXF core entities integration with Bootique</name>
<description>
Provides Apache CXF core entities integration with Bootique.
</description>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>jakarta.jws</groupId>
<artifactId>jakarta.jws-api</artifactId>
<version>${jws.jakarta.version}</version>
</dependency>
<dependency>
<groupId>jakarta.xml.ws</groupId>
<artifactId>jakarta.xml.ws-api</artifactId>
<version>${jaxws-api.jakarta.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-core</artifactId>
<version>${cxf.jakarta.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<!-- Compile dependencies -->
<dependency>
<groupId>io.bootique</groupId>
<artifactId>bootique</artifactId>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-core</artifactId>
</dependency>
<dependency>
<groupId>jakarta.jws</groupId>
<artifactId>jakarta.jws-api</artifactId>
</dependency>
<!-- Java 9+ implicit deps -->
<dependency>
<groupId>jakarta.xml.ws</groupId>
<artifactId>jakarta.xml.ws-api</artifactId>
</dependency>

<!-- Unit test dependencies -->
<dependency>
<groupId>io.bootique</groupId>
<artifactId>bootique-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.bootique.cxf;

import org.apache.cxf.Bus;
import org.apache.cxf.bus.CXFBusFactory;

import javax.inject.Inject;
import javax.inject.Provider;
import java.util.Map;

/**
* Bridge to provide Bootique managed factory for all classes, that will attempt to access Bus from static context
*/
public class BQBusFactory extends CXFBusFactory {

@Inject
private Provider<Bus> busProvider;

public BQBusFactory() {
System.out.println("test");
}

@Override
public Bus createBus(Map<Class<?>, Object> e, Map<String, Object> properties) {
return busProvider.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package io.bootique.cxf;

import io.bootique.cxf.conf.MultisourceBeanLocator;
import io.bootique.cxf.interceptor.CxfInterceptorsIn;
import io.bootique.cxf.interceptor.CxfInterceptorsInFault;
import io.bootique.cxf.interceptor.CxfInterceptorsOut;
import io.bootique.cxf.interceptor.CxfInterceptorsOutFault;
import io.bootique.shutdown.ShutdownManager;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.bus.extension.ExtensionManagerBus;
import org.apache.cxf.configuration.ConfiguredBeanLocator;
import org.apache.cxf.configuration.Configurer;
import org.apache.cxf.feature.Feature;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.message.Message;

import javax.inject.Inject;
import javax.inject.Provider;
import java.util.Set;

public class BusProvider implements Provider<Bus> {

private final Configurer configurer;
private final ConfiguredBeanLocator beanLocator;
private final Set<Feature> features;
private final ShutdownManager shutdownManager;
private final Set<Interceptor<? extends Message>> inInterceptors;
private final Set<Interceptor<? extends Message>> outInterceptors;
private final Set<Interceptor<? extends Message>> inFaultInterceptors;
private final Set<Interceptor<? extends Message>> outFaultInterceptors;

@Inject
public BusProvider(
Configurer configurer,
ConfiguredBeanLocator beanLocator,
Set<Feature> features,
ShutdownManager shutdownManager,
@CxfInterceptorsIn Set<Interceptor<? extends Message>> inInterceptors,
@CxfInterceptorsOut Set<Interceptor<? extends Message>> outInterceptors,
@CxfInterceptorsInFault Set<Interceptor<? extends Message>> inFaultInterceptors,
@CxfInterceptorsOutFault Set<Interceptor<? extends Message>> outFaultInterceptors
) {

this.configurer = configurer;
this.beanLocator = beanLocator;
this.features = features;
this.shutdownManager = shutdownManager;
this.inInterceptors = inInterceptors;
this.outInterceptors = outInterceptors;
this.inFaultInterceptors = inFaultInterceptors;
this.outFaultInterceptors = outFaultInterceptors;
}

@Override
public Bus get() {
ExtensionManagerBus bus = new ExtensionManagerBus();

ConfiguredBeanLocator originalLocator = bus.getExtension(ConfiguredBeanLocator.class);

MultisourceBeanLocator multisourceBeanLocator = new MultisourceBeanLocator(beanLocator, originalLocator);

bus.setExtension(multisourceBeanLocator, ConfiguredBeanLocator.class);
bus.setExtension(configurer, Configurer.class);

bus.setFeatures(features);

bus.getInInterceptors().addAll(inInterceptors);
bus.getInFaultInterceptors().addAll(inFaultInterceptors);
bus.getOutInterceptors().addAll(outInterceptors);
bus.getOutFaultInterceptors().addAll(outFaultInterceptors);

bus.initialize();

BusFactory.possiblySetDefaultBus(bus);

return shutdownManager.onShutdown(bus, b -> b.shutdown());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package io.bootique.cxf;

import io.bootique.BQModule;
import io.bootique.ModuleCrate;
import io.bootique.cxf.conf.BQBeanLocator;
import io.bootique.cxf.conf.BqConfigurer;
import io.bootique.cxf.conf.CustomConfigurer;
import io.bootique.di.Binder;
import io.bootique.di.Injector;
import io.bootique.di.Provides;
import io.bootique.di.TypeLiteral;
import org.apache.cxf.Bus;
import org.apache.cxf.configuration.ConfiguredBeanLocator;
import org.apache.cxf.configuration.Configurer;

import javax.inject.Named;
import javax.inject.Singleton;
import java.util.List;
import java.util.Map;

public class CxfModule implements BQModule {

public static CxfModuleExtender extend(Binder binder) {
return new CxfModuleExtender(binder);
}

@Override
public ModuleCrate crate() {
return ModuleCrate.of(this)
.description("Integrates Apache CXF core")
.build();
}

@Override
public void configure(Binder binder) {
CxfModule.extend(binder).initAllExtensions();
binder.bind(Bus.class).toProvider(BusProvider.class).initOnStartup();

// TODO: is this call necessary?
// binder.requestStaticInjection(BqBusFactory.class);
}

@Provides
@Singleton
public Configurer provideConfigurer(
Injector injector,
@Named("custom") Map<TypeLiteral<?>, CustomConfigurer<?>> customConfigurers,
@Named("default") Map<TypeLiteral<?>, CustomConfigurer<?>> defaultConfigurers
) {

Map<TypeLiteral<?>, List<CustomConfigurer<?>>> mergedConfigurers = MapUtils.mergeMaps(
defaultConfigurers,
customConfigurers
);

return new BqConfigurer(injector, mergedConfigurers);
}

@Provides
@Singleton
public ConfiguredBeanLocator provideLocator(Injector injector) {
return new BQBeanLocator(injector);
}
}
Loading

0 comments on commit 48beded

Please sign in to comment.