I'm working with Postman and I see that it has many modes. I was able to implement a restRequest object that "knows" how to send a request in Post or Get method.
This is part of my code:
#Override
public RestResponse sendRequest() {
return data.accept(new RequestDataVisitor<RestResponse>() {
#Override
public RestResponse visit(GetData getData) {
return new RestResponse(webTarget.request().headers(headers).get());
}
#Override
public RestResponse visit(PostFormData post) {
return new RestResponse(webTarget.request(post.getMediaType()).headers(headers).post(post.getEntity()));
}
#Override
public RestResponse visit(PostRawData post) {
return new RestResponse(webTarget.request(post.getMediaType()).headers(headers).post(post.getEntity()));
}
#Override
public RestResponse visit(DeleteData deleteData) {
return new RestResponse(webTarget.request(deleteData.getMediaType()).headers(headers).delete());
}
});
}
How do I get my webTarget to send a request in Patch mode?
You can use the method method with first argument set to "PATCH".
method is a generalized method (as opposed to post, get, delete which have the http-method hardwired) and allows you to call an arbitrary method:
webTarget.request(mediaType).headers(headers).method("PATCH", entity);
See the documentation for additional details: WebTarget.request gives you an instance of an Invocation.Builder which inherits method from SyncInvoker.
Note: depending on the JDK version and the JAX-RS library that you are using, you may run into problems when calling the PATCH method. If you do, see if any of these help:
PATCH request using Jersey Client
HttpURLConnection Invalid HTTP method: PATCH)
Invalid HTTP method: PATCH
The issue was in WebTarget object:
WebTarget target = client.target(baseUrl).path(resourcePath)
.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND,"true");
PATCH method only works when SET_METHOD_WORKAROUND is true.
Related
I have a interface for getting responses from an API server, the result is a future containing the response for a request string, my question is what is better and efficient way without repeating code to cache the results, currently in each implementation of the method I am doing map.get() from in memory cache if is cached, but it is repetitive since in each method I am writing the same. If it's useful, I'm using OkHttp, just in case it's possible to use some kind of interceptor or some other way, thanks..
interface SodyApi {
ListenableFuture<FriendsListResponse> fetchFriendsList(String repo);
ListenableFuture<GuildResponse> fetchGuild(String repo);
ListenableFuture<UsersListResponse> fetchAllUsers(String repo);
}
class SodyApiImpl implements SodyApi {
final Map<String, ListenableFuture<Response>> map = new HashMap();
public ListenableFuture<FriendsList> fetchFriendsList(String repo) {
if (map.containsKey(repo))
return map.get(repo);
// .... get response with okHttp
}
public ListenableFuture<GuildResponse> fetchGuild(String repo) {
if (map.containsKey(repo))
return map.get(repo);
// .... get response with okHttp
}
public ListenableFuture<UsersListResponse> fetchAllUsers(String repo) {
if (map.containsKey(repo))
return map.get(repo);
// .... get response with okHttp
}
}
I want to create a REST API client, which for the same REST API server will call different URLs. This different calls will return JSON and XML to the client.
What would be a good design pattern for this situation ?
So far I've come up with a combination of Strategy and Command:
public interface IRestCall {
/** Setup the URL for the call. */
void setup(IRestSetup setup) throws Exception;
/** Execute the call, using the URL set up in the first step.
* #throws Exception */
void call() throws Exception;
/** Process the result and return to the user. */
<T> T getResult(IRestResultProcessor<T> result) throws Exception;
}
This is the Strategy interface. The context for the Strategy will
be in some Get/Post/Put methods in a Facade class.
IRestSetup and IRestResultProcessor are interfaces for Command objects
which will setup the URL for the REST API and will process the result.
I don't think you need some special design pattern to handle that situation. I personally would just add some generic methods for GET and POST requests. The code below handles only GET requests but it should be enough to get an idea what I mean.
Your client method processing GET requests might look something like
/**
restUrl - url to the service
resClz - the actual POJO object that the JSON or XML response will be mapped to
resType - type of MIME object returned by the server (typically MediaType.APPLICATION_JSON or MediaType.APPLICATION_XML)
*/
<T> T doRestGet(String restUrl, Class<T> resClz, String resType){
T obj;
Client client = ClientBuilder.newClient();
WebTarget target = client.target(UriBuilder.fromUri("http://localhost:8088/Your_WS_root").build());
try{
obj =(T) target.path(restUrl).request()
.accept(resType).get().readEntity(resClz);
}catch(Exception e){
System.out.println(e);//log or propagate the exception
return null;
}
return obj;
}
Your server method might look something like
#GET
#Path("/userMsg")
#Produces(MediaType.APPLICATION_JSON)
public UserMessage getUsersOne() {
UserMessage uMsg = new UserMessage();
uMsg.setUserMsg("successful call");
return uMsg;
}
Now you'd call your service
UserMessage uMsg = (UserMessage)doRestGet("userMsg", UserMessage.class, MediaType.APPLICATION_JSON );
I have a simple REST client with GET POST and DELETE methods.
Weird things is that only GET methods work, neither POST nor DELETE doesn't even get hit and response is "404 Not Found" of course.
Here's my REST service and the client:
Interface:
public interface MyInterface {
#GET
#Path("/content")
#Produces(MediaType.APPLICATION_JSON)
Response getAirports();
#DELETE
#Path("/content/{id}")
#Produces(MediaType.APPLICATION_JSON)
Response deleteAirport(#PathParam("id") String id);
}
Implementation:
#Path("/source")
public class SourceService extends AbstractService implements MyInterface {
#Override
public Response getContent() {
DBCollection collection = getDBCollection("content");
DBCursor cursor = collection.find();
String serialize = JSON.serialize(cursor);
return Response.status(Response.Status.OK).entity(serialize).build();
}
#Override
public Response deleteContent(#PathParam("id") Integer id) {
DBCollection collection = getDBCollection("content");
BasicDBObject query = new BasicDBObject();
query.append("id", id);
collection.remove(query);
return Response.status(Response.Status.OK).build();
}
}
Client:
// This is working
public void getContent() {
WebTarget path = collect.path("/content");
Response response = path.request().get();
LOGGER.info("collect.ping: " + response.readEntity(String.class) + "\n");
}
// This is not working
public void deleteContent(Integer id) {
WebTarget path = collect.path("/content/"+id);
Response response = path.request(MediaType.APPLICATION_JSON).delete();
System.out.println("object deleted:"+response);
}
I've tried requesting with jersey or apache clients but all of them return 404 and I'm like hopeless now.
Hope you can give me a direction.
This looks like a possible duplicate of Inheritance with JAX-RS. Have you tried replicating all annotations in the subclass or none, means do not use #PathParam in the implementation class at all?
If you actually can debug your client and you are indeed able to "Step through" the client code?
If you place a break-point within your server code and you never actually "break" on it? Then the problem is with the way you are exposing your web service and how you are then trying to consume it.
Try to change the parameter type expected by the Server and the type you pass from your client.
If you can change it on the server and client to a simpler type.. i.e.. an integer.. and then you can actually capture a breakpoint in both client and server, then you know that the problem is in your types.
I hope you can understand what I'm saying? You really need to simplify your parameters and/or try it without parameters first.
When you get something simpler working, then you can extend it to something else.
try just changing it to a string... such as "airport" Also, you are passing a parameter in the client as this:
public void deleteAirport(String iata) {
But you don't use "iata" in your client code...
In our case, we want to get raw POST body and use request.getParameter() at the same time. But if we call request.getParameter(), we would not able to read raw body.
I found a solution for servlet 2.x Http Servlet request lose params from POST body after read it once.
But for servlet 3.x, ServletInputStream API is changed. The ServletInputStream now has abstract isReady(), isFinished() and setReadListener() to deal with non-blocking IO which must be implemented. Any idea to do this in servlet 3.x?
And for tomcat 7, it seems it doesn't call getInputStream when parsing parameter.
The new Servlet 3.1 methods in ServletInputStream could be implemented as follows, extended the linked solution:
public class CachedServletInputStream extends ServletInputStream {
private ByteArrayInputStream input;
public CachedServletInputStream(byte[] cached) {
/* create a new input stream from the cached request body */
input = new ByteArrayInputStream(cached);
}
public int read() throws IOException {
return input.read();
}
public boolean isFinished() {
return input.available() == 0;
}
public boolean isReady() {
return true;
}
public void setReadListener(ReadListener listener) {
listener.onAllDataRead();
}
}
Not sure if the ReadListener also needs a callback to onDataAvailable(). Alternatively you could also throw an UnsupportedOperationException from that method which maybe never is called in your application.
Say I have 2 classes in an SOA model application..
Service class - which takes request and returns response
For further processing (say, business logic/parsing/dao etc), it passes the request to a SvcBusiness class.
Question is, should SvcBusiness class use the request as its class variable or should it just use the request in one of it's business methods? It is possible that request needs to be passed to other lower layers like DAO layer. Should those classes also use request as a class variable or should the request be just part of a method?
ServiceImpl class:
public class ServiceImpl {
public Response getDataForType1Request(Request type1) {
SvcBusiness buzclazz = new SvcBusiness();
return buzclazz.doOperationForType1(type1);
}
public Response getDataForType2Request(Request type2) {
SvcBusiness buzclazz = new SvcBusiness();
return buzclazz.doOperationForType2(type2);
}
}
Option 1: when request is passed as a parameter.
public class SvcBusiness {
public Response doOperationForType1(Request type1) {
// do business and return response1
}
public Response doOperationForType2(Request type2) {
// do business and return response2
}
}
Option 2: request is set as a class variable. In this scenario.. ServiceImpl will pass the request to SvcBusiness constructor when the object is created.. and will simply call execute() method.
public class SvcBusiness {
private Request request;
public SvcBusiness(Request request) {
this.request = request;
}
private Response doOperationForType1() {
// do business and return response1
}
private Response doOperationForType2() {
// do business and return response2
}
public Response execute() {
// if type1 request call doOperationForType1()
// if type2 request call doOperationForType1()
}
}
Please help! What are the advantages and disadvantages of both? Is there a design pattern to address this scenario?
Don't use the Request (and Response) further down in your class hierarchy! The service (and everything called by the service) may be called from somewhere else, where there is no such thing as a Request. And then you will have a problem with filling that parameter. Use an own data model in the service, and extract and convert everything you need for that from the Request.
Fully agree with Uwe's answer. However, if you still want to use Request class, it'll be less harmful as a parameter (The way Servlets work). Otherwise, you'd have to deal with synchronization on a highly probable multithreaded environment.
When I face a problem like this I always wonder if I really need an object. Usually I use the option 1 but creating all methods as static. As those methods don't rely in the current object state (there are no instance attributes), I save some memory just not creating such objects (other option is just implement the Singleton pattern).
public class SvcBusiness {
public static Response doOperationForType1(Request type1) {
// do business and return response1
}
public Response doOperationForType2(Request type2) {
// do business and return response2
}
}