Lightweight jax-rs client - rest

Using below code sample from tutorial i can successfully make post to a jax-rs service on glassfish-4.
Client client = ClientFactory.newClient();
WebTarget root = client.target("http://localhost:8080/roast-house/api/coffeebeans");
Bean origin = new Bean("arabica", RoastType.DARK, "mexico");
final String mediaType = MediaType.APPLICATION_XML;
final Entity<Bean> entity = Entity.entity(origin, mediaType);
Response response = root.request().post(entity, Response.class);
response.close();
But it forces to bring a dependency that totals about 4.5mb (resteasy 3.0.5 was ~5mb)
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.4.1</version>
</dependency>
I have the feeling i'm using only a portion of the client API, is there any more lightweight clients out there, or how would i go about to construct the request using only standard libraries?

Related

Jax rs rest client - timeout configuration [duplicate]

I have written simple REST web service client class which uses the JAX-RS 2.0 client API to make REST requests. I am trying to figure out how to set a request timeout for each invocation. Here is the code for a request:
Client client = ClientBuilder.newBuilder().build();
WebTarget resourceTarget = client.target(restServiceUrl)
.path("{regsysID}/{appointmentID}/")
.resolveTemplate("regsysID", regSysId)
.resolveTemplate("appointmentID", apptId);
Invocation invocation = resourceTarget.request(MediaType.APPLICATION_JSON).buildPut(null);
String createSessionJson = invocation.invoke(String.class);
Note: this is a new method available on JAX-RS 2.1
This is a very old post but the below code will work for both jersey and resteasy.
ClientBuilder clientBuilder = ClientBuilder.newBuilder();
clientBuilder.connectTimeout(10, TimeUnit.SECONDS);
clientBuilder.readTimeout(12, TimeUnit.SECONDS);
Client client = clientBuilder.build();
You can do this by creating a ClientConfig first and providing it as an argument when creating the new client.
import org.glassfish.jersey.client.ClientProperties;
ClientConfig configuration = new ClientConfig();
configuration.property(ClientProperties.CONNECT_TIMEOUT, 1000);
configuration.property(ClientProperties.READ_TIMEOUT, 1000);
Client client = ClientBuilder.newClient(configuration);
With Resteasy this can be accomplished by building your Client as such.
Client client = new ResteasyClientBuilder()
.establishConnectionTimeout(2, TimeUnit.SECONDS)
.socketTimeout(2, TimeUnit.SECONDS)
.build();
I have not seen a list of standard configuration properties you could set via ClientBuilder.newClient(Configuration configuration) which would be needed to make this portable.
First, you have to add relevant dependencies (here is for the WildFly 10.1):
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.0.14.Final</version>
<scope>provided</scope>
</dependency>
Next - create a normal Apache HttpClient and push it the RestEasy Enginge with overriding one method, which causes the problem:
// create here a normal Apache HttpClient with all parameters, that you need
HttpClient httpClient = createHttpClient(connectTimeout,
socketTimeout,
connectionRequestTimeout,
maxTotalHTTPConnections);
// Deprecated Apache classes cleanup https://issues.jboss.org/browse/RESTEASY-1357
// Client Framework not honoring connection timeouts Apache Client 4.3 https://issues.jboss.org/browse/RESTEASY-975
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient) {
#Override
protected void loadHttpMethod(ClientInvocation request, HttpRequestBase httpMethod) throws Exception {
super.loadHttpMethod(request, httpMethod);
httpMethod.setParams(new BasicHttpParams());
}
};
return new ResteasyClientBuilder().httpEngine(engine).build();
Have a look at https://issues.jboss.org/browse/RESTEASY-975 Seems, that the problem was just resolved in the version 3.1.0.Final.
For people stuck with older JAX-RS 2.0 API and old Resteasy implementation, you may use this method:
Client client = new ResteasyClientBuilder()
.establishConnectionTimeout(3, TimeUnit.SECONDS)
.socketTimeout(5, TimeUnit.SECONDS).build();
Despite the name, socketTimeout stands for "read timeout", since by the docs, it stands for "The timeout for waiting for data".
If you are using Jersey 2.x Here it is the simple solution it's work for me
import com.jclient.JClient;
Client c = Client.create();
WebResource webResource = c.resource("requestUrl");
c.setConnectTimeout(yourMins*60*1000);

