No response back from REST WS called by jQuery/JSON - java

I know there is a lot of these posts but I couldn't really get this to work since I am new to both REST and JQuery:
I am using REST-WS with Java 5 and I am able to call it and get result back with "Poster" ,the firefox plugin to test it. When I call the URL below I should get the employee in order '0' in the map by calling the method "getCustomer" in the resource class shown below.
Although I am not able to get the result and getting an error "unknown "using jQuery and returning JSON when I call the REST from an html page with body as below:
<body>
jQuery to REST <br><br>
jQuery
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function (){
$.ajax({
type: "GET",
url: "http://localhost:8081/RestDemo/services/customers/0",
dataType: "json",
success: function (data) {
alert(data.name);
},
error: function(e){
alert("Error: " + e);
}
});
});
});
</script>
<br>
<br>
<button>Return Customer</button>
</body>
This is my Resource class:
package com.myeclipseide.ws;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
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.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.sun.jersey.spi.resource.Singleton;
#Produces("application/xml")
#Path("customers")
#Singleton
#XmlRootElement(name = "customers")
public class CustomerResource {
private TreeMap<Integer, Customer> customerMap = new TreeMap<Integer, Customer>();
public CustomerResource() {
// hardcode a single customer into the database for demonstration
// purposes
Customer customer = new Customer();
customer.setName("Harold Abernathy");
customer.setAddress("Sheffield, UK");
addCustomer(customer);
}
#GET
#XmlElement(name = "customer")
public List<Customer> getCustomers() {
List<Customer> customers = new ArrayList<Customer>();
customers.addAll(customerMap.values());
return customers;
}
#GET
#Path("/{id}")
#Produces("application/json")
public String getCustomer(#PathParam("id") int cId) {
return "{\"name\": \"unknown\", \"address\": -1}"; //customerMap.get(cId);
}
#POST
#Path("add")
#Produces("text/html")
#Consumes("application/xml")
public String addCustomer(Customer customer) {
int id = customerMap.size();
customer.setId(id);
customerMap.put(id, customer);
return "Customer " + customer.getName() + " added with Id " + id;
}
}
I appreciate anyone's help,
Thanks!

I got it!
Returning {"name": "unknown", "address": -1} is right because that's exactly what is hard coded in my method return,
so i replaced return "{\"name\": \"unknown\", \"address\": -1}";
simply with a correct form which is
return "{\"name\": \" " + customer.getName() + " \", \"address\": \"" + customer.getAddress() + "\"}";
and obviously it works!
Thanks everyone.

I appreciate anyone's help,
If you are stumped, take a look at what is in the web countainer's log files. If necessary, turn on debug logging.
The next thing would be to use your web browser's built-in "web developer" support to see what request is actually being sent.

Related

I want to take value from one API response body and use into another api request using Cucumber gherkin

Scenario: Verify the manifest of published app
1. Given Base url "baseUrl" and path "basepath"
2. And Headers are
3. And Query parameter
4. And App with below details
5. When I execute the another API with Base url "baseUrl" and path "basePath"
6. And Append with Attributevalue (complete url will be , baseUrl + basePath + AttributeValue )
7. And api headers
8. And query parameters
9. Then Success message with 200 status code
I have implemented something very similar recently. You can utilize below code and modify it to your need. You'll probably need to omit some steps from your feature . Those steps are included as part of step def implementation in below code
Feature
#get
Scenario: get employee
Given an employee exist in the database with id "2"
When user retrieves employee info by id
Then the status code for get employee is 200
StepDefs
import io.cucumber.java.en.Given;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.And;
import io.restassured.RestAssured;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import static org.junit.jupiter.api.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
public class secondIT {
public static Response response;
public static ValidatableResponse json;
public static RequestSpecification request;
public static String id;
public static JsonPath jsonPathEvaluator;
#Given("an employee exist in the database with id {string}")
public void an_employee_exists_with_id(String ID){
secondIT.id=ID;
RestAssured.baseURI = "http://dummy.www.com/api/v1";
secondIT.request = RestAssured.given();
}
#When("user retrieves employee info by id")
public void user_retrieves_employee_info_by_id(){
secondIT.response = secondIT.request.pathParam("id", secondIT.id).get("/employee/{id}");
secondIT.jsonPathEvaluator = secondIT.response.jsonPath();
assertNotNull(response);
}
#Then("the status code for get employee is {int}")
public void verify_status(int sc){
System.out.println("status code check.. " );
secondIT.json = secondIT.response.then().statusCode(sc);
System.out.println("status code: " + secondIT.response.getStatusCode());
assertEquals(sc,secondIT.response.getStatusCode());
}
}

Spring boot response filter for restructuring controller response before sending to client

I have a couple of spring boot rest controllers, and I want a standard JSON response structure to be sent to the client.
The standard response will be composed of responseTime, apiResponseCode, status, apiName, response ( which will vary based on the api). See below:
{
"responseTime": "2020-04-19T08:36:53.001",
"responseStatus": "SUCCESS",
"apiResponseCode": "SUCCESS",
"apiName": "PROPERTY_STORE_GET_PROPERTIES",
"response": [
{
"propertyName": "app.name",
"propertyValue": "property-store"
}
]
}
To achieve this, I have created below model class:
package com.example.response.model;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.example.constants.ApiResponseCode;
import com.example.constants.Status;
public class ApplicationResponse<T> implements Serializable {
private static final long serialVersionUID = -1715864978199998776L;
LocalDateTime responseTime;
Status responseStatus;
ApiResponseCode apiResponseCode;
String apiName;
T response;
public ApplicationResponse(LocalDateTime responseTime, Status status,
ApiResponseCode apiRespCode, String apiName, T response) {
this.responseTime = responseTime;
this.responseStatus = status;
this.apiResponseCode = apiRespCode;
this.apiName = apiName;
this.response = response;
}
// getters and setters
To create a generic response wrapper, I have created below response util class.
import java.time.LocalDateTime;
import com.example.constants.ApiResponseCode;
import com.example.constants.Status;
import com.example.response.model.ApplicationResponse;
public class ResponseUtil {
public static <T> ApplicationResponse<T> createApplicationResponse(String
apiName, T response) {
return new ApplicationResponse<>(LocalDateTime.now(),
Status.SUCCESS, ApiResponseCode.SUCCESS, apiName,
response);
}
private ResponseUtil() {
}
}
Now the ask is that my response from controller should get serialized in the standard way. Shown below is my controller method.
package com.example.propertystore.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RestController;
import com.example.constants.ApiResponseCode;
import com.example.constants.Status;
import com.example.exception.ApplicationException;
import com.example.exception.ApplicationExceptionHelper;
import com.example.propertystore.constants.PropertyStoreApiName;
import com.example.propertystore.dto.PropertyDTO;
import com.example.propertystore.entity.Property;
import com.example.propertystore.service.PropertyStoreService;
import com.example.response.ResponseUtil;
import com.example.response.model.ApplicationResponse;
#RestController
public class PropertyStoreControllerImpl implements PropertyStoreController {
#Autowired
PropertyStoreService propertyStoreService;
#Autowired
ApplicationExceptionHelper exceptionHelper;
#Override
public ApplicationResponse<List<PropertyDTO>> getProperties() throws ApplicationException {
ApplicationResponse<List<PropertyDTO>> response = null;
try {
response = ResponseUtil.createApplicationResponse(
PropertyStoreApiName.PROPERTY_STORE_GET_PROPERTIES.toString(),
propertyStoreService.getProperties());
} catch (Exception e) {
exceptionHelper.raiseApplicationException( HttpStatus.INTERNAL_SERVER_ERROR, Status.FAILURE,
ApiResponseCode.INTERNAL_SERVER_ERROR,
PropertyStoreApiName.PROPERTY_STORE_GET_PROPERTIES.toString(), null);
}
return response;
}}
With the current implementation what I'll have to do is that in my controllers I will have to transform the response by calling ResponseUtil.createApplicationResponse(). This is going to litter the entire controller methods with the createApplicationResponse() method call.
What I wanted to explore is that if there is any cleaner way of achieving this using servlet filters or AOP?
PS: I tried filter option, but couldn't understand how to proceed around it. Got stuck after retrieving the response.getOutputStream() in doFilter().
Hope someone can help?
Just wrap all your responses into a decorator object.
class ResponseDecorator<T> {
//global.fields (time,code, status.....)
T response;
}
Then wrap this response wrapper into the ResponseEntity
The response.getOutputStream that you used and filters are servlet related classes , and i think you can do that without them.Just make your custom response class and add fields however you want your response. Than in the controller , just return new ResponseEntity(HttpStatus.OK,"your message "):
I don't know if this is the behavior you want.

Play framework error: not found: value message

I have a route, controller and view defined. When I do a get request for the home directory, which is "/", I am getting the error not found: value message. index.scala.html:2.
routes:
GET / controllers.HomeController.index(message: String, name: String)
GET /count controllers.CountController.count
GET /message controllers.AsyncController.message
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
index.scala.html:
#(name: String)
#(message: String)
#main("Welcome to Sparta") {
#welcome(message, style = "java")
}
HomeController.java:
package controllers;
import play.mvc.*;
import play.*;
import views.html.*;
import java.util.Date;
public class HomeController extends Controller {
public String name;
public String message;
public Result index(String name, String message) {
name = "TEST NAME";
message = "Test message";
return ok(name, "message: " + message);
}
}
Why is the error telling me I have not defined a value for message?
Your route and index method in the controller is not correct. If you are sending any parameters to the server, they come into the picture. Your URL does look like you are sending some parameter with it, so please remove parameters for the index method.
public Result index() {
name = "TEST NAME";
message = "Test message";
return ok(name, "message: " + message);
}

Why Swagger created a systemId field in example?

I have a REST POST function that has the following header:
#POST
#Consumes(value = { MediaType.APPLICATION_JSON + ";charset=utf-8" })
#Produces(value = { MediaType.APPLICATION_JSON + ";charset=utf-8" })
#ApiOperation(value = "Create a document type", notes = "creates a document type from Json and returns the created type", response = Response.class)
#Session(roles = { Role.ROLE_ADMINISTRATOR })
#PublicApi
public Response create(
#ApiParam(value = "Created DocumentType", required = true)
#SwaggerDataType(type =
com.infor.daf.icp.internal.rest.models.DocumentType.class)
com.infor.daf.icp.internal.rest.models.DocumentType documentType) {
When I look at it in Swagger UI, the Swagger creates an example request body. That body has
systemId (string, optional),
in Model view and
systemId : "string"
in the JSON view. But in the whole project there is not a field named systemId. I had checked the request class and its ancestors one by one, and the whole project by search Java. That symbol sequence systemId does not appear even as a substring of another name.
Where does Swagger gets that name and how can I stop it? For I want it to create a valid example, of course.
Edit: The API function itself takes JSON input without problems and correctly composes an object of the declared class.
Imports :
package com....documentarchive.rest.v1
import javax.servlet.http.HttpServletRequest;
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.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
The swagger UI looks so:
Edit 2.
I have removed #SwaggerDataType, or replaced it with #RequestBody, but the strange behaviour remains.
I have set the example to be shown as a concrete string with real data:
#ApiParam(example = DOC_TYPE_EXAMPLE, value = "Created DocumentType", required = true) #RequestBody com.infor.daf.icp.internal.rest.models.DocumentType documentType) {
....
static final private String DOC_TYPE_EXAMPLE = "{'entityModel':\n" +
" {'name':'Anatemplate',\n" +
" 'desc':'Ana-template',\n" +
And even that didn't help! Swagger still generates some senseless string from some distant file (thanks to #xpa1492 for the reference) somewhere on the internet, instead of simply showing out the prepared string.
More edit:
The pom file: https://drive.google.com/file/d/16fOCq5EFZYVBJRPg0HeiP102eRzEaH6W/view?usp=sharing
Seems to have been answered here: https://github.com/kongchen/swagger-maven-plugin/issues/608
Swagger configuration was not loading the Jackson annotation module, ignoring all annotations used. Therefore ApiReader was reading wrong class (https://docs.oracle.com/javase/8/docs/api/org/w3c/dom/DocumentType.html).

Rest Web service parameter issue

am using below code to test a basic web service. When am passing normal string it works fine for example - http://localhost.com:8080/CheckRest/rest/pmg?p1=xyz. It displays HELLO xyz
But when I add '#' to the URL it doesnt give the right output for example - http://localhost.com:8080/CheckRest/rest/pmg?p1=xyz#abc. It then displays HELLO xyz instead of HELLO xyz#abc
package com.check.ws;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
#Path("/pmg")
public class CheckCall {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayPlainTextHello() {
return " ";
}
// This method is called if XML is request
#GET
#Produces(MediaType.TEXT_XML)
public String sayXMLHello() {
return "<?xml version=\"1.0\"?>" + "<pmg> </pmg>";
}
// This method is called if HTML is request
#GET
#Produces(MediaType.TEXT_HTML)
public String sayHtmlHello(#QueryParam("p1") String par1) {
return "<html> <body> HELLO </body> </html>"+par1;
}
}
The pound/hash sign (#) indicates the beginning of the URL fragment identifier. If you want to use a pound/hash sign in your query string, you need to URL encode it by replacing it with %23:
http://localhost.com:8080/CheckRest/rest/pmg?p1=xyz%23abc

Categories