Connecting to Solr 1.4 with SolrJ client connector 3.6 - java

How do I connect to Solr 1.4 search server configured with Basic Auth using the SolrJ 3.6 connector?

Based on the instructions on using SolrJ :
Fetch relevant dependencies for e.g. using maven:
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.1.2</version>
</dependency>
A sample application connecting to Solr 1.4 using SolrJ 3.6 with the latest Apache Http Components http client to negotiate Basic Auth:
import java.io.IOException;
import java.util.Iterator;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HttpContext;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
/**
* Sample app
*
*/
public class App
{
public static void main( String[] args ) throws SolrServerException, IOException
{
String url = "https://localhost:8080/solr/";
String httpAuthUser = "solr_admin";
String httpAuthPass= "somePassword";
// Configure latests Apache Http Components http client
HttpClient httpClient = new DefaultHttpClient();
if (httpAuthUser != null && httpAuthPass != null) {
AbstractHttpClient client = (AbstractHttpClient) httpClient;
App a = new App();
client.addRequestInterceptor(a.new PreEmptiveBasicAuthenticator(httpAuthUser, httpAuthPass));
}
// Configure XMLResponseParser as standard javabin parser does not work with 1.4
SolrServer solr = new HttpSolrServer(url, httpClient, new XMLResponseParser());
// Test adding some data
SolrInputDocument document = new SolrInputDocument();
document.addField("id", "552199");
document.addField("name", "Gouda cheese wheel");
document.addField("price", "49.99");
UpdateResponse uresponse = solr.add(document);
System.out.println("UpdateResponse"+uresponse.getStatus());
solr.commit();
// Query for the data just added
SolrQuery parameters = new SolrQuery();
parameters.set("q", "*");
QueryResponse response = solr.query(parameters);
SolrDocumentList list = response.getResults();
Iterator<SolrDocument> si = list.iterator();
System.out.println("Solr document"+list.getNumFound());
while(si.hasNext()){
System.out.println("Solr document"+si.next().toString());
}
}
protected class PreEmptiveBasicAuthenticator implements HttpRequestInterceptor {
private final UsernamePasswordCredentials credentials;
public PreEmptiveBasicAuthenticator(String user, String pass) {
credentials = new UsernamePasswordCredentials(user, pass);
}
public void process(HttpRequest request, HttpContext context)
throws HttpException, IOException {
request.addHeader(BasicScheme.authenticate(credentials,"US-ASCII",false));
}
}
}

Related

Elasticsearch 8 Java Client ResponseException status line [HTTP/1.1 404 Not Found] {"statusCode":404,"error":"Not Found","message":"Not Found"}