Why is apiKeyRequired = AnnotationBoolean.TRUE not enforced?

I am building GAE standard endpoint with Java using Maven dependency:
<dependency>
<groupId>com.google.endpoints</groupId>
<artifactId>endpoints-framework</artifactId>
<version>${endpoints.framework.version}</version>
</dependency>
where
<endpoints.framework.version>2.0.9</endpoints.framework.version>
Annotating API with:
#Api( name = "blah",
version = "v1",
apiKeyRequired = AnnotationBoolean.TRUE,
#ApiMethod( name = "taxdocument.store",
path = "taxdoc/store",
httpMethod = HttpMethod.POST )
But API is not enforcing API keys.
Perhaps I am not understanding. I am expecting that POST to this would work.
https://blah.appspot.com/_ah/api/blah/v1/taxdoc/store?key=valid-key
But this would fail
https://blah.appspot.com/_ah/api/blah/v1/taxdoc/store?key=invalid-key
https://blah.appspot.com/_ah/api/blah/v1/taxdoc/store
But ALL succeed with no errors.
Can anyone steer me in the right direction? Thanks.
You need to include the API management library and filters.

Restlet client resource "not modified" condition

I've got a Restlet based application, and I'm trying to use Restlet client resources to test certain parts of it.
Since upgrading from Restlet 2.2.3 to 2.3.4, my ETag verification tests have started failing. Here's how I was adding the header in the old version:
Series<Header> headers = (Series<Header>) currentClientResource.getRequest().getAttributes().get("org.restlet.http.headers");
if (headers == null) {
headers = new Series<Header>(Header.class);
}
headers.add("If-None-Match", "\"" + eTag + "\"");
currentClientResource.getRequestAttributes().put("org.restlet.http.headers", headers);
Then when calling represent() again on the wrapped clientResource I was getting a 304 Not Modified response (which is what I want).
In 2.3.4 this started returning a 200 OK instead, and I noticed a log message about not setting the If-None-Match header directly.
Instead I'm now trying this:
currentClientResource.getRequest().getConditions().getNoneMatch().add(new Tag(eTag));
However this is still giving me a 200 OK. If I do the request manually through a REST client I can get a 304 Not Modified, so the server is still doing the right behavior. What do I need to do in the tests to see what I want to see?
I made a try and it works for me with version 2.3.4 of Restlet.
Here is what I did:
The Maven dependencies for my test
<project>
<modelVersion>4.0.0</modelVersion>
(...)
<properties>
<java-version>1.7</java-version>
<restlet-version>2.3.4</restlet-version>
</properties>
<dependencies>
<dependency>
<groupId>org.restlet.jse</groupId>
<artifactId>org.restlet</artifactId>
<version>${restlet-version}</version>
</dependency>
<dependency>
<groupId>org.restlet.jse</groupId>
<artifactId>org.restlet.ext.jetty</artifactId>
<version>${restlet-version}</version>
</dependency>
<dependency>
<groupId>org.restlet.jse</groupId>
<artifactId>org.restlet.ext.jackson</artifactId>
<version>${restlet-version}</version>
</dependency>
<dependency>
<groupId>org.restlet.jse</groupId>
<artifactId>org.restlet.ext.crypto</artifactId>
<version>${restlet-version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>maven-restlet</id>
<name>Public online Restlet repository</name>
<url>http://maven.restlet.com</url>
</repository>
</repositories>
</project>
A server resource that sets the etag on the returned representation:
public class ETagServerResource extends ServerResource {
#Get
public Representation test() {
String test = "test";
String md5 = DigestUtils.toMd5(test);
StringRepresentation repr = new StringRepresentation(test);
repr.setTag(new Tag(md5));
return repr;
}
}
The client that makes two calls: a first one without the etag and a second one with the etag that should return a 304 status code.
// First call
ClientResource cr
= new ClientResource("http://localhost:8182/test");
Representation repr = cr.get();
Tag tag = repr.getTag();
System.out.println(">> cr = "+cr); // Status code: 200
// Second call
cr.getRequest().getConditions().getNoneMatch().add(tag);
cr.get();
System.out.println(">> cr = "+cr); // Status code: 304
I don't know what you use within the server resource. Feel free to tell me.
Hope it helps you,
Thierry

JAX-RS Jersey Error java.lang.NoSuchMethodError

I wanted to implement a file-upload function for my jersey based rest server.
when i set my pom.xml (using maven) to:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jdk-http</artifactId>
<version>2.0</version>
</dependency>
i get following error:
JAX-RS Jersey Error java.lang.NoSuchMethodError: org.glassfish.jersey.internal.util.ReflectionHelper.getContextClassLoaderPA()Ljava/security/PrivilegedAction;
without the "jersey-media-multipart"-dependency the rest server is working but i cant use the file-upload functions.
Following the important part of source code:
ResourceConfig resourceConfig = new ResourceConfig(RestWebServer.class);
//resourceConfig.register(MultiPartFeature.class);
URI endPoint = new URI(pathServer);
server = JdkHttpServerFactory.createHttpServer( endPoint, resourceConfig );
RestWebserver.java:
#Path("/fileupload")
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormParam("file") InputStream uploadedInputStream,
#FormParam("file") FormDataContentDisposition fileDetail)
{
String uploadedFileLocation = "c://" + fileDetail.getFileName();
// save it
saveToFile(uploadedInputStream, uploadedFileLocation);
String output = "File uploaded via Jersey based RESTFul Webservice to: " + uploadedFileLocation;
return Response.status(200).entity(output).build();
}
Not a Jersey user so I am just guessing, but you probably have a jar mismatch.
Try replacing your second entry with this:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jdk-http</artifactId>
<version>2.4.1</version>
</dependency>
Basing my guess on the chapter 8, have you registered your client/server code?

Restlet - Connection Problems - 406 Not Acceptable - Plain Text

couldnt find somewhere else advice.
I am writing a Restlet JSE Client for a Jersey(!) Restful Service. I already wrote a Jersey client for that and it is working, so the jersey service is alright. Now I get problems in writing a restlet client:
My Service root adress is:
http://localhost:8080/com-project-core/rest, so I call:
ClientResource = service = new ClientResource("http://localhost:8080/com-project-core/rest");
My Basic Auth Credentiels are admin and xxx, so I call:
service.setChallengeResponse(ChallengeScheme.HTTP_BASIC, "admin", "xxx");
Now the problems:
ClientResource service = new ClientResource("http://localhost:8080/com-project-core/rest/ping");
calls up my service. After that I try
String myString = service.get(String.class);
System.out.println(myString);
I get a:
08.07.2012 17:41:48 org.restlet.engine.http.connector.HttpClientHelper start
INFO: Starting the default HTTP client
in my output. Not more! The Junit Test says:
Not Acceptable (406) - Not Acceptable
So he can find the resource but cannot produce #Produces("text/plain") ??
So when I remove #Produces("text/plain") on server side it works!!
For the resourcey my server side looks like this:
#Path("/ping")
#RolesAllowed({"admin", "user"})
public class ConnectedResourceBean implements ConnectedResourceIF {
#GET
#Produces("text/plain")
public String getPingMessage() throws NamingException {
return "Hello World";
}
}
For my pom in set this dependencies:
<dependency>
<groupId>org.restlet.jse</groupId>
<artifactId>org.restlet</artifactId>
<version>${restlet.version}</version>
</dependency>
<dependency>
<groupId>org.restlet.jse</groupId>
<artifactId>org.restlet.ext.xstream</artifactId>
<version>${restlet.version}</version>
</dependency>
As I said, its working with my jersey client.
No way: Restlet had problems with
#Produces("text/plain")
on jersey server side. Can someone explain me that fact?
Edit:
Made it work with
<properties>
<restlet.version>2.1-M3</restlet.version>
</properties>