Server GET json in jersey, JAVA - java

im not sure how to get a json object and output it in jersey using rest GET from a ajax json post, im using grizzly server, server has been set, heres the code that supposed to get the json, correct me please, thanks!
import java.io.IOException;
import java.io.InputStream;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
import org.apache.commons.io.IOUtils;
import javax.ws.rs.*;
#Path("/helloworld")
public class GetData {
#GET
#Consumes("application/json")
public String getResource(JSONObject obj) throws IOException {
InputStream in = (InputStream) obj.values();
String data = IOUtils.toString(in);
JSONObject out = (JSONObject) JSONSerializer.toJSON(data);
String result = out.getString("name");
return result;
}
}

You need to find out, what is your JSON object should be deserialized to. If it's just a JSONObject and you want to parse it manually:
#Consumes("application/json")
public String getResource(JSONObject obj) {
...
}
If it is some kind of custom object:
#Consumes("application/json")
public String getResource(CustomObj customObj) {
...
}
But then you should take care about marshalling/unmarshalling of that object to JSON by Jackson.

Related

How to get a jakarta.json.JsonObject Response using the Java 11 HttpClient?

I want to fetch a jakarta.json.JsonObject in the HttpResponse itself using the Jakarta JSONP API. Right now, I have to fetch it as a String, feed the body into a reader and then get the JsonObject like the code below.
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonReader;
HttpRequest request = HttpRequest.newBuilder().uri(uri).GET().build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
JsonReader jsonReader = Json.createReader(new StringReader(response.body()));
JsonObject object = jsonReader.readObject();
jsonReader.close();
How do I get the response as HttpResponse<JsonObject> response directly? I don't want to use any external libraries other than the Jakarta JSONP one.
Edit: As an example, one could write their own BodyHandler like this:
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodySubscriber;
import java.net.http.HttpResponse.BodySubscribers;
import java.net.http.HttpResponse.ResponseInfo;
import jakarta.json.JsonObject;
public class JsonObjectBodyHandler implements HttpResponse.BodyHandler<JsonObject> {
#Override
public BodySubscriber<JsonObject> apply(ResponseInfo responseInfo) {
// How to implement this
}
}
and then use it in the function like this:
HttpResponse<JsonObject> response = httpClient.send(request, new JsonObjectBodyHandler());

Can I send an excel file and JSON body with a description of file in same REST API Response

