Implement a JUnit test for a rest service - java

I have to implement some JUnit tests for my rest services.
For instance this is one of my Rest services:
#Path("/dni-fe")
public class HelloWorld
{
#POST
#Path("/home")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public MachineResponse doMachineRegister(MachineBean machineBean)
{
MachineResponse response = new MachineResponse();
String name = machineBean.getName();
String country = machineBean.getCountry();
String company = machineBean.getCompany();
String model = machineBean.getModel();
//make some stuff and some queries on db to populate the response object
return response;
}
And here is my test on this service:
public class MachineResponseTest {
private static final String BASE_URI = "http://localhost:8080/dni-fe/home"
#Test
public void testDevice() {
WebResource resource = Client.create().resource(BASE_URI);
resource.accept(MediaType.APPLICATION_JSON);
StringBuilder sb = new StringBuilder();
sb.append("{\"name\":\"123456\",\n");
sb.append(" \"country\":\"Spain\",\n");
sb.append(" \"company\":\"xxx\",\n");
sb.append(" \"model\":\"1.10.0\"\n}");
MachineResponse result = resource.post(MachineResponse.class,sb.toString());
}
The test fails with the following error:
com.sun.jersey.api.client.UniformInterfaceException: POST
http://localhost:8080/dni-fe/home returned a response status of 415
Unsupported Media Type at
com.sun.jersey.api.client.WebResource.handle(WebResource.java:686)

I am fairly sure you have to use .type(MediaType.APPLICATION_JSON), not .accept(

You can use simple JSONObject from org.json.JSONObject and pass data as toString of it. Sample code is
JSONObject address = new JSONObject();
address.put("line1", address1);
address.put("line2", address2);
address.put("city", city);
address.put("state", state);
address.put("postalCode", zip);
address.put("country", "US");
address.toString()

Related

How to send multiple HTTP requests from the same service in Java?

Java noob here. I'm trying to develop a web service as per the following diagram.
When a POST request is sent to the REST server, with certain values, the values (being read from a list, in a loop) get inserted in a table (new row with an id). Server returns HTTP 202 Accepted.
To ensure that the resource(with id from 1) is created, a GET request is issued that returns the POJO as Json.
Finally a PATCH request is sent to update a certain column.
I have written a service class that does all three tasks when each API is called individually. I need to implement something that would automatically execute steps 2 and 3 when a POST request is sent to the server. Here's my code so far.
#Path("attachments")
public class FilesService {
private TiedostoService tiedostoService;
private AttachmentService attachmentService;
#GET
#Path("{id}")
#Produces({MediaType.APPLICATION_JSON})
public Response listAttachmentsAsJson(#PathParam("id") Integer attachmentId) throws Exception {
attachmentService = new AttachmentService();
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Attachment attachment = attachmentService.getAttachment(attachmentId);
String jsonString = gson.toJson(attachment.toString());
return Response.status(Response.Status.OK).entity(jsonString).build();
}
#PATCH
#Path("{id}")
#Produces({MediaType.APPLICATION_JSON})
public Response patchAttachments(#PathParam("id") Integer attachmentId) throws Exception {
attachmentService = new AttachmentService();
Integer update = attachmentService.update(attachmentId);
String jsonString = new Gson().toJson(update);
return Response.status(Response.Status.ACCEPTED).entity(jsonString).build();
}
#POST
#Produces({MediaType.APPLICATION_JSON})
public Response migrateToMinio(#Context UriInfo uriInfo) throws Exception {
Response response;
List<String> responseList = new ArrayList<>();
tiedostoService = new TiedostoService();
attachmentService = new AttachmentService();
List<Tiedosto> tiedostoList = tiedostoService.getAllFiles();
String responseString = null;
int i = 1;
for (Tiedosto tiedosto : tiedostoList) {
Attachment attachment = new Attachment();
attachment.setCustomerId(tiedosto.getCustomerId());
attachment.setSize(tiedosto.getFileSize());
Integer id = attachmentService.createNew(attachment);
if (id == 1) {
UriBuilder builder = uriInfo.getAbsolutePathBuilder();
builder.path(Integer.toString(i));
response = Response.created(builder.build()).build();
System.out.println(response);
responseString = response.toString();
}
responseList.add(responseString);
i++;
}
String jsonString = new Gson().toJson(responseList);
return Response.status(Response.Status.OK).entity(jsonString).build();
}
}
when I test the individual endpoints with curl or postman, they work as expected, but I got stuck on how to execute GET and PATCH automatically after POST. I'd really appreciate some advice/suggestions/help.

Jersy REST service does not return object value from HashMap

We have created the Jersy REST service.
We are returning response object with 10 String fields and one Hash Map in format specified in below code snippet.
We could receive all the 10 string field values.
We can also see the HashMap with key/values when access it from client program.
CustomObject in HashMap became String when access it from client program.
so it throws exception
Listcom.tetherfi.restful.model.AppTypeData#2dc0f069
Test
err: java.lang.ClassCastException: java.lang.String cannot be cast to com.tetherfi.restful.model.AppTypeData.
We use Moxy to do the mapping. Please advise whether there is a way to retain the object value.
Response object from Jersy service
#XmlRootElement
public class ServiceRespParams {
private String param1;
private String param2;
private String param3;
private String param4;
private String param5;
private HashMap<String,ArrayList<AppTypeData>>hm;
public HashMap<String, ArrayList<AppTypeData>> getHm() {
return hm;
}
public void setHm(HashMap<String, ArrayList<AppTypeData>> hm) {
this.hm = hm;
}
Client code
public class Client {
public ServiceResponse postRequest(ServiceRequest request) {
Logger logger = Logger.getLogger("JerseyClient");
ServiceResponse serviceResponse = null;
WebTarget webTarget = null;
Response response = null;
// creating client with MOXy JSON
Client client = ClientBuilder.newClient();
try {
String url = "http://localhost:9080/Rest_ProxyLayer/webapi/doc01";
logger.info("Sending Request.... "+url);
webTarget = client.target(url).property(ClientProperties.CONNECT_TIMEOUT, 1000)
.property(ClientProperties.READ_TIMEOUT, 1000);
logger.info("Request Sent...");
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
response = invocationBuilder.get();
logger.info("Response Status :"+response.getStatus());
serviceResponse = response.readEntity(ServiceResponse.class);
System.out.println("Response from service"+ serviceResponse.getHm().get("CreditCard").get(0).getParam1());
} catch (Exception e) {
logger.error("Error!! Check connection..", e);
e.printStackTrace();
}
return serviceResponse;
}
}
It throws class cast exception when try to access the method.
System.out.println("Response from service"+ serviceResponse.getHm().get("CreditCard").get(0).getParam1());
Output from Rest service. Hashmap entries are below. It shows object but it seems to be converted to string.
HM: {CreditCard=[com.tetherfi.restful.model.AppTypeData#1b6c278e, com.tetherfi.restful.model.AppTypeData#208f5a00]}
Thanks
Vinoth

How to pass multiple parameters to Jersey POST method

I am trying to pass multiple parameters to Jersey POST method . Currently I am following below steps to pass a single parameter to Jersey POST method.
Client client = ClientBuilder.newClient();
WebTarget target= client.target("http://localhost:8080/Rest/rest/subuser").path("/insertSubUser");
SubUserBean subUserBean=new SubUserBean();
subUserBean.setIdUser(1);
subUserBean.setIdSubUserType(1);
subUserBean.setIdSubUser(15);
subUserBean.setFirstName("Haritha");
subUserBean.setLastName("Wijerathna");
subUserBean.setNumberOfDaysToEditRecord(14);
subUserBean.setUserName("haritha");
subUserBean.setPassword("hariwi88");
subUserBean.setDateCreated(Common.getSQLCurrentTimeStamp());
subUserBean.setLastUpdated(Common.getSQLCurrentTimeStamp());
target.request(MediaType.APPLICATION_JSON_TYPE).post(Entity.entity(subUserBean, MediaType.APPLICATION_JSON_TYPE));
SubUserJSONService.java
#Path("/subuser")
public class SubUserJSONService {
#POST
#Path("/insertSubUser")
#Consumes(MediaType.APPLICATION_JSON)
public String updateSubUser(SubUserBean bean){
SubUserInterface table = new SubUserTable();
String result= table.insertSubUser(bean);
return result;
}
}
Now, I want to pass parameters to following method via Jersey POST method.
public String insertHistory(List<SocialHistoryBean> list, String comment){
//my stuffs
}
Have any ideas to do above work ?
Thank you.
You can try using MultivaluedMap.Add form data and send it to the server. An example below, code is not tested just for demo/logic flow.
WebTarget webTarget = client.target("http://www.example.com/some/resource");
MultivaluedMap<List, String> formData = new MultivaluedHashMap<List, String>();
formData.add(List, "list1");
formData.add("key2", "value2");
Response response = webTarget.request().post(Entity.form(formData));
Consume this on server side something like
#Path("/uripath")
#POST -- if this is post or #GET
#Consumes("application/x-www-form-urlencoded;charset=UTF-8") or json..
#Produces("application/json")
public void methodNameHere(#FormParam("list") List<String> list1, #FormParam("key2") String val2) {
System.out.println("Here are I am");
System.out.println("list1" + list1.size);
System.out.println("val2" + val2);
}
Read more here in docs..
In case you're using Jersey 1.x, check this example on how to post multiple objects as #FormParam
Client: (pure Java):
public Response testPost(String param1, String param2) {
// Build the request string in this format:
// String request = "param1=1&param2=2";
String request = "param1=" + param1+ "&param2=" + param2;
WebClient client = WebClient.create(...);
return client.path(CONTROLLER_BASE_URI + "/test")
.post(request);
}
Server:
#Path("/test")
#POST
#Produces(MediaType.APPLICATION_JSON)
public void test(#FormParam("param1") String param1, #FormParam("param2") String param2) {
...
}
JSON data cannot be passed to the server in a List. This means that you should create a wrapper around your SocialHistoryBean class (i.e around the list that holds your objects)
#XmlRootElement(name = "uw")
public class SocialHistoryBeanWrapper implements Serializable {
private List<SocialHistoryBean> sList ;//this will hold your SocialHistoryBean instances
public SocialHistoryBeanWrapper(){
sList = new ArrayList<User>();
}
public List<User> getUsrList(){
return sList;
}
}
Your server side code will be like
#POST
#Path("/history")
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.APPLICATION_JSON)
public String insertHistory( #QueryParam("comment") String comment, SocialHistoryBeanWrapper uw) {
do whatever you want with your history data
//userData.setUser(uw.getUsrList().get(0));
return comment; //just echo the string that we have sent from client
}
Note that comment is passed with #QueryParam (this means it's not part of the POST request (body) but is rather encoded in the URL string. For this to work, you can call your service as (the client code)
WebTarget target = client.target(UriBuilder.fromUri("http://localhost:8088/Rest/rest/subuser").build());
SocialHistoryBeanWrapper uw = new SocialHistoryBeanWrapper();
//just populate whatever fields you have;
uw.getUsrList().get(0).setName("Mark Foster");
uw.getUsrList().get(0).setProfession("writer");
uw.getUsrList().get(0).setId(55);
String s = target.path("history").queryParam("comment", "OK").request()
.accept(MediaType.TEXT_PLAIN).post(Entity.entity(uw, MediaType.APPLICATION_JSON), String.class);
System.out.println(s);//this prints OK

How to submit multiple entities to the post method from jersey client program?

I am trying to pass multiple entities to the web service method. The web service method has two parameters of pojo entity type. I am able to post only one entity to the web service method. I am unable to post multiple entities to the web service method.
Server side code:
#POST
#Path("/test")
#Produces(MediaType.APPLICATION_XML)
#Consumes(MediaType.APPLICATION_XML)
public void testMethod(Emp emp, Student stud){
...
}
Client side code:
...
...
Emp emp = new Emp;
Student stud = new Student();
ClientResponse response = resource.type(MediaType.APPLICATION_XML).entity(emp).entity(stud).post(ClientResponse.class);
A request can only have one entity body, that's why the restriction. The only option I can think of is to use multipart request, where you can have multiple body parts.
Example server side
#Path("multipart")
public class MultipartResource {
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response doPost(#FormDataParam("emp") Emp emp,
#FormDataParam("student") Student student) {
StringBuilder builder = new StringBuilder();
builder.append("Emp:").append(emp.name).append("\n");
builder.append("Student:").append(student.name).append("\n");
return Response.ok(builder.toString()).build();
}
public static class Student {
public String name;
}
public static class Emp {
public String name;
}
}
Client side
public class Main {
public static void main(String[] args) throws Exception {
Client client = Client.create();
Emp emp = new Emp();
emp.name = "pee";
Student stu = new Student();
stu.name = "skillet";
FormDataMultiPart multipart = new FormDataMultiPart()
.field("emp", emp, MediaType.APPLICATION_JSON_TYPE)
.field("student", stu, MediaType.APPLICATION_JSON_TYPE);
final String url = "http://localhost:8080/api/multipart";
String response = client.resource(url).type(MediaType.MULTIPART_FORM_DATA_TYPE)
.post(String.class, multipart);
System.out.println(response);
}
}
Result:
Emp:pee
Student:skillet
Jersey dependency for multipart support.
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-multipart</artifactId>
<version>${jersey1.version}</version>
</dependency>

Passing JSONObject in RestFul Webservice

I am using RestFul Webservice with JBoss Server to deploy the app to receive the JSONObject to my web service ,to test that i have created the web service and written test cases for it .Now i got hung up in passing the JSONobject from test case to web services , when i pass the json object to #post service calls it responses that Null Pointer Exception , even i have tried with passing string to it it responds null values.
I have used Annotations as follows in webservice
#consumes({Mediatype.APPLICATION_JSON})
#Consumes("application/json")
Test case As:
#Test
public void testgetmsg() {
String msg = "{\"patient\":[{\"id\":\"6\",\"title\":\"Test\"}]}";
try {
JSONObject obj = new JSONObject(new JSONTokener(msg));
WebResource resource = client.resource( "https://localhost:8443/../../resources/create");
ClientResponse response = resource.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).
entity(obj).post(ClientResponse.class,JSONObject.class);
}
}
can any body guide me to proceed further ?
Thanks in Advance
You don't need to create the json object, you can just pass the string.
you should
ClientResponse response = resource.type(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.post(ClientResponse.class, msg);
//CLIENT
public static void createStudent() {
String input = "{\"id\":12,\"firstName\":\"Fade To Black\",\"lastName\":\"Joy\"}";
ClientResponse response = service.path("class/post")
.type("application/json").post(ClientResponse.class, input);
System.out.println("Output from Server .... \n");
String output = response.getEntity(String.class);
System.out.println(output);
System.out.println(response.getStatus()+ "OK");
}
Instead of using code client you can use add on firefox (POSTER) to passing value as json or formparam...
// create new student SERVER
//class
#POST
#Path("post")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response createStudent(Student st) {
// add new student
StudentDAO.instance.getModelStudent().put("8", st);
// response status code
return Response.status(200).entity(st).build();
}

Categories