How can you consume a distant rest api using gwt? - java

I have a couple of sipring boot restfull APIs, that I want to communicate with, from a GWT based front-end. I've looked a bit on the Internet and found the RestyGWT framework, but as far as I've seen, all the documentation available is for using the embeded GWT server as a restfull API.
Can anyone please direct me to a usefull tutorial that I can follow.
Thanks to all.
I actually found a way to GET data through JsonPRequestBuilder, the problem now resides in POSTing data in json format.

final RequestBuilder reqBuilder = new RequestBuilder(httpMethod, url);
final Request request = reqBuilder.sendRequest(requestData, new RequestCallback()
{
#Override
public void onResponseReceived(Request request, Response response)
{
GWT.log(response.getText());
}
#Override
public void onError(Request request, Throwable exception)
{
}
}
httpMethod is something from com.google.gwt.http.client.Method like Method.GET
request is a String in which you pass the json.
response.getText will display the json.
To convert from object to json I would suggest to look at https://github.com/nmorel/gwt-jackson or https://github.com/vegegoku/gwt-jackson-apt (first one is older and has more features, second one is newer and better suited for future (GWT 3.0) but maybe has some features missing).

Related

How to handle a POST request with a Servlet API

I am trying to make an API with Jetty Server, and I have this simple GET request:
#GET
public String helloWorld(){
return "Hello world";
}
In order to make a POST request, I assume that one must save the input to the Jetty server. I have tried to research for quite a while, but found nothing.
I imagine something like this:
#POST
public void Save(String stringToSave) {
// Save to DB?
}
You could likely google this but let me give you a quick overview. A Servlet is a chunk of code that is normally run during an HTTP action - GET, POST, etc. It is the original technology of the JavaEE world, having been released in the late 1990's.
A simple Java servlet, using modern annotations, would look something like:
#WebServlet(name = "SampleServlet", urlPatterns = "/sampleServlet")
public class SampleServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// called when an HTTP POST is sent
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// called when an HTTP GET is sent
}
}
The important parts to note are that the class extends HttpServlet and that you have to write code to pull data out of the request and push it into the response. This isn't bad to do but it does have to be done.
JAX-RS is a newer standard, aimed simplifying the creation of REST services. It too is a chunk of code that runs during an HTTP interaction.
A simple example of this would be:
#Path("/sampleService")
public class SampleService{
#Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#POST
#Path("/v1/hello")
public Response sayHello( SomeObject someobject ) {
The code here is both simpler and a bit more complex. The use of annotations helps determine the path that the service exists on a URL (in this case /sampleService/v1/hello), the HTTP method, and the Content-Type for both the request and response. Additionally, if the SomeObject object is defined correctly, the JAX-RS framework will automatically deserialize the incoming JSON or XML payload into an object for you.
The Response object contains the HTTP response code (perhaps a teapot) and a response body. In this example, the body will be automatically serialized back to the requestor in a way that matches the Accept header of the HTTP request (i.e., JSON for an application/json Accept header and XML for application/xml).
Note that while not directly related the JAX-RS framework takes advantage of the Servlet framework. Indeed in JAX-RS you can access the HttpServletRequest and HttpServletResponse object in your methods.
Which way is "better"? In general I would recommend using JAX-RS where possible as it is the newer standard and is a bit easier to implement. However, if you do any work in the JavaEE world you're very likely to run into Servlet code so it's important to understand it too.
Note that both Servlets and JAX-RS require an application server of some sort. Jetty is one of those. Another very common one is Tomcat. The application server sets up the environment for your code and listens for incoming HTTP messages. When it gets one it looks to see if it knows how to handle the URL and routes to the appropriate place. In the servlet world the server routes solely on the URL. In the JAX-RS world the server routes on the URL and, if specified by the #Consumes annotation, the HTTP Content-Type header too.
There is much more but let's start there and see if it answers what you're after.

Get JSON message in JAX-RS web service filter

I have a web service method as follow (deployed on WebLogic 12.2.1), which I can receive the JSON request body in the POJO object "requestParameters":
#POST
#SessionChecker
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("LogIn")
public Response logIn(#Context HttpServletRequest request, Parameters requestParameters) {
....
}
I have a filter that I want to intercept the request before the above web service method is called.
#Provider
#SessionChecker
public class CheckSessionFilter implements ContainerRequestFilter {
#Context
private HttpServletRequest servletRequest;
#Override
public void filter(ContainerRequestContext requestContext) throws WebApplicationException {
....
}
}
In the filter() method, how do I get the JSON message body into the POJO object of type Parameters? I just need to get one attribute from the JSON message. After the filter is done, the JSON message should pass on to the web service method without change.
Thanks in advance.
Here's the problem. When your filter is hit, the request stream (InputStream) hasn't been read yet. So if you try to read it, then Jersey will not be able to read it, as a stream can only be read once, so it will be empty.
Jersey actually offers a solution to this. The ContainerRequestContext, is actually an instance of Jersey specific ContainerRequest. If you look at the linked API, you will find a bufferEntity() method. This allows us to read the entity, and Jersey will be able to read it again. So your first step is to make that call
#Override
public void filter(ContainerRequestContext requestContext)
ContainerRequest cr = (ContainerRequest) requestContext;
cr.bufferEntity();
}
Now you can get the entity. If you look at the API for ContainerRequest, there are also methods to readEntity(..). If you are familiar with the JAX-RS Client API, you may have before used Response#readEntity(...class) to read the response entity. The ContainerRequest#readEntity(..) works pretty much the same way.
So if you know what the JSON format is supposed to be, and you have the POJO, you could do
POJO pojo = cr.readEntity(POJO.class);
Otherwise, if the format will change from request to request, you could extract the data as a map
Map<String, Object> json = cr.readEntity(new GenericType<Map<String, Object>>(){});
UPDATE
If you are using one JAX-RS APIs, and not Jersey specific APIs, then the above is not doable. You will instead need to read the stream to get the JSON, and set the stream back, so that Jersey can read it. If might look something like
InputStream entityIn = requestContext.getEntityStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// write `entityIn` to `baos`
byte[] bytes = baos.toByteArray();
POJO pojo = new ObjectMapper().readValue(bytes, POJO.class);
// do something with POJO
requestContext.setEntityStream(new ByteArrayInputStream(bytes));
Of course you will need to some JSON deserializer to do this. I just used Jackson in the example.
It's not as elegant as the first example, but you don't have much option if you are strictly sticking the JAX-RS APIs. If you can I would suggest just adding the Jersey dependencies to your project as provided (compile-time) so that you can use the APIs, since you are using Jersey with WebLogic anyway.

Cloud Endpoints: Access Paramters in Servlet Filter

I'm trying to build an api with Google Cloud Endpoints.
As Cloud Endpoints does not provide authentication beside Googles own OAuth I try to build my own. Therefore I want to access the parameters provided for the API (for example #Named("token") token) inside a servlet filter.
Unfortunately I cannot find any of the provided information inside the httpRequest. Is that normal? Is there a possibility to access the parameters?
I would appreciate if someone could help me!
UPDATE:
With the infos from jirungaray I tried to build an authentication using headers but ran into the same problem. Used a REST-Client to send some headers as I could not figure out how to do this with the API Explorer. Inside my filter I try to access the token from the headers:
#Override
public void doFilter(
ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String authToken = httpRequest.getHeader(Constants.AUTH_TOKEN);
...
chain.doFilter(request, response);
}
The reason why I try to do something like this, is that I'm using Guice for Dependency Injection and want my token to be injected inside another object.
With Guice I have the following Provider using the token to inject a FacebookClient (using the token) per request.
#Provides
public FacebookClient getFacebookClientProvider(#Named("fbToken") Provider<String> fbToken) {
return new DefaultFacebookClient(fbToken.get(), Version.VERSION_2_2);
}
As described in the Guice wiki (SevletModule) this uses a sevlet filter to get the information from the request.
Is there any solution to achieve this kind of DI with Cloud Endpoints?
Philip,
Yes, it does makes sense you are getting an empty request. Your endpoint calls are first handled by Google (they receive the API calls) and then those are processed and sent to a handler in your app. As this is all done in the background it's very easy to miss that your endpoints aren't actually getting the same request you sent, they get a completely different request sent from Google's infrastructure.
Even though your approach should work including tokens info in url makes them easier to sniff, even if you use SSL or encrypt your params the token is there in plain sight.
For what you are trying to achieve I recommend you include the token as a header in your request and retrieve that header by accessing the HTTPRequest directly on the endpoint, this is injected automatically if you include an HTTPServletRequest param in you endpoint method.
eg.
public APIResponse doSomething(SomeComplexRquestModel request,
HttpServletRequest rawRequest) {
}
If you still feel you should go with your original approach just comment and I'll help you debug the issue.

Configure Response object for Rest Services inside a Jersey-Grizzly server, in OSGi container (CORS error prevention with Jersey 1x)

The last couple of days, I have been struggling with an issue. I've created a rest service hosted by a Grizzly server inside an OSGi container. Everything is working perfectly at this point.
Now, I want to add a header in every response.Not so complex or illogical right? Yet, I can't find a way to do it.
I have tried to:
1) Get the response object inside the rest functions as this question suggests (pretty textbook when you are not under OSGi).
2) Add a handler using the code above (in this case the service method is never called)
server.getServerConfiguration().addHttpHandler(
new HttpHandler() {
#Override
public void service(Request arg0, Response arg1)
throws Exception {
arg1.setHeader("Access-Control-Allow-Origin", "*");
}
});
I am using jersey-server/client/core 1.18.1 and grizzly2-server 1.18.1, hence i prefer a solution that can be applied in this version, but I am willing to update jar versions if it cannot be done in 1.18.x.
You could give a try to Jersey filters.
In a nutshell, you should create class implementing ContainerResponseFilter:
public class MyFilter implements ContainerResponseFilter {
#Override
public void filter(
ContainerRequest request,
ContainerResponse response
) throws IOException {
request.getHttpHeaders().add(<header name>, <header value>);
}
}
Then, you should register this filter in your Jersey server configuration.
Please, note, that this filter would be invoked on every response. To bind it only to specific resources, you could use annotation-binding, that is described here.
All other information you could find here.

HttpServletRequest.getParameter() returns null

Here is a little background of my problem:
I'm using Spring MVC 3.1.2.RELEASE. The server is deployed on Amazon AWS. I have a simple controller.
public class MyWebController implements Controller {
#Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
try {
String delegateGuid = request.getParameter("delegateGuid");
String serviceCodesToBeUpdated = request.getParameter("serviceCodesToBeUpdated");
if (StringUtils.isBlank(delegateGuid) || StringUtils.isBlank(serviceCodesToBeUpdated)) {
throw new MyException("delegateGuid and/or serviceCodesToBeUpdted cannot be null or empty");
}
...
I have a client script that makes POST request to this endpoint. But sometimes, I hit this MyException that tells me the params are not set. But client logs show that the params are set correctly before sending the requests. The difficult part of debugging this is that it is not reproducible.
Does anyone know what could possibly have caused this issue? I know this might not be the level of detail enough to identify the problem. But if you can suggest any debug logs I could insert into my code, that would be helpful as well. I'm lost in that I don't even know where to start debugging this.
Thanks.

Categories

Resources