I have an API which returns APPLICATION_OCTET_STREAM as Media Type in response. I need to enhance it to also send a JSON body with some details regarding the file, say counts of right and wrong records in the file. So basically I need two kinds of response in same API. Is this doable ?
It's possible, but you will need to use a Multipart response. Keep in mind though that some clients will not be able to handle this type of response. You'll normally see this data type using in uploading files, but is not very often used as a response data type.
That being said, below is a complete example using the Jersey Test Framework. In the resource, a file and some extra data are being sent in the response, with the use of Jersey's FormDataMultiPart
#Path("test")
public static class TestResource {
#GET
#Produces(MediaType.MULTIPART_FORM_DATA)
public Response get() throws Exception {
final MultiPart multiPart = new FormDataMultiPart()
.field("json-data", new Model("Test Value"), MediaType.APPLICATION_JSON_TYPE)
.bodyPart(new FileDataBodyPart("file-data", new File("test.txt")));
return Response.ok(multiPart).build();
}
}
To make the test succeed, you should have a file called test.txt with the content "Some Test Data in File" (without quotes) on the first line of that file. This multipart response has two parts, the json-data part, which uses a Model class to model the JSON, and the file-data part which has the contents of the file.
To make the Multipart work, we need to have the MultiPartFeature register on the server and the client (for client side deserialization) and we need to have the multipart dependency in our project.
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey2.version}</version>
</dependency>
On the client, to get the multipart out of the response, we should read the entity as FormDataMultiPart, then we can get individual parts by name and extract them by their data type.
Response res = target("test").request().get();
FormDataMultiPart multiPart = res.readEntity(FormDataMultiPart.class);
FormDataBodyPart jsonPart = multiPart.getField("json-data");
FormDataBodyPart filePart = multiPart.getField("file-data");
Model jsonData = jsonPart.getValueAs(Model.class);
InputStream file = filePart.getValueAs(InputStream.class);
Below is the complete test.
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import static org.assertj.core.api.Assertions.assertThat;
public class MultipartResponseTest extends JerseyTest {
public static class Model {
private String value;
public Model() {}
public Model(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
}
#Path("test")
public static class TestResource {
#GET
#Produces(MediaType.MULTIPART_FORM_DATA)
public Response get() throws Exception {
final MultiPart multiPart = new FormDataMultiPart()
.field("json-data", new Model("Test Value"), MediaType.APPLICATION_JSON_TYPE)
.bodyPart(new FileDataBodyPart("file-data", new File("test.txt")));
return Response.ok(multiPart).build();
}
}
#Override
public ResourceConfig configure() {
return new ResourceConfig()
.register(TestResource.class)
.register(MultiPartFeature.class);
}
#Override
public void configureClient(ClientConfig config) {
config.register(MultiPartFeature.class);
}
#Test
public void testIt() throws Exception {
final Response res = target("test")
.request().get();
FormDataMultiPart multiPart = res.readEntity(FormDataMultiPart.class);
FormDataBodyPart jsonPart = multiPart.getField("json-data");
FormDataBodyPart filePart = multiPart.getField("file-data");
Model jsonData = jsonPart.getValueAs(Model.class);
InputStream file = filePart.getValueAs(InputStream.class);
BufferedReader fileReader = new BufferedReader(new InputStreamReader(file));
String fileData = fileReader.readLine();
file.close();
fileReader.close();
System.out.println(jsonData.getValue());
System.out.println(fileData);
assertThat(jsonData.getValue()).isEqualTo("Test Value");
assertThat(fileData).isEqualTo("Some Test Data in File");
}
}
To use the test framework, you should add the following dependency
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${jersey2.version}</version>
</dependency>

Sending HTTP POST request with custom JSON file in the request body

I'm facing with some issue in my java code:
package com.automation.com.automation.<name>;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.junit.Test;
import static com.jayway.restassured.RestAssured.*;
import java.io.FileNotFoundException;
import java.io.FileReader;
public class SendDCandidateDate {
#Test
public void sendCandidateData() throws FileNotFoundException {
String accessToken = "<your access token comes here>";
String apiUrl = "<your API url comes here>";
JSONParser parser = new JSONParser();
try {
Object object = parser.parse(new FileReader("src/main/resources/Full_List.json"));
JSONObject jsonObject = (JSONObject) object;
given().auth().preemptive().oauth2(accessToken);
given().body(jsonObject).when().post(apiUrl).then().assertThat().statusCode(200);
}catch (Exception ex) {
System.out.println(ex);
}
}
}
I have no exception, however the assertion comes back with error 404 instead of 200. (Error 401 is also acceptable for now, which means the accessToken is expired it would be also an expected behaviour).
I think I have a logical issue in my code, can anyone help me with it?

Unsupported Media Type (415) for POST request to Restlet service

I POST to an endpoint like following:
import java.util.logging.Level;
import org.json.JSONException;
import org.json.JSONObject;
import org.restlet.ext.json.JsonRepresentation;
import org.restlet.representation.Representation;
import org.restlet.resource.Post;
import org.restlet.resource.ServerResource;
try {
JSONObject jsonToCallback = AcceptorManager.getJsonFromClient();
String test = jsonToCallback.getString("test");
String st2 = jsonToCallback.getString("st2");
ClientResource clientResource = new ClientResource(callback);
clientResource.setMethod(Method.POST);
Form form = new Form ();
form.add("key1", val1);
form.add("key2", "stat");
Representation representation = clientResource.post(form, MediaType.APPLICATION_JSON);
} catch (Exception e) {
//Here I get "Unsupported Media Type (415) - Unsupported Media Type"
}
And this is the endpoint:
public class test extends ServerResource{
#Post
public JSONObject testPost(JSONObject autoStackRep) throws JSONException, AcceptorException {
JSONObject json=new JSONObject();
try {
json.put("result",false);
json.put("id",1);
} catch (JSONException e) {
e.printStackTrace();
}
return json;
}
}
How can I fix this issue?
Passing JSONObject as input parameter of your POST method doesn't make it accept appication/json. Restlet has several ways of specifying accepted Media-Type. You can specify it in #Post annotation like this:
#Post("json")
public Representation testPost(Representation autoStackRep)
If only one extension is provided, the extension applies to both request and response entities. If two extensions are provided, separated by a colon, then the first one is for the request entity and the second one for the response entity. Note that parameter type is now Representation. You can use Representation.getText() method to retrieve content of response entity. You may also specify POJO as parameter type:
#Post("json")
public MyOutputBean accept(MyInputBean input)
In this case you need Jackson extension to be able to map JSON to POJO and vice versa. Just make sure org.restlet.ext.jackson.jar is in your classpath. You may omit media type declaration when using POJO as parameter, in this case Restlet will try to apply all available converters to input stream to map it to your POJO.

Passing an object to a REST Web Service using Jersey

I have a simple WS that is a #PUT and takes in an object
#Path("test")
public class Test {
#PUT
#Path("{nid}"}
#Consumes("application/xml")
#Produces({"application/xml", "application/json"})
public WolResponse callWol(#PathParam("nid") WolRequest nid) {
WolResponse response = new WolResponse();
response.setResult(result);
response.setMessage(nid.getId());
return response;
}
and my client side code is...
WebResource wr = client.resource(myurl);
WolResponse resp = wr.accept("application/xml").put(WolResponse.class, wolRequest);
I am trying to pass an instance of WolRequest into the #PUT Webservice. I am constantly getting 405 errors trying to do this..
How can I pass an object from the client to the server via Jersey ? Do I use a query param or the request ?
Both my POJOs (WolRequest and WolResponse) have the XMlRootElement tag defined so i can produce and consume xml..
I think the usage of the #PathParam is not correct here. A #PathParam is can basically be a String (see its javadoc for more info).
You can
use the #PathParam as a String parameter or
don't define WolRequest as a #PathParam.
The first approach:
#Path("test")
public class Test {
#PUT
#Path("{nid}")
#Consumes("application/xml")
#Produces({"application/xml", "application/json"})
public WolResponse callWol(#PathParam("nid") String nid) {
WolResponse response = new WolResponse();
response.setResult(result);
response.setMessage(nid);
return response;
}
This will accept urls like: "text/12", 12 will then be the String nid. It doesn't look like this will help what you are trying to do.
The second approach:
#Path("test")
public class Test {
#PUT
#Consumes("application/xml")
#Produces({"application/xml", "application/json"})
public WolResponse callWol(WolRequest nid) {
WolResponse response = new WolResponse();
response.setResult(result);
response.setMessage(nid.getId());
return response;
}
Your client code can be like you specified, only the url for PUT is: "test". Perhaps you need a combination of both one #PathParam for your id and one "normal" parameter to get your request data.
Check this link https://www.vogella.com/tutorials/REST/article.html
As per the code sample of method putTodo of class TodoResource ,
your code should be like this.
#Path("test")
public class Test{
#PUT
#Consumes("application/xml")
#Produces({"application/xml", "application/json"})
public WolResponse callWol(JAXBElement<WolRequest> nid) {
WolResponse response = new WolResponse();
response.setResult(result);
response.setMessage(nid.getValue().getId());
return response;
}
}
Hope this will solve your problem.
You can try something like this
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
public Response callWol(WolRequest nid) {
WolResponse response = new WolResponse();
response.setResult(result);
response.setMessage(nid.getValue().getId());
return Response.status(Status.OK).entity(response).build();
}
You can try #PUT instead of #Post as well. Hope this helps
I had the same problem I solved in 3 Steps with Jackson in Netbeans/Glashfish btw.
1)Requirements :
some of the Jars I used :
commons-codec-1.10.jar
commons-logging-1.2.jar
log4j-1.2.17.jar
httpcore-4.4.4.jar
jackson-jaxrs-json-provider-2.6.4.jar
avalon-logkit-2.2.1.jar
javax.servlet-api-4.0.0-b01.jar
httpclient-4.5.1.jar
jackson-jaxrs-json-provider-2.6.4.jar
jackson-databind-2.7.0-rc1.jar
jackson-annotations-2.7.0-rc1.jar
jackson-core-2.7.0-rc1.jar
If I missed any of the jar above , you can download from Maven here http://mvnrepository.com/artifact/com.fasterxml.jackson.core
2)Java Class where you send your Post.
First ,Convert with Jackson the Entity User to Json and then send it to your Rest Class.
import com.fasterxml.jackson.databind.ObjectMapper;
import ht.gouv.mtptc.siiv.model.seguridad.Usuario;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.simple.JSONObject;
public class PostRest {
public static void main(String args[]) throws UnsupportedEncodingException, IOException {
// 1. create HttpClient
DefaultHttpClient httpclient = new DefaultHttpClient();
// 2. make POST request to the given URL
HttpPost httpPost
= new HttpPost("http://localhost:8083/i360/rest/seguridad/obtenerEntidad");
String json = "";
Usuario u = new Usuario();
u.setId(99L);
// 3. build jsonObject
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", u.getId());
// 4. convert JSONObject to JSON to String
//json = jsonObject.toString();
// ** Alternative way to convert Person object to JSON string usin Jackson Lib
//ObjectMapper mapper = new ObjectMapper();
//json = mapper.writeValueAsString(person);
ObjectMapper mapper = new ObjectMapper();
json = mapper.writeValueAsString(u);
// 5. set json to StringEntity
StringEntity se = new StringEntity(json,"UTF-8");
// 6. set httpPost Entity
httpPost.setEntity(se);
// 7. Set some headers to inform server about the type of the content
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
// 8. Execute POST request to the given URL
HttpResponse httpResponse = httpclient.execute(httpPost);
// 9. receive response as inputStream
//inputStream = httpResponse.getEntity().getContent();
}
}
3)Java Class Rest where you want to receive the Entity JPA/Hibernate .
Here with your MediaType.APPLICATION_JSON you recieve the Entity in this way :
""id":99,"usuarioPadre":null,"nickname":null,"clave":null,"nombre":null,"apellidos":null,"isLoginWeb":null,"isLoginMovil":null,"estado":null,"correoElectronico":null,"imagePerfil":null,"perfil":null,"urlCambioClave":null,"telefono":null,"celular":null,"isFree":null,"proyectoUsuarioList":null,"cuentaActiva":null,"keyUser":null,"isCambiaPassword":null,"videoList":null,"idSocial":null,"tipoSocial":null,"idPlanActivo":null,"cantidadMbContratado":null,"cantidadMbConsumido":null,"cuotaMb":null,"fechaInicio":null,"fechaFin":null}"
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.apache.log4j.Logger;
#Path("/seguridad")
public class SeguridadRest implements Serializable {
#POST
#Path("obtenerEntidad")
#Consumes(MediaType.APPLICATION_JSON)
public JSONArray obtenerEntidad(Usuario u) {
JSONArray array = new JSONArray();
LOG.fatal(">>>Finally this is my entity(JPA/Hibernate) which
will print the ID 99 as showed above :" + u.toString());
return array;//this is empty
}
..
Some tips : If you have problem with running the web after using this code may be because of the #Consumes in XML ... you must set it as #Consumes(MediaType.APPLICATION_JSON)
Try this it will work
Server Side:
#PUT
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
public String addRecord(CustomClass mCustomClass)
{
///
///
///
return "Added successfully : "+CustomClass.getName();
}// addRecord
Client Side:
public static void main(String[] args)
{
///
///
///
CustomClass mCustomClass = new CustomClass();
Client client = ClientBuilder.newClient();
String strResult = client.target(REST_SERVICE_URL).request(MediaType.APPLICATION_XML).put(Entity.xml(mCustomClass), String.class);
}

Categories