Showing posts with label Spring Boot. Show all posts
Showing posts with label Spring Boot. Show all posts

Saturday, 29 January 2022

This week 1/2022 - Spring WS client

In this post I'd like to present my reflection after implementing Web Service client in Spring WS. A time ago when I have been implementing a client or a service I did that in Apache CXF but this time to archive organisational standards for new implementation I used Spring WS.

Comparing to Apache CXF, from my perspective Spring WS is easier. It needs only to generate a model classes from WSDL or XSD file. This is important because Spring WS is contact-first implementation (only transform XSD/WSDL to classes, do not support other direction) to avoid incompatibles between different languages and implementations. 

I was a bit surprised that I don't create any Webservice Stub for my client. Only a model classes.

Below are presented a configuration of beans. The wsClient where I injected marshaller and defined interceptors. In my case I created interceptor to signature and encrypt message. 

In method signatureInterceptor is whole interceptor configuration.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Bean
public Client wsClient(final Jaxb2Marshaller marshaller) throws Exception {
    final Client client = new Client("https://example.com/webservice_uri");
    client.setMarshaller(marshaller);
    client.setUnmarshaller(marshaller);
    client.setInterceptors(new ClientInterceptor[]{signatureInterceptor()});
    return client;
}

private ClientInterceptor signatureInterceptor() throws Exception {
    Wss4jSecurityInterceptor wss4jSecurityInterceptor = new Wss4jSecurityInterceptor();
    wss4jSecurityInterceptor.setEnableSignatureConfirmation(true);
    wss4jSecurityInterceptor.setSecurementActions("Signature Encrypt");
    wss4jSecurityInterceptor.setSecurementUsername("securementUsername");
    wss4jSecurityInterceptor.setSecurementPassword("securementPassword");
    wss4jSecurityInterceptor.setSecurementSignatureCrypto(getCryptoFactoryBean().getObject());

    wss4jSecurityInterceptor.setSecurementEncryptionUser("encryption-user");
    wss4jSecurityInterceptor.setSecurementEncryptionParts("{Content}{https://example.com/service}getResponse");
    wss4jSecurityInterceptor.setSecurementEncryptionCrypto(getCryptoFactoryBean().getObject());

    return wss4jSecurityInterceptor;
}

@Bean
public CryptoFactoryBean getCryptoFactoryBean() throws IOException {
    CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
    cryptoFactoryBean.setKeyStorePassword("testKeyStorePassword");
    cryptoFactoryBean.setKeyStoreLocation(new ClassPathResource("some.jks"));
    return cryptoFactoryBean;
}

@Bean
public Jaxb2Marshaller marshaller() {
    final Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    marshaller.setClassesToBeBound(Request.class, Response.class);
    return marshaller;
}


Implementation of ws client extends WebServiceGatewaySupport and implements my custom method "service". In those method I call webService template with uri and request object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class Client extends WebServiceGatewaySupport {

    private final String uri;

    public Client(String uri) {
        this.uri = uri;
    }

    public Response service() {
        return (Response)getWebServiceTemplate()
                .marshalSendAndReceive(uri, new Request());
    }
}

In response I got object which I had to cast to expected type.

To use the model in JDK17 I  generated it by maven plugin org.jvnet.jaxb2.maven2:maven-jaxb2-plugin but it is possible to use others. 

Below an example of plugin configuration to generate a model form wsdl file with possible additional annotations defined in wsdl or binding file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.14.0</version>
    <dependencies>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.6</version>
        </dependency>
    </dependencies>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <schemaLanguage>WSDL</schemaLanguage>
        <schemaDirectory>${project.basedir}/src/main/resources/wsdl</schemaDirectory>
        <schemaIncludes>
            <include>*.wsdl</include>
        </schemaIncludes>
        <args>
            <arg>-Xannotate</arg>
         </args>
        <plugins>
            <plugin>
                <groupId>org.jvnet.jaxb2_commons</groupId>
                <artifactId>jaxb2-basics</artifactId>
                <version>1.11.1</version>
            </plugin>
            <plugin>
                <groupId>org.jvnet.jaxb2_commons</groupId>
                <artifactId>jaxb2-basics-annotate</artifactId>
                <version>1.11.0</version>
            </plugin>
        </plugins>
    </configuration>
</plugin>

And here possible (some of them required) dependences.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-oxm</artifactId>
        <version>5.3.15</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ws</groupId>
        <artifactId>spring-ws-core</artifactId>
        <version>3.1.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ws</groupId>
        <artifactId>spring-ws-security</artifactId>
        <version>3.1.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ws</groupId>
        <artifactId>spring-ws-support</artifactId>
        <version>3.1.2</version>
    </dependency>
    <dependency>
        <groupId>wsdl4j</groupId>
        <artifactId>wsdl4j</artifactId>
        <version>1.6.3</version>
    </dependency>
    <dependency>
        <groupId>org.jvnet.jaxb2_commons</groupId>
        <artifactId>jaxb2-basics-runtime</artifactId>
        <version>1.11.1</version>
    </dependency>
</dependencies>


Resources:

[1] - Wss4jSecurityInterceptor java doc

[2] - Baeldung Example

[3] - spring ws

 

Tuesday, 18 April 2017

This week 7/2017

Spring Boot (v. 1.5.x) is a project which supports developer in creating and boot application. Application created by it integrates with long technology stack list mentioned in project reference guide.
Creation of complex application is very easy. Developer add dependences of starter artefact and application should work with default settings. If he need to change defaults, he can add properties file, add custom annotation or set custom settings in code.
Simple application is ready in a few seconds, there is needed only a custom pom or gradle file and writing a few lines of code - simple class with annotation
@EnableAutoConfiguration
and main method in which is execution of run method of the SpringApplication class.
If there is needed a web application, it is not a problem. Spring Boot supports three web containers Tomcat/Jetty/Undertow. If there is needed something else probably it is not a problem as well list is truly long.

Spring Boot contains additional development tools supporting Http caching, automatic restart of application after source update and few less important things for me. 
In my case, I was most interested in automatic restart and hot swapping. DevTools don't contain solution as good as JRebel and Spring Loaded because they don't reload byte code during runtime but restart part of application. This solution splits class path on the unchangeable paths and changeable. This first is loaded by standard class loader. The second is loaded by loader which is removed during restart and created new one. It is possible to choose jar files which should be replaced during restart.

Spring Boot support loading configuration parameters (@ConfigurationProperties) and validate them during application start.

In the end I can add that there is a page with an application creator. Generator create pom/gladle file with selected technology stack and sample code.