this is Michael from germany and i am reaching out to you because i have to finish my master thesis before 31.10.2022.
I had working code in july 2022 which i didn't touch since then. I used the online 2 weeks trial vom elastic.co to connect and do my stuff. Now i want to execute the code again on a new 2 weeks trial but i am facing an error, which i can't solve.
What happened in the meanwhile:
a) in july i used version 8.2.0 of the software while meanwhile Elasticsearch company released
version 8.4.0 of their software.
b) i changed password in the code, because i have a new 2 weeks trial now.
Here are some short example codes which all fail (actually my real code is bigger but these are small examples). Only the code after the line // "productive code" changes
Creating an index:
package Kapselung;
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.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
public class create_index {
public static void main(String[] args) {
String username = "";
String password = "";
String host = "";
int port =;
RestClient restClient;
ElasticsearchClient ESClient;
// https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/connecting.html
// https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/_basic_authentication.html
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
HttpClientConfigCallback httpClientConfigCallback = new HttpClientConfigCallback() {
#Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
httpClientBuilder.disableAuthCaching();
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
};
// Create the low-level client
RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(host, port, "https"));
restClientBuilder.setHttpClientConfigCallback(httpClientConfigCallback);
restClient = restClientBuilder.build();
// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
ESClient = new ElasticsearchClient(transport);
// "productive code"
try {
ESClient.indices().create(c -> c.index("products100"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Failure is:
co.elastic.clients.transport.TransportException: [es/indices.create] Failed to decode error response
at co.elastic.clients.transport.rest_client.RestClientTransport.getHighLevelResponse(RestClientTransport.java:290)
at co.elastic.clients.transport.rest_client.RestClientTransport.performRequest(RestClientTransport.java:147)
at co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient.create(ElasticsearchIndicesClient.java:266)
at co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient.create(ElasticsearchIndicesClient.java:282)
at Kapselung.create_index.main(create_index.java:51)
Caused by: org.elasticsearch.client.ResponseException: method [PUT], host [https://gattinger-fourth.kb.us-central1.gcp.cloud.es.io:9243], URI [/products100], status line [HTTP/1.1 404 Not Found]
... 5 more
Or posting a document:
package Kapselung;
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.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
import com.fasterxml.jackson.databind.ObjectMapper;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
public class post_document {
public static void main(String[] args) {
String username = "elastic";
String password = "JotkB5QY5v9IN0qRtvf6d5dL";
String host = "gattinger-fourth.kb.us-central1.gcp.cloud.es.io";
int port = 9243;
RestClient restClient;
ElasticsearchClient ESClient;
// https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/connecting.html
// https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/_basic_authentication.html
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
HttpClientConfigCallback httpClientConfigCallback = new HttpClientConfigCallback() {
#Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
httpClientBuilder.disableAuthCaching();
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
};
// Create the low-level client
RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(host, port, "https"));
restClientBuilder.setHttpClientConfigCallback(httpClientConfigCallback);
restClient = restClientBuilder.build();
// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
ESClient = new ElasticsearchClient(transport);
// "productive code"
try {
Request request = new Request("POST", "/products100/_doc");
String document = "{\"sku\": \"21847816\",\"name\": \"Rasierapparat\",\"price\": 23.99}";
ObjectMapper mapper = new ObjectMapper(); // Jackson Json
request.setJsonEntity(mapper.writeValueAsString(document));
Response response = restClient.performRequest(request);
} catch (Exception e) {
e.printStackTrace();
}
}
}
failure:
org.elasticsearch.client.ResponseException: method [POST], host [https://gattinger-fourth.kb.us-central1.gcp.cloud.es.io:9243], URI [/products100/_doc], status line [HTTP/1.1 404 Not Found]
{"statusCode":404,"error":"Not Found","message":"Not Found"}
at org.elasticsearch.client.RestClient.convertResponse(RestClient.java:346)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:312)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:287)
at Kapselung.post_document.main(post_document.java:59)
Or just checking the Elasticsearch version:
package Kapselung;
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.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
public class getESClient_info_version_number {
public static void main(String[] args) {
String username = "elastic";
String password = "JotkB5QY5v9IN0qRtvf6d5dL";
String host = "gattinger-fourth.kb.us-central1.gcp.cloud.es.io";
int port = 9243;
RestClient restClient;
ElasticsearchClient ESClient;
// https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/connecting.html
// https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/_basic_authentication.html
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
HttpClientConfigCallback httpClientConfigCallback = new HttpClientConfigCallback() {
#Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
httpClientBuilder.disableAuthCaching();
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
};
// Create the low-level client
RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(host, port, "https"));
restClientBuilder.setHttpClientConfigCallback(httpClientConfigCallback);
restClient = restClientBuilder.build();
// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
ESClient = new ElasticsearchClient(transport);
// "productive code"
try {
System.out.println(ESClient.info().version().number());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Failure:
co.elastic.clients.transport.TransportException: [es/info] Missing [X-Elastic-Product] header. Please check that you are connecting to an Elasticsearch instance, and that any networking filters are preserving that header.
at co.elastic.clients.transport.rest_client.RestClientTransport.checkProductHeader(RestClientTransport.java:351)
at co.elastic.clients.transport.rest_client.RestClientTransport.getHighLevelResponse(RestClientTransport.java:253)
at co.elastic.clients.transport.rest_client.RestClientTransport.performRequest(RestClientTransport.java:147)
at co.elastic.clients.elasticsearch.ElasticsearchClient.info(ElasticsearchClient.java:976)
at Kapselung.getESClient_info_version_number.main(getESClient_info_version_number.java:51)
Caused by: org.elasticsearch.client.ResponseException: method [GET], host [https://gattinger-fourth.kb.us-central1.gcp.cloud.es.io:9243], URI [/], status line [HTTP/1.1 200 OK]
And this is my pom.xml:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>00003</groupId>
<artifactId>00004</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.2.0</version>
</dependency>
<!--
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>8.2.3</version>
</dependency>
-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
<!-- benötigt falls ClassNotFoundException: jakarta.json.spi.JsonProvider
https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/installation.html -->
<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
<version>2.0.1</version>
</dependency>
<!-- -->
</dependencies>
</project>
Changing dependency from 8.2.0 to 8.4.0 didn't help.
So i don't know what actually to do. Do you?
Yes i know that i spread the password, it is intentional so somebody could help me by actually executing it. It is only a 2 weeks trial so i don't care about the logindata.
Thanks - Enomine

Apache Commons AsyncClient - Ignore Certificates - SSLPeerUnverifiedException

Thought I disabled checking certs in my Http Client, but keep getting SSLPeerUnverifiedException.
Here's my client:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.stream.Stream;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.message.BasicHeader;
import org.apache.http.nio.reactor.ConnectingIOReactor;
import org.apache.http.nio.reactor.IOReactorException;
import org.apache.http.ssl.SSLContextBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class ApacheCommonsAsyncClient implements IMakeHttpRequests {
private static final Logger LOGGER = LoggerFactory.getLogger(PaxHttpClient.class);
private static final int MAX_POOL_SIZE = 100;
private static final int MAX_CONN_PER_ROUTE = 10;
private final CloseableHttpAsyncClient httpClient;
ApacheCommonsAsyncClient() {
final RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000)
.setConnectionRequestTimeout(5000).setSocketTimeout(0).build();
final Header doNotKeepAlive = new BasicHeader("Connection: keep-alive", "false");
final Header closeConnection = new BasicHeader("Connection", "close");
try {
final SSLContextBuilder sslContextBuilder = new SSLContextBuilder().loadTrustMaterial(null,
new TrustSelfSignedStrategy());
final ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor();
final PoolingNHttpClientConnectionManager cm = new PoolingNHttpClientConnectionManager(ioReactor);
// #formatter:off
this.httpClient = HttpAsyncClients.custom()
.setDefaultRequestConfig(requestConfig)
.setKeepAliveStrategy((httpResponse, httpContext) -> 0)
.setDefaultHeaders(Arrays.asList(doNotKeepAlive, closeConnection))
.setConnectionManager(cm)
.setSSLContext(sslContextBuilder.build())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.setMaxConnTotal(MAX_POOL_SIZE)
.setMaxConnPerRoute(MAX_CONN_PER_ROUTE)
.build();
// #formatter:on
this.httpClient.start();
} catch (final GeneralSecurityException | IOReactorException e) {
throw new RuntimeException(e);
}
}
}
Exception:
java.util.concurrent.ExecutionException: javax.net.ssl.SSLPeerUnverifiedException: Host name '<public-dns>' does not match the certificate subject provided by the peer (CN=*.<domain>.com, O="<org>", L=<location>, ST=<state>, C=<country>)
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.paxata.performance.App.run(App.java:30)
at com.paxata.performance.Bootstrap.main(Bootstrap.java:43)
Caused by: javax.net.ssl.SSLPeerUnverifiedException: Host name '<public-dns>' does not match the certificate subject provided by the peer (CN=*.<domain>.com, O="<org>", L=<location>, ST=<state>, C=<country>)
at org.apache.http.nio.conn.ssl.SSLIOSessionStrategy.verifySession(SSLIOSessionStrategy.java:208)
at org.apache.http.nio.conn.ssl.SSLIOSessionStrategy$1.verify(SSLIOSessionStrategy.java:188)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doHandshake(SSLIOSession.java:367)
at org.apache.http.nio.reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:508)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:120)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:588)
at java.lang.Thread.run(Thread.java:748)
and the dependency versions i'm bringing in:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.9</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
<version>4.1.3</version>
</dependency>
Connection manager instance passed to the builder supersedes all connection management parameters such as SSL and pool settings.
There are two ways it could be remedied.
Let the builder construct and initialize a connection manager
final SSLContextBuilder sslContextBuilder = new SSLContextBuilder().loadTrustMaterial(null,
new TrustSelfSignedStrategy());
this.httpClient = HttpAsyncClients.custom()
.setDefaultRequestConfig(requestConfig)
.setKeepAliveStrategy((httpResponse, httpContext) -> 0)
.setDefaultHeaders(Arrays.asList(doNotKeepAlive, closeConnection))
.setSSLContext(sslContextBuilder.build())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.setMaxConnTotal(MAX_POOL_SIZE)
.setMaxConnPerRoute(MAX_CONN_PER_ROUTE)
.build();
Configure the connection manager prior to passing to the builder
final SSLContextBuilder sslContextBuilder = new SSLContextBuilder().loadTrustMaterial(null,
new TrustSelfSignedStrategy());
final PoolingNHttpClientConnectionManager cm = new PoolingNHttpClientConnectionManager(
new DefaultConnectingIOReactor(),
RegistryBuilder.<SchemeIOSessionStrategy>create()
.register("http", NoopIOSessionStrategy.INSTANCE)
.register("https", new SSLIOSessionStrategy(sslContextBuilder.build(), NoopHostnameVerifier.INSTANCE))
.build());
cm.setMaxTotal(MAX_POOL_SIZE);
cm.setDefaultMaxPerRoute(MAX_CONN_PER_ROUTE);
this.httpClient = HttpAsyncClients.custom()
.setDefaultRequestConfig(requestConfig)
.setKeepAliveStrategy((httpResponse, httpContext) -> 0)
.setDefaultHeaders(Arrays.asList(doNotKeepAlive, closeConnection))
.setConnectionManager(cm)
.build();
The former is recommended unless there are very strong reasons for doing the latter.
PS: You do not want to disable connection persistence

Rest client Jersey 2

Trying to create a restful clint in Java with Jersey2.
There is 2 problem with this code:
1. Prety slow needs more than 2 seconds
2. Something is wrong with the data binding, only 2/6 data is binded well
Main Java:
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
public class JerseyTestClient {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
WebTarget webTarget = client.target("https://wtfismyip.com/json");
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
Response response = invocationBuilder.get();
WtfIsMyConfig wtfIsMyConfig = response.readEntity(WtfIsMyConfig.class);
System.out.println(response);
System.out.println(wtfIsMyConfig);
}
}
Model
public class WtfIsMyConfig implements Serializable {
private String YourIPAddress;
private String YourLocation;
private String YourHostname;
private String YourISP;
private String YourTorExit;
private String YourCountryCode;
public WtfIsMyConfig() {
}
//getters setters
}
Pom.xml
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.bundles</groupId>
<artifactId>jaxrs-ri</artifactId>
<version>2.26</version>
</dependency>
</dependencies>
Output console:
InboundJaxrsResponse{context=ClientResponse{method=GET, uri=https://wtfismyip.com/json, status=200, reason=OK}}
WtfIsMyConfig{YourIPAddress='192.168.0.0', YourLocation='null', YourHostname='192-168-0-0.pool.digikabel.hu', YourISP='null', YourTorExit='null', YourCountryCode='null'}
Process finished with exit code 0
Compilation completed successfully with 3 warnings in 2s 500ms
Requested Output:
{
"YourIPAddress": "192.168.0.0",
"YourLocation": "XXX, 18, Hungary",
"YourHostname": "192-168-0-0.pool.digikabel.hu",
"YourISP": "DIGI Tavkozlesi es Szolgaltato Kft.",
"YourTorExit": "false",
"YourCountryCode": "HU"
}

Swagger with Jersey 2 throws java.lang.NoClassDefFoundError: javax/servlet/ServletConfig

Trying to setup my first REST API (using Jersey 2 and Gradle) and add some documentation to it by using swagger. But when adding swagger dependencies and following this swagger documentation, "Using a custom Application subclass" approach, it throws me this exception, when executing the main method from Eclipse:
Exception in thread "main" java.lang.NoClassDefFoundError: javax/servlet/ServletConfig
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.getDeclaredMethods(Class.java:1975)
at org.glassfish.jersey.server.model.IntrospectionModeller$2.run(IntrospectionModeller.java:253)
at java.security.AccessController.doPrivileged(Native Method)
at org.glassfish.jersey.server.model.IntrospectionModeller.getAllDeclaredMethods(IntrospectionModeller.java:247)
at org.glassfish.jersey.server.model.IntrospectionModeller.checkForNonPublicMethodIssues(IntrospectionModeller.java:172)
at org.glassfish.jersey.server.model.IntrospectionModeller.doCreateResourceBuilder(IntrospectionModeller.java:119)
at org.glassfish.jersey.server.model.IntrospectionModeller.access$000(IntrospectionModeller.java:80)
at org.glassfish.jersey.server.model.IntrospectionModeller$1.call(IntrospectionModeller.java:112)
at org.glassfish.jersey.server.model.IntrospectionModeller$1.call(IntrospectionModeller.java:109)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:255)
at org.glassfish.jersey.server.model.IntrospectionModeller.createResourceBuilder(IntrospectionModeller.java:109)
at org.glassfish.jersey.server.model.Resource.from(Resource.java:797)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:465)
at org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:184)
at org.glassfish.jersey.server.ApplicationHandler$3.call(ApplicationHandler.java:350)
at org.glassfish.jersey.server.ApplicationHandler$3.call(ApplicationHandler.java:347)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:255)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:347)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:299)
at org.glassfish.jersey.jdkhttp.JdkHttpHandlerContainer.<init>(JdkHttpHandlerContainer.java:98)
at org.glassfish.jersey.jdkhttp.JdkHttpServerFactory.createHttpServer(JdkHttpServerFactory.java:111)
at org.glassfish.jersey.jdkhttp.JdkHttpServerFactory.createHttpServer(JdkHttpServerFactory.java:93)
at example.MyApp.main(MyApp.java:21)
Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletConfig
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 29 more
My code looks like this:
package example;
import static org.glassfish.jersey.jdkhttp.JdkHttpServerFactory.createHttpServer;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import com.sun.net.httpserver.HttpServer;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
public class MyApp extends ResourceConfig {
public static void main(String[] args) throws Throwable {
URI baseUri = UriBuilder.fromUri("http://localhost/").port(9999).build();
HttpServer server = createHttpServer(baseUri, new MyApp());
System.out.println("SERVICE started at: " + baseUri);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
server.stop(0);
}));
}
public MyApp() {
packages("example");
register(SwaggerSerializers.class); // <-- swagger specific
register(ApiListingResource.class); // <-- swagger specific
register(JacksonFeature.class);
}
}
My gradle dependencies
dependencies {
compile 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:+'
compile 'org.glassfish.jersey.containers:jersey-container-jdk-http:+'
compile 'org.glassfish.jersey.media:jersey-media-moxy:+'
compile 'org.glassfish.jersey.media:jersey-media-json-jackson:+'
compile 'io.swagger:swagger-jersey2-jaxrs:1.5.9'
}
Using jdk1.8.0_77 on Windows 7
However, if I comment out the swagger dependency and the swagger specifics in the code, then the actual REST service works as expected. How can I make swagger work without using a servlet container? The REST service can work without it
dependencies {
compile 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:+'
compile 'org.glassfish.jersey.containers:jersey-container-jdk-http:+'
compile 'org.glassfish.jersey.media:jersey-media-moxy:+'
compile 'org.glassfish.jersey.media:jersey-media-json-jackson:+'
// compile 'io.swagger:swagger-jersey2-jaxrs:1.5.9'
}
code:
package example;
import static org.glassfish.jersey.jdkhttp.JdkHttpServerFactory.createHttpServer;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import com.sun.net.httpserver.HttpServer;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
public class MyApp extends ResourceConfig {
public static void main(String[] args) throws Throwable {
URI baseUri = UriBuilder.fromUri("http://localhost/").port(9999).build();
HttpServer server = createHttpServer(baseUri, new MyApp());
System.out.println("SERVICE started at: " + baseUri);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
server.stop(0);
}));
}
public MyApp() {
packages("example");
// register(SwaggerSerializers.class); // <-- swagger specific
// register(ApiListingResource.class); // <-- swagger specific
register(JacksonFeature.class);
}
}
So it looks like the issue is derived from you running in a non-servlet environment. While Jersey supports it, swagger-core... not so much. This poses some issues with specific deployment, although they are less common.
The easiest solution would, obviously, be to use a servlet-container engine. Something lightweight like Jetty would work.
I know that is a litlle bit late, but I have the same issue and came up with a solution to run swagger on a non-servlet environment.
Hope to be helpful for the next devs.
pom.xml
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.7.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.196</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
</dependencies>
...
<properties>
<jersey.version>2.28</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
Main.java
package me.nunum.whereami;
import me.nunum.whereami.facade.ApiListingResource;
import me.nunum.whereami.framework.interceptor.PrincipalInterceptor;
import org.glassfish.grizzly.http.server.CLStaticHttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.ServerConfiguration;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import java.io.IOException;
import java.net.URI;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Main class.
*/
public class Main {
// Base URI the Grizzly HTTP server will listen on
private static final String BASE_URI = "http://0.0.0.0:8080";
private static final Logger LOGGER = Logger.getLogger("Main");
/**
* Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
*
* #return Grizzly HTTP server.
*/
public static HttpServer startServer() {
// create a resource config that scans for JAX-RS resources and providers
// in me.nunum.whereami.facade package
final ResourceConfig rc = new ResourceConfig().packages("me.nunum.whereami.facade");
rc.setApplicationName("where");
rc.register(PrincipalInterceptor.class);
rc.register(ApiListingResource.class);
rc.register(io.swagger.jaxrs.listing.SwaggerSerializers.class);
// create and start a new instance of grizzly http server
// exposing the Jersey application at BASE_URI
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}
/**
* Main method.
*
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
final HttpServer server = startServer();
ClassLoader loader = Main.class.getClassLoader();
CLStaticHttpHandler docsHandler = new CLStaticHttpHandler(loader, "swagger-ui/dist/");
docsHandler.setFileCacheEnabled(false);
ServerConfiguration cfg = server.getServerConfiguration();
cfg.addHttpHandler(docsHandler, "/docs/");
Main.LOGGER.log(Level.INFO,"Jersey app started with WADL available at "
+ "{0} \nHit enter to stop it...", BASE_URI);
System.in.read();
server.shutdown();
}
}
Refactor io.swagger.jaxrs.listing.ApiListingResource class into a new class (created in my facade package) to work on a non-servlet environment.
package me.nunum.whereami.facade;
import io.swagger.annotations.ApiOperation;
import io.swagger.config.FilterFactory;
import io.swagger.config.Scanner;
import io.swagger.config.SwaggerConfig;
import io.swagger.core.filter.SpecFilter;
import io.swagger.core.filter.SwaggerSpecFilter;
import io.swagger.jaxrs.Reader;
import io.swagger.jaxrs.config.JaxrsScanner;
import io.swagger.jaxrs.config.ReaderConfig;
import io.swagger.jaxrs.listing.SwaggerSerializers;
import io.swagger.models.Swagger;
import io.swagger.util.Yaml;
import java.util.*;
import javax.inject.Singleton;
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.Cookie;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#Path("/api/doc")
#Singleton
public class ApiListingResource {
static boolean initialized = false;
Logger LOGGER = LoggerFactory.getLogger(io.swagger.jaxrs.listing.ApiListingResource.class);
public Swagger mSwaggerConfig;
public ApiListingResource() {
mSwaggerConfig = new Swagger();
mSwaggerConfig.setBasePath("/");
}
public ApiListingResource(Swagger swagger){
this.mSwaggerConfig = swagger;
}
protected synchronized Swagger scan(Application app) {
Swagger swagger = null;
Scanner scanner = new Scanner() {
#Override
public Set<Class<?>> classes() {
return app.getClasses();
}
#Override
public boolean getPrettyPrint() {
return false;
}
#Override
public void setPrettyPrint(boolean b) {
}
};
this.LOGGER.debug("using scanner " + scanner);
SwaggerSerializers.setPrettyPrint(scanner.getPrettyPrint());
swagger = this.mSwaggerConfig;
new HashSet();
Set classes;
if (scanner instanceof JaxrsScanner) {
classes = null;
} else {
classes = scanner.classes();
}
if (classes != null) {
Reader reader = new Reader(swagger, new ReaderConfig() {
#Override
public boolean isScanAllResources() {
return false;
}
#Override
public Collection<String> getIgnoredRoutes() {
return new ArrayList<>();
}
});
swagger = reader.read(classes);
if (scanner instanceof SwaggerConfig) {
swagger = ((SwaggerConfig)scanner).configure(swagger);
} else {
SwaggerConfig configurator = new SwaggerConfig() {
#Override
public Swagger configure(Swagger swagger) {
return swagger;
}
#Override
public String getFilterClass() {
return "";
}
};
this.LOGGER.debug("configuring swagger with " + configurator);
configurator.configure(swagger);
}
}
initialized = true;
return swagger;
}
#GET
#Produces({"application/json"})
#Path("/swagger.json")
#ApiOperation(
value = "The swagger definition in JSON",
hidden = true
)
public Response getListingJson(#Context Application app, #Context HttpHeaders headers, #Context UriInfo uriInfo) {
Swagger swagger = this.mSwaggerConfig;
if (!initialized) {
this.mSwaggerConfig = this.scan(app);
}
if (swagger != null) {
SwaggerSpecFilter filterImpl = FilterFactory.getFilter();
if (filterImpl != null) {
SpecFilter f = new SpecFilter();
swagger = f.filter(swagger, filterImpl, this.getQueryParams(uriInfo.getQueryParameters()), this.getCookies(headers), this.getHeaders(headers));
}
return Response.ok().entity(swagger).build();
} else {
return Response.status(404).build();
}
}
#GET
#Produces({"application/yaml"})
#Path("/swagger.yaml")
#ApiOperation(
value = "The swagger definition in YAML",
hidden = true
)
public Response getListingYaml(#Context Application app, #Context HttpHeaders headers, #Context UriInfo uriInfo) {
Swagger swagger = this.mSwaggerConfig;
if (!initialized) {
this.mSwaggerConfig = this.scan(app);
}
try {
if (swagger != null) {
SwaggerSpecFilter filterImpl = FilterFactory.getFilter();
this.LOGGER.debug("using filter " + filterImpl);
if (filterImpl != null) {
SpecFilter f = new SpecFilter();
swagger = f.filter(swagger, filterImpl, this.getQueryParams(uriInfo.getQueryParameters()), this.getCookies(headers), this.getHeaders(headers));
}
String yaml = Yaml.mapper().writeValueAsString(swagger);
String[] parts = yaml.split("\n");
StringBuilder b = new StringBuilder();
String[] arr$ = parts;
int len$ = parts.length;
for(int i$ = 0; i$ < len$; ++i$) {
String part = arr$[i$];
int pos = part.indexOf("!<");
int endPos = part.indexOf(">");
b.append(part);
b.append("\n");
}
return Response.ok().entity(b.toString()).type("application/yaml").build();
}
} catch (Exception var16) {
var16.printStackTrace();
}
return Response.status(404).build();
}
protected Map<String, List<String>> getQueryParams(MultivaluedMap<String, String> params) {
Map<String, List<String>> output = new HashMap();
if (params != null) {
Iterator i$ = params.keySet().iterator();
while(i$.hasNext()) {
String key = (String)i$.next();
List<String> values = (List)params.get(key);
output.put(key, values);
}
}
return output;
}
protected Map<String, String> getCookies(HttpHeaders headers) {
Map<String, String> output = new HashMap();
if (headers != null) {
Iterator i$ = headers.getCookies().keySet().iterator();
while(i$.hasNext()) {
String key = (String)i$.next();
Cookie cookie = (Cookie)headers.getCookies().get(key);
output.put(key, cookie.getValue());
}
}
return output;
}
protected Map<String, List<String>> getHeaders(HttpHeaders headers) {
Map<String, List<String>> output = new HashMap();
if (headers != null) {
Iterator i$ = headers.getRequestHeaders().keySet().iterator();
while(i$.hasNext()) {
String key = (String)i$.next();
List<String> values = (List)headers.getRequestHeaders().get(key);
output.put(key, values);
}
}
return output;
}
}
Any questions, please ask.
I was facing the same issue, I solved it by following the same swagger documentation, The only difference is that I provided my own ApiListingResource implementation
package com.example;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.annotations.ApiOperation;
import io.swagger.jaxrs.config.BeanConfig;
import io.swagger.models.Swagger;
import io.swagger.util.Yaml;
import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
#Path("/docs")
#ApplicationScoped
public class ApiListingResource {
private final Swagger swagger;
public ApiListingResource() {
BeanConfig beanConfig = new BeanConfig();
beanConfig.setTitle("MY REST API");
beanConfig.setVersion("v1");
beanConfig.setBasePath("/api");
beanConfig.setResourcePackage("com.example.resource");
beanConfig.setScan(true);
this.swagger = beanConfig.getSwagger();
}
#GET
#Produces({"application/json"})
#Path("/swagger.json")
public Response getListingJson() {
return Response.ok(this.swagger).build();
}
#GET
#Produces({"application/yaml"})
#Path("/swagger.yaml")
public Response getListingYaml() throws JsonProcessingException {
String yaml = Yaml.mapper().writeValueAsString(this.swagger);
return Response.ok(yaml).build();
}
}
Then I registered the resource along with the SwaggerSerializers provider.

Twilio: java.lang.NoClassDefFoundError: com/twilio/sdk/TwilioRestException

I am trying to send a sms using twillio, here the code:
import com.twilio.sdk.TwilioRestClient;
import com.twilio.sdk.TwilioRestException;
import org.apache.http.NameValuePair;
import org.apache.http.auth.Credentials;
import org.apache.http.message.BasicNameValuePair;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
public class SendSms extends HttpServlet {
private Logger logger = Logger.getLogger(SendSms.class.getName());
private TwilioRestClient client;
private Credentials credentials;
#Override
public void service(HttpServletRequest req, HttpServletResponse resp) throws IOException,
ServletException {
final String twilioAccountSid = System.getenv("TWILIO_ACCOUNT_SID");
final String twilioAuthToken = System.getenv("TWILIO_AUTH_TOKEN");
final String twilioNumber = System.getenv("TWILIO_NUMBER");
final String toNumber = (String) twilioNumber;
String message = "prova";
client = new TwilioRestClient(twilioAccountSid, twilioAuthToken);
sendMessage(toNumber, message);
}
public void sendMessage(String to, String message) {
List<NameValuePair> params = getParams(to, message);
try {
this.client.getAccount().getMessageFactory().create(params);
} catch (TwilioRestException exception) {
exception.printStackTrace();
}
}
private List<NameValuePair> getParams(String to, String message) {
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("Body", message));
params.add(new BasicNameValuePair("To", to));
params.add(new BasicNameValuePair("From", to));
return params;
}
}
Is just a test so I don't matter about performarce, code cleaning and so on. Calling the servlet I am getting the following error:
WARNING: Error for /SendSms
java.lang.NoClassDefFoundError: com/twilio/sdk/TwilioRestException
I am using maven, importing the related twillio apis, here the pom dependency:
<dependencies>
<dependency>
<groupId>com.twilio.sdk</groupId>
<artifactId>twilio-java-sdk</artifactId>
<version>(6.0,6.9)</version>
</dependency>
Does someone has some suggestions?
Thank you in advance.
Perhaps the missing <scope> for compile is the problem:
<dependency>
<groupId>com.twilio.sdk</groupId>
<artifactId>twilio-java-sdk</artifactId>
<version>(6.0,6.9)</version>
<scope>compile</scope>
</dependency>
And for the full detailed instructions regarding the dev environment:
https://www.twilio.com/docs/quickstart/java/devenvironment#pomxml
I have a tired application layered like this
WebServices
Services
DAO
Common
I call twilio in the services module, so I put the maven dependency in the pom file in that maven module. For some reason I kept getting the same error as you. Adding the dependency to the WebServices module fixed the issue

Categories