IndexRequest is deprecated - java

I'm using RestHighLevelClient, in the main method I use IndexRequest (this one is closed off because is deprecated). I use 7.10.1 elasticsearch. When I run the program, I have error message below :
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/client/config/RequestConfig
at org.elasticsearch.client.RestClientBuilder.createHttpClient(RestClientBuilder.java:211)
at java.security.AccessController.doPrivileged(Native Method)
at org.elasticsearch.client.RestClientBuilder.build(RestClientBuilder.java:201)
at org.elasticsearch.client.RestHighLevelClient.<init>(RestHighLevelClient.java:291)
at org.elasticsearch.client.RestHighLevelClient.<init>(RestHighLevelClient.java:283)
at com.gihub.simplesteph.kafka.tutorial3.ElasticSearchConsumer.createClient(ElasticSearchConsumer.java:41)
at com.gihub.simplesteph.kafka.tutorial3.ElasticSearchConsumer.main(ElasticSearchConsumer.java:46)
Caused by: java.lang.ClassNotFoundException: org.apache.http.client.config.RequestConfig
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
... 7 more
I need your support to solve my problem, below are code of ElasticSearchConsumer.javaand pom.xml. I tried many recipe but I have the same error.
package com.gihub.simplesteph.kafka.tutorial3;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class ElasticSearchConsumer {
public static RestHighLevelClient createClient(){
// replace with your own credentials
String hostname = "xxxxxxxxxxxxxxxxxxxxxxxx";
String username = "xxxxxxxxxx";
String password = "xxxxxxx";
//don't do if you run a local ES
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
RestClientBuilder builder = RestClient.builder(
new HttpHost(hostname, 443, "https"))
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
#Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
return httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
});
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
public static void main(String[] args) throws IOException {
Logger logger = LoggerFactory.getLogger(ElasticSearchConsumer.class.getName());
RestHighLevelClient client = createClient();
String jsonString = "{ \"foo\": \"bar\" }";
IndexRequest indexRequest = new IndexRequest("twitter", "tweets" ).source(jsonString, XContentType.JSON);
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
String id = indexResponse.getIndex();
logger.info(id);
//close the client gracefully
client.close();
}
}
pom.xml file :
<?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>kafka-beginners-course</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>kafka-consumer-elasticsearch</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-high-level-client -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.10.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
<!-- <scope>test</scope>-->
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
</dependencies>
</project>
Thank you!

NoClassDefFoundError usually means that the dependency was present at compile time, but not at runtime.
You need to make sure that when you run your project it has all the necessary dependencies on the classpath

Add org.apache.httpcomponents dependency in the main module if you have multiple modules in your setup, it worked for me.
And while creating IndexRequest, don't add topic in the constructor,
use it like:
IndexRequest indexRequest = new IndexRequest(
"ur_index"
).source(urJsonString, XContentType.JSON);

Related

IntelliJ, Junit 4 Maven - Cannot resolve symbol assertEquals

Maven JUnit 4.12 dependency is there. Doesn't work with both static and without it. assertEquals is in red/not resolved. Assert. does not show methods.
Tried by adding assertJ library too as dependency. Same issue. In code, I do Assertions.. It doesn't show any methods.
package examples;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import org.junit.Assert;
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;
public class Ch4Test {
private static RequestSpecification requestSpec;
#BeforeClass
public static void createRequestSpec() {
requestSpec = new RequestSpecBuilder().
setBaseUri("http://zippopotam.us").build();
}
private static ResponseSpecification responseSpec;
#BeforeClass
public static void createResponseSpec(){
responseSpec = new ResponseSpecBuilder().
expectStatusCode(200).
expectContentType(ContentType.JSON).
build();
}
#Test
public void requestUsZip(){
given().
spec(requestSpec).
when().
get("us/90210").
then().
spec(responseSpec).
and().
assertThat().
body("places[0].'place name'", equalTo("Beverly Hills"));
}
#Test
public void requestUsZipExtractPlaceName(){
String placeName =
given().
spec(requestSpec).
when().
get("us/90210").
then().
extract().
path("places[0].'place name'");
}
// Assert.assertEquals("Beverly Hills", placeName);
}
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>RestAssuredLearn</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.3.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.tngtech.java/junit-dataprovider -->
<dependency>
<groupId>com.tngtech.java</groupId>
<artifactId>junit-dataprovider</artifactId>
<version>1.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.23.1</version>
<scope>test</scope>
</dependency>
The issue isn't the import of Assert (which is fine), but the fact you have the call to Assert.assertEquals outside of any method - and you can't have such a statement directly under a class. Move it up into requestUsZipExtractPlaceName, and you should be fine:
#Test
public void requestUsZipExtractPlaceName(){
String placeName =
given().
spec(requestSpec).
when().
get("us/90210").
then().
extract().
path("places[0].'place name'");
Assert.assertEquals("Beverly Hills", placeName); // Move here, inside the method
}
// Instead of here

java: package MongoClientOptions does not exist

I am trying to upgrade the log4j version to 2.16.0 with the springboot version 2.6.2 .After upgrading My code is failing with the below error while connecting to MongoDB database .Which version of spring-data-mongodb is compatible with the springboot version 2.6.2 .Could anyone suggest which version of Mongodb is the proper version for the below Java code . Any help would be appreciated
Error:(51,27) java: package MongoClientOptions does not exist . My pom.xml as like below
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
<relativePath/>
</parent>
<groupId>com.sample</groupId>
<artifactId>SampleService</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SampleService</name>
<description>Project for Service</description>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<surefire-plugin.version>2.22.0</surefire-plugin.version>
<log4j2.version>2.17.0</log4j2.version>
</properties>
<dependencyManagement>
<dependencies>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.2.3</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.2.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestone</id>
<name>Spring Maven MILESTONE Repository</name>
<url>https://repo.spring.io/libs-milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<systemProperties>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
</systemProperties>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.6.2</version>
<configuration>
<arguments>
<source>1.8</source>
<target>1.8</target>
<uberJar>true</uberJar>
</arguments>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
My Application Java Code :
package com.sample;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;
#SpringBootApplication
public class Application implements CommandLineRunner {
private static final Logger LOG = LoggerFactory.getLogger(Application.class);
//private String uri;
private String database;
private String host;
private String username;
private String password;
private int port;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public void run(String... args) throws Exception {
LOG.info("Application Running.......");
}
public #Bean
com.mongodb.MongoClient mongoClient() {
MongoClientOptions.Builder mongoClientOptions = MongoClientOptions.builder().sslInvalidHostNameAllowed(true)
.sslEnabled(true).applicationName("Sample-Service");
try {
KeyStore keystore = KeyStore.getInstance("JKS");
try (InputStream in = new FileInputStream("/mnt/secrets/keystore.jks")) {
keystore.load(in, "password".toCharArray());
} catch (IOException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
}
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keystore, "password".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
mongoClientOptions.sslContext(sslContext);
} catch (NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException | KeyManagementException e) {
e.printStackTrace();
}
MongoClientOptions mops = mongoClientOptions.build();
MongoCredential mongoCredential = MongoCredential.createCredential(username, database, password.toCharArray());
MongoClient mongoClient = new MongoClient(new ServerAddress(host, port), mongoCredential, mops);
return mongoClient;
}
// #Value("${spring.data.mongodb.uri}")
// public void setUri(String uri) {
// this.uri = uri;
// }
public String getDatabase() {
return database;
}
#Value("${spring.data.mongodb.authentication-database}")
public void setDatabase(String database) {
this.database = database;
}
public String getHost() {
return host;
}
#Value("${spring.data.mongodb.host}")
public void setHost(String host) {
this.host = host;
}
public String getUsername() {
return username;
}
#Value("${spring.data.mongodb.username}")
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
#Value("${spring.data.mongodb.password}")
public void setPassword(String password) {
this.password = password;
}
public int getPort() {
return port;
}
#Value("${spring.data.mongodb.port}")
public void setPort(int port) {
this.port = port;
}
}
Your pom.xml is asking for mongodb-driver-sync 4.2.3. Some of the classes moved or were retired in the 4.x version; for example, com.mongodb.MongoClient is now com.mongodb.client.MongoClient. Your code appears to be 3.x API compatible. You will have to spend a few minutes to rework your options setup to be compatible with the new classes. See the API docs https://mongodb.github.io/mongo-java-driver/4.2/apidocs for more.
UPDATED
I took a look and the migration to the new classes is not trivial and I hadn't used non-connection string based material in a long time so I reworked the critical parts of the code above. Note that credential, sslsettings, and connectionstring objects are designed to be built in slightly different ways which can lead to some confusion at first.
import com.mongodb.client.MongoClient; // interface
import com.mongodb.client.MongoClients; // factory
import com.mongodb.MongoClientSettings; // yes, *not* in the .client hierarchy!
import com.mongodb.MongoCredential;
import com.mongodb.ConnectionString;
MongoCredential credentials = MongoCredential.createCredential(
"USER", "ADMIN_DB", "PASSWORD".toCharArray());
String conns = String.format("mongodb://%s:%d/?replicaSet=rs0", "localhost", 27017);
MongoClientSettings.Builder mcsb = MongoClientSettings.builder();
MongoClientSettings mcs = mcsb
.applicationName("Sample-Service")
.credential(credentials)
.applyToSslSettings(sslb ->
sslb.enabled(true)
.invalidHostNameAllowed(true))
.applyConnectionString(new ConnectionString(conns))
.build();
MongoClient client = MongoClients.create(mcs);
I think you should upgrade your dependencies. Please see the version and pom
Please try:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.3.0</version>
</dependency>
<!-- reactive: Do you really need it? -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.4.0</version>
</dependency>
Suggestion
If you use spring-boot, and you can try org.springframework.boot:spring-boot-starter-data-mongodb to auto config.

RESTEASY003900: Unable to find a public constructor - What am I missing?

In another project I have an embedded Jetty server and after updating the Jetty version to anything above 9.4.29 I got an error.
So I went to create a new project to start finding out what caused this error.
However... I didn't even get to the same error as the new project fails with:
javax.servlet.ServletException: org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher-7b2bbc3==org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher#b539e71f{jsp=null,order=-1,inst=true,async=true,src=EMBEDDED:null,STARTED}
at jetty.test.JettyTest.hello(JettyTest.java:78)
Caused by: java.lang.IllegalArgumentException: RESTEASY003900: Unable to find a public constructor for provider class jetty.test.JettyTest$TestApplication
at jetty.test.JettyTest.hello(JettyTest.java:78)
I have the feeling that I'm missing something obviously... Any help is appreciated.
Thanks
My test class:
package jetty.test;
import static io.restassured.RestAssured.given;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.specification.RequestSpecification;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.ServletConfig;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.eclipse.jetty.server.Server;
import org.junit.jupiter.api.Test;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher;
public class JettyTest {
#Path("/health")
public class HealthResource {
#GET
#Path("/")
#Produces(MediaType.TEXT_PLAIN)
public Response getHealth() {
return Response.ok().entity("good").build();
}
}
#ApplicationPath("/api")
public class TestApplication extends Application {
HashSet<Object> singletons = new HashSet<>();
public TestApplication() {
super();
}
public TestApplication(#Context ServletConfig servletConfig) {
singletons.add(HealthResource.class);
}
#Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<>();
set.add(HealthResource.class);
return set;
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
#Test
public void hello() throws Exception {
Server server = new Server(8082);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
final ServletHolder servletHolder = new ServletHolder(new HttpServletDispatcher());
servletHolder.setInitParameter("resteasy.scan", "true");
servletHolder.setInitParameter("resteasy.servlet.mapping.prefix", "/api/*");
servletHolder.setInitParameter("javax.ws.rs.Application", TestApplication.class.getName());
context.addServlet(servletHolder, "/api/*");
server.start();
RequestSpecification spec = new RequestSpecBuilder()
.setBaseUri("http://localhost:8082/").build();
given().spec(spec).when().get("/api/res").then().statusCode(200);
}
}
And my pom.xml:
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>JettyTestProject</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.43.v20210629</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.4.43.v20210629</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.4</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-servlet-initializer</artifactId>
<version>4.7.1.Final</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
</project>
The definition you have of ...
public class JettyTest {
....
public class TestApplication extends Application {
means you cannot create TestApplication without first creating the JettyTest.
Just change the inner class to static, that should be enough.
public class JettyTest {
....
public static class TestApplication extends Application {

Basic Spring based WSSecurity client gets a null response

I've been following this tutorial to learn how to develop a basic spring client and server application using wssecurity (certificates).
The demo works beautifully, but i need to deploy my application on a wildfly server, so i had to change the example a bit in order to avoid the embedded tomcat, the changes are as follows:
pom.xml
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.memorynotfound.spring.ws</groupId>
<artifactId>ws-security-certificate-wss4j-security-interceptor</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>SPRING-WS - ${project.artifactId}</name>
<url>http://memorynotfound.com</url>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-security</artifactId>
</dependency>
<dependency>
<groupId>org.apache.ws.security</groupId>
<artifactId>wss4j</artifactId>
<version>1.6.19</version>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<source>src/main/resources/xsd</source>
</sources>
<generatePackage>com.memorynotfound.beer</generatePackage>
</configuration>
</plugin>
</plugins>
</build>
RunServer.java
package com.memorynotfound.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
#SpringBootApplication
public class RunServer extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(RunServer.class);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<RunServer> applicationClass = RunServer.class;
}
BeerEndpoint.java
package it.corvallis.soap.endpoint;
import com.memorynotfound.beer.Beer;
import com.memorynotfound.beer.GetBeerRequest;
import com.memorynotfound.beer.GetBeerResponse;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
import org.springframework.ws.soap.server.endpoint.annotation.SoapAction;
#Endpoint
public class BeerEndpoint {
public static final String NAMESPACE_URI = "http://memorynotfound.com/beer";
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "getBeerRequest")
#SoapAction("http://localhost:8080/ws/beers")
#ResponsePayload
public GetBeerResponse getBeer(#RequestPayload GetBeerRequest request) {
GetBeerResponse beerResponse = new GetBeerResponse();
Beer beer = new Beer();
beer.setId(request.getId());
beer.setName("Beer name");
beerResponse.setBeer(beer);
return beerResponse;
}
}
I deployed the server application on my wildfly and i tried to call it using the same client application used in the tutorial. The service seems to answer correctly, the beerResponse object is correctly istantiated, but, as soon as the object is being sent back to the the client, i see it's NULL.
What am i missing?
Thanks in advance
Oh well, next time i'll read better. At the same link of my first post, a guy asked the same question in the comments, here is the solution: add a callBackHandler to the client configuration, and modify the securityInterceptor to use this handler.
SoapClientConfig.java
package com.memorynotfound.client;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.stereotype.Component;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor;
import org.springframework.ws.soap.security.wss4j2.callback.KeyStoreCallbackHandler;
import org.springframework.ws.soap.security.wss4j2.support.CryptoFactoryBean;
import java.io.IOException;
#Configuration
public class SoapClientConfig {
#Bean
public Wss4jSecurityInterceptor securityInterceptor() throws Exception {
Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();
// set security actions
securityInterceptor.setSecurementActions("Timestamp Signature Encrypt");
// sign the request
securityInterceptor.setSecurementUsername("client");
securityInterceptor.setSecurementPassword("changeit");
securityInterceptor.setSecurementSignatureCrypto(getCryptoFactoryBean().getObject());
// encrypt the request
securityInterceptor.setSecurementEncryptionUser("server-public");
securityInterceptor.setSecurementEncryptionCrypto(getCryptoFactoryBean().getObject());
securityInterceptor.setSecurementEncryptionParts("{Content}{http://memorynotfound.com/beer}getBeerRequest");
// sign the response
securityInterceptor.setValidationActions("Signature Encrypt");
securityInterceptor.setValidationSignatureCrypto(getCryptoFactoryBean().getObject());
securityInterceptor.setValidationDecryptionCrypto(getCryptoFactoryBean().getObject());
securityInterceptor.setValidationCallbackHandler(securityCallbackHandler());
return securityInterceptor;
}
#Bean
public CryptoFactoryBean getCryptoFactoryBean() throws IOException {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setKeyStorePassword("changeit");
cryptoFactoryBean.setKeyStoreLocation(new ClassPathResource("client.jks"));
return cryptoFactoryBean;
}
#Bean
public Jaxb2Marshaller getMarshaller(){
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.memorynotfound.beer");
return marshaller;
}
#Bean
public BeerClient getBeerClient() throws Exception {
BeerClient beerClient = new BeerClient();
beerClient.setMarshaller(getMarshaller());
beerClient.setUnmarshaller(getMarshaller());
beerClient.setDefaultUri("http://localhost:8080/ws/beers");
ClientInterceptor[] interceptors = new ClientInterceptor[]{securityInterceptor()};
beerClient.setInterceptors(interceptors);
return beerClient;
}
#Bean
public KeyStoreCallbackHandler securityCallbackHandler(){
KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler();
callbackHandler.setPrivateKeyPassword("changeit");
return callbackHandler;
}
}

Spring RestTemplate & AsyncRestTemplate with Netty4 hangs forever

Very simple setup:
pom.xml
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo-rest-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo-rest-client</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.5.Final</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-buffer</artifactId>
<version>4.1.5.Final</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>9.3.1</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-hystrix</artifactId>
<version>9.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
And a test case to demonstrate different usages of AsyncRestTemplate:
SampleTests.java
package com.example;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandProperties;
import feign.RequestLine;
import feign.hystrix.HystrixFeign;
import feign.hystrix.SetterFactory;
import org.junit.Test;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.Netty4ClientHttpRequestFactory;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.client.AsyncRestTemplate;
import org.springframework.web.client.RestTemplate;
public class SampleTests {
private static final String URL = "https://api.github.com/users/octocat";
private static final int DEFAULT_SLEEP_MILLIS = 20;
private static final int DEFAULT_TIMEOUT = 10000;
#Test(timeout = DEFAULT_TIMEOUT)
public void syncRestNetty() throws Exception {
RestTemplate restTemplate = new RestTemplate(new Netty4ClientHttpRequestFactory());
ResponseEntity<String> response = restTemplate.getForEntity(URL, String.class);
System.out.println("response = " + response);
}
#Test(timeout = DEFAULT_TIMEOUT)
public void asyncRestNetty() throws Exception {
AsyncRestTemplate restTemplate = new AsyncRestTemplate(new Netty4ClientHttpRequestFactory());
ListenableFuture<ResponseEntity<String>> listenableFuture = restTemplate.getForEntity(URL, String.class);
listenableFuture.addCallback(result -> System.out.println("result = " + result), Throwable::printStackTrace);
while (!listenableFuture.isDone()) {
Thread.sleep(DEFAULT_SLEEP_MILLIS);
}
System.out.println("the end");
}
#Test
public void asyncRestOkHttp() throws Exception {
AsyncRestTemplate restTemplate = new AsyncRestTemplate(new OkHttp3ClientHttpRequestFactory());
ListenableFuture<ResponseEntity<String>> listenableFuture = restTemplate.getForEntity(URL, String.class);
listenableFuture.addCallback(result -> System.out.println("result = " + result), Throwable::printStackTrace);
while (!listenableFuture.isDone()) {
Thread.sleep(DEFAULT_SLEEP_MILLIS);
}
System.out.println("the end");
}
#Test
public void asyncRestHystrixFeign() throws Exception {
GitHub gitHub = HystrixFeign.builder()
.setterFactory((target, method) -> new SetterFactory.Default().create(target, method).andCommandPropertiesDefaults(HystrixCommandProperties.defaultSetter().withExecutionTimeoutInMilliseconds(10000)))
.target(GitHub.class, "https://api.github.com");
HystrixCommand<String> command = gitHub.octocatAsync();
command.toObservable().subscribe(result -> System.out.println("result = " + result), Throwable::printStackTrace);
while (!command.isExecutionComplete()) {
Thread.sleep(DEFAULT_SLEEP_MILLIS);
}
System.out.println("command.getExecutionTimeInMilliseconds() = " + command.getExecutionTimeInMilliseconds());
System.out.println("the end");
}
interface GitHub {
#RequestLine("GET /users/octocat")
HystrixCommand<String> octocatAsync();
}
}
When trying to run the tests which use Netty they just hang forever. (To see this please remove the JUnit timeout constraint). But if I run the exact same code with other clients everything works as expected.
I have tried different versions of Spring Boot and Netty but did not succeed. And from the logs everything looks ok.
What am I missing here?
EDIT:
Opened a ticket https://jira.spring.io/browse/SPR-14744 as suggested on Spring Gitter
EDIT-2:
Answer from Brian Clozel helped me find the issue which is related to Netty not realizing the server sent an empty response (a particular case with Github API and plain http) so I am marking it as accepted.
Can you try to configure your request factory with a Netty Sslcontext?
Netty4ClientHttpRequestFactory nettyFactory = new Netty4ClientHttpRequestFactory();
nettyFactory.setSslContext(SslContextBuilder.forClient().build());
AsyncRestTemplate restTemplate = new AsyncRestTemplate(nettyFactory);
Without that context, the client is trying to send plaintext requests to the https endpoint; in that case, you're probably getting an HTTP 400 response.
In your example code, the throwable should be an instance of HttpClientErrorException, and you could get that information by logging the response status or its body with exception.getResponseBodyAsString().

Categories