Today I'm dealing with an issue creating a client to consume a restful service with a Bearer JWT. After appying the swagger codegen maven plugin I got the following GET operation what I need to consume in my new service:
public String getRelationByCucoIdUsingGET(Integer cucoId, String GS_AUTH_TOKEN) throws RestClientException {
Object postBody = null;
// verify the required parameter 'cucoId' is set
if (cucoId == null) {
throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'cucoId' when calling getRelationByCucoIdUsingGET");
}
// create path and map variables
final Map<String, Object> uriVariables = new HashMap<String, Object>();
uriVariables.put("cucoId", cucoId);
String path = UriComponentsBuilder.fromPath("/getRelationByCucoId/{cucoId}").buildAndExpand(uriVariables).toUriString();
final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
final HttpHeaders headerParams = new HttpHeaders();
final MultiValueMap<String, Object> formParams = new LinkedMultiValueMap<String, Object>();
if (GS_AUTH_TOKEN != null)
headerParams.add("GS-AUTH-TOKEN", apiClient.parameterToString(GS_AUTH_TOKEN));
final String[] accepts = {
"application/json"
};
final List<MediaType> accept = apiClient.selectHeaderAccept(accepts);
final String[] contentTypes = { };
final MediaType contentType = apiClient.selectHeaderContentType(contentTypes);
String[] authNames = new String[] { };
ParameterizedTypeReference<String> returnType = new ParameterizedTypeReference<String>() {};
return apiClient.invokeAPI(path, HttpMethod.GET, queryParams, postBody, headerParams, formParams, accept, contentType, authNames, returnType);
}
The model class is as follow:
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
public class CuCoPerson {
private Integer cucoId;
private List<CustomerRelation> customers;
}
And last, I have done this service but it doesnt work and I don't know how to create the controller to use this service.
#Service
public class CustomerRelationService {
RestControllerApi restControllerApi = new RestControllerApi();
public void getCustomers(Integer cudoId, Principal auth) {
restControllerApi.getRelationByCucoIdUsingGET(cudoId, auth.getName());
}
Related
We have a put api that will update an assignment based on its id. As we should be cleaning up the data after a test, our assignment id would change after the original one is deleted, so we're trying to dynamically inject that into the body for the request from the provider side. However, we seem to be perhaps missing something here as it's not updating correctly and the request is still being triggered with the id set as the example.
This is the provider class:
#Slf4j
#Provider("Assignments API")
#Consumer("LTI-AGS-Tool")
//#PactBroker(url = BROKER_PACT_URL, authentication = #PactBrokerAuth(token = "${pactbroker.auth.token}"))
#VerificationReports(value = {"console", "markdown"}, reportDir = "target/pacts")
class PactProviderLTIAGSIT {
private HashMap<String, String> headers = new HashMap<>();
private String updateAssignmentId;
private final String SERVICE_TOKEN = "myToken";
#BeforeEach
void createTeacherAssignment() {
String assignmentBody = createBodyStringForStudentAssignmentSetup();
assignmentBody = assignmentBody.replace("CPWAG", "OTHER_TEXT_RESOURCE");
headers.put("Content-Type", "application/json");
headers.put("Authorization", "myToken");
RequestSpecification rq = Util.getRequestSpecification().baseUri(baseAssignmentUrl).headers(headers);
Response response = rq.body(assignmentBody).post();
assertEquals(201, response.getStatusCode());
updateAssignmentId = response.jsonPath().get("assignments[0].refId");
log.info("assignment id is " + updateAssignmentId);
}
#TestTemplate
#ExtendWith(PactVerificationInvocationContextProvider.class)
void pactTestTemplate(PactVerificationContext context, HttpRequest request) {
request.addHeader("Authorization", SERVICE_TOKEN);
logCurlFromPact(context, request);
context.verifyInteraction();
}
#BeforeEach
void before(PactVerificationContext context) {
context.setTarget(new HttpsTestTarget(BASE_PACT_TEACHER_ASSIGNMENTS_URL, 443, ""));
}
#State("Scoring info is passed between ags-tool and assignmentapi")
Map<String, Object> getScoringInfo() {
Map<String, Object> map = new HashMap<>();
map.put("assignmentId", updateAssignmentId);
return map;
}
}
And here the consumer contract:
#ExtendWith(PactConsumerTestExt.class)
class PactConsumerSendScoreIT {
private final Map<String, String> headers = new HashMap<>();
private final String path = "/v5/assignmentStatus/update";
#Pact(provider = PACT_PROVIDER, consumer = PACT_CONSUMER)
public RequestResponsePact scoreConsumerPact(PactDslWithProvider builder) {
headers.put("Content-Type", "application/json");
//Body given and returned
DslPart body = new PactDslJsonBody()
.valueFromProviderState("assignmentId", "assignmentId", "c1ef3bbf-55a2-4638-8f93-22b2916fe085")
.stringType("timestamp", DateTime.now().plusHours(3).toString())
.decimalType("scoreGiven", 75.00)
.decimalType("scoreMaximum", 100.00)
.stringType("comment", "Good work!")
.stringType("status", "IN_PROGRESS")
.stringType("userId", "c2ef3bbf-55a2-4638-8f93-22b2916fe085")
.close();
return builder
.given("Scoring info is passed between ags-tool and assignmentapi")
.uponReceiving("Scoring info is passed between ags-tool and assignmentapi")
.path(path)
.method("POST")
.body(body)
.headers(headers)
.willRespondWith()
.status(201)
.body(body)
.toPact();
}
#Test
#PactTestFor(pactMethod = "scoreConsumerPact", providerName = PACT_PROVIDER, port = "8080", pactVersion = PactSpecVersion.V3)
void runTest(MockServer mockServer) {
String updateAssignmentId = "c2ef3bbf-55a2-4638-8f93-22b2916fe085";
HashMap<String, Object> map = new HashMap<>();
map.put("timestamp", DateTime.now().plusHours(3).toString());
map.put("scoreGiven", 75.00);
map.put("scoreMaximum", 100.00);
map.put("comment", "Good work!");
map.put("status", "IN_PROGRESS");
map.put("userId", "c2ef3bbf-55a2-4638-8f93-22b2916fe085");
map.put("assignmentId", updateAssignmentId);
//Mock url
RequestSpecification rq = Util.getRequestSpecification().baseUri(mockServer.getUrl()).headers(headers);
Response response = rq.body(map)
.post(path);
assertEquals(201, response.getStatusCode());
}
}
Thank you.
We figured out that the expression needed is to include the ${} (at least if it's a string).
Once we updated it to valueFromProviderState("assignmentId", "${assignmentId}", "c1ef3bbf-55a2-4638-8f93-22b2916fe085") it seemed to work.
Thank you for clicking here.
I have an JSON REST API (providing by Directus CMS). All API responses contains a json object with a "data" attribute containing what I want.
{
"data": {
"id": 1,
"status": "published",
"sort": null,
"user_created": "5a91c184-908d-465e-a7d5-4b648029bbe0",
"date_created": "2022-04-26T09:43:37.000Z",
"user_updated": "5a91c184-908d-465e-a7d5-4b648029bbe0",
"date_updated": "2022-05-30T14:23:50.000Z",
"Titre": "Réseaux Sociaux",
"Description": "Retrouvez les dernières news en direct sur nos réseaux sociaux!",
"Lien": "https://www.instagram.com/univlorraine/",
"ImageArrierePlan": "f23ffd53-7244-4439-a8cf-41bd0fd3aa72",
"Erreur_Bloc": null
}
}
This data attribute can be a object or a list of objects depending the request.
I have a Java Spring application with a service consuming the API. I'm using RestTemplate with exchange method.
public Object callAPI(String url, HttpMethod httpMethod, Object body, MultiValueMap<String, String> headers, Class<?> classe) {
final RestTemplate rt = new RestTemplate();
try {
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
rt.setRequestFactory(requestFactory);
final HttpEntity<?> request = new HttpEntity<>(body, headers);
final ResponseEntity<?> response = rt.exchange(url, httpMethod, request, classe);
if (response.getStatusCode().equals(HttpStatus.OK)) {
return response.getBody();
}
else return response.getStatusCode();
} catch (final Exception e) {
System.out.println(e);
return null;
}
}
In the exchange method I pass an existing class to directly link response data with the provided class.
The probleme is that I have this data attribute which prevents me from linking the data.
Does anyone have a solution to this probleme please?
----UPDATE----
Thanks to the response of AlbiKai, I created a generic Wrapper class :
public class Wrapper<T> {
private T data;
public void set(T data) {
this.data = data;
}
public T get() {
return data;
}
}
I then tried to put this Wrapper in the exchange :
public <classe> Object callAPI(String url, HttpMethod httpMethod, Object body, MultiValueMap<String, String> headers, Class<?> classe) {
final RestTemplate rt = new RestTemplate();
try {
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
rt.setRequestFactory(requestFactory);
final HttpEntity<?> request = new HttpEntity<>(body, headers);
final ResponseEntity<?> response = rt.exchange(url, httpMethod, request, Wrapper<classe>.class);
But I get the error "Cannot select from parameterized type" on the Wrapper :/
You can create a wrapper class that match the json response : an object with only one attribute named "data" type of desire final class (or a list) and use it in the exchange method.
public class wrapper {
YourClass data;
}
I gave up with the Wrapper etc...
I just pass a String class and work with it in my controllers to delete this "data" property and map the string with a class.
Service :
public String callAPI(String url, HttpMethod httpMethod, Object body, MultiValueMap<String, String> headers) {
final RestTemplate rt = new RestTemplate();
try {
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
rt.setRequestFactory(requestFactory);
final HttpEntity<?> request = new HttpEntity<>(body, headers);
final ResponseEntity<String> response = rt.exchange(url, httpMethod, request, String.class);
if (response.getStatusCode().equals(HttpStatus.OK)) {
return response.getBody();
}
else return response.getStatusCode().toString();
} catch (final Exception e) {
System.out.println(e);
return null;
}
}
One controller :
public List<BlocInformation> getBlocInformation() {
String url = "http://localhost:8055/items/bloc_information/?fields=*,Erreur_Bloc.*";
final RestAPIService blocService = new RestAPIService();
String response = blocService.callAPI(url, HttpMethod.GET, null, null);
if (response != null) {
String result = response.substring(8, response.length() - 1);
ObjectMapper mapper = new ObjectMapper();
List<BlocInformation> blocInformationList = null;
try {
blocInformationList = Arrays.asList(mapper.readValue(result, BlocInformation[].class));
} catch (IOException e) {
e.printStackTrace();
}
return blocInformationList;
}
return null;
}
I have an entity class like below:
public class InputData {
byte[] nameBytes;
InputType inputType;
InputType outputType;
String inputName;
Description desc;
}
Here is my rest controller:
#PostMapping(path = "/submitData", consumes = "application/json")
public HttpStatus callDataService(#RequestBody Map<String, String> json) {
Gson gson = new GsonBuilder().create();
InputData inputData = gson.fromJson(json.get("inputData"), InputData.class);
Report report = dataService.getReport(inputData);
//return HttpStatus.OK;
}
I have two questions:
How can I send the report as well as Http Status back as a response?
How to send the data to controller?
I have created the following test case:
#Test
public void testController() throws JSONException {
Gson gson = new Gson();
Description desc = new Description();
desc.setMinimumValidSize(512);
File file = new File("src/test/resources/sampleDocuments/test_1.pdf");
byte[] byteArray = { 'P', 'A', 'N', 'K', 'A', 'J' };
JSONObject inputSample = new JSONObject();
inputSample.put("nameBytes", byteArray);
inputSample.put("inputType", ImageType.PDF);
inputSample.put("outputType", ImageType.TIFF);
inputSample.put("inputName", "ABCDEF");
inputSample.put("desc", desc);
String result = invokeRest(fileInputSample.toString(),"/submitData", HttpMethod.POST);
assertEquals("200", result);
}
private String invokeRest(String basicParams, String inputImageType, String
outputImageType, String options, String url, HttpMethod httpMethod) {
String testUrl = "http://localhost:" + port + url;
Map<String, Object> body = new HashMap<>();
body.put("fileInput", basicParams);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity(body, headers);
String result = "";
ResponseEntity<String> response = restTemplate.exchange(testUrl, httpMethod, entity, String.class);
if (response.getStatusCode() == HttpStatus.OK) {
result = response.getBody();
} else {
result = response.getStatusCode().toString();
}
return result;
}
When I run this the test case failed and I was able to pin point the issue :
Expected BEGIN_OBJECT but was STRING at line 1 column 13 path $.desc
So I am guessing I am not sending this values in right way
For Description POJO is below:
public class Description {
private static final int DPI = 300;
private Ctype c = CType.NONE;
private ColorType color = DEFAULT_COLOR;
private int dpi = DPI;
}
public enum CType {
NONE, GROUPA,GROUPB,GROUPB_B,GROUPD
}
public enum ColorType {
RGB, GREY;
}
Here is the values that is being send:
{"desc":"org.restservice.Description#1213ffbc”,
"outputType":"TIFF","inputType":"PDF","nameBytes":"src/test/resources/sampleDocuments/test_16.pdf","inputName":"98111"}
How can I send that as Object if I am sending a Map of <String, String> in body? Is there any other way to send that object to controller?
To return the status and also the object you can try to do it like this:
#PostMapping(path = "/submitData", consumes = "application/json")
public ResponseEntity<Report> callDataService(#RequestBody Map<String, String> json) {
Gson gson = new GsonBuilder().create();
InputData inputData = gson.fromJson(json.get("inputData"), InputData.class);
Report report = dataService.getReport(inputData);
return ResponseEntity.ok(report);
}
How to instantiate a referenced object in Spring Boot by means of annotations?
public class Sign {
private static final List<String> KEYS = new ArrayList<>();
static {
KEYS.add(HeaderKey.XCaAppkey);
KEYS.add(HeaderKey.XCaEncryption);
KEYS.add(HeaderKey.XCaNonce);
KEYS.add(HeaderKey.XCaTimestamp);
KEYS.add(HeaderKey.XServiceId);
KEYS.add(HeaderKey.XServiceMethod);
KEYS.add(HeaderKey.XCaSignature);
}
private HttpEntity<String> httpEntity;
public Sign(HttpEntity<String> httpEntity) {
this.httpEntity = httpEntity;
}
public String encode() {
List<String> parts = new ArrayList<>();
parts.add("requestBody=" + httpEntity.getBody());
KEYS.stream().forEach(key -> {
parts.add(key + "="+httpEntity.getHeaders().getFirst(key));
});
String value = StringUtils.join(parts, "&");
return DigestUtils.md5Hex(value);
}
}
public class ApiClient {
/*
*
* */
#Autowired
private Sign sign;
HttpHeaders headers = new HttpHeaders();
HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);
//Sign sign=new Sign(entity); how to choose new object and automatic import
String caSignature=sign.encode();
Put #Service or #Component annotation on Sign class.
I am developing a front end application using Java Spring-MVC, however I'm facing difficulties in creating Request Object for Hitting Web-Services as I did in .Net-MVC. Can anyone tell me the equivalent classes and methods in Java for below given code.
I need to replicate these 2 methods from .Net-MVC to Java.
1st Method:
private HttpWebRequest RequestObj { get; set; }
public Stream DataStreamObj { get; set; }
private RequestModel RequestModelObj { get; set;
public RequestGenerator(String WebserviceUrl)
{
RequestObj = (HttpWebRequest)WebRequest.Create(WebConfigurationManager.AppSettings["WebServiceURL"] + WebserviceUrl);
RequestObj.Method = "POST";GenerateLoginRequest
RequestObj.ContentType = "application/json";
RequestModelObj = new RequestModel();
RequestModelObj.ApiKey = WebConfigurationManager.AppSettings["apiKey"];
RequestModelObj.DeviceId = Constant.AppConstants.ONE;
}
2nd Method:
private string CallWebservice(Dictionary<String, Object> RequestDict)
{
try
{
HttpWebRequest Request = (HttpWebRequest)RequestDict["request"];
RequestModel RequestModel = (RequestModel)RequestDict["requestData"];
//Tell them the length of content
string Json = JsonConvert.SerializeObject(RequestModel);
byte[] ByteArray = Encoding.UTF8.GetBytes(Json);
Request.ContentLength = ByteArray.Length;
//Write content on stream
Stream DataStream = Request.GetRequestStream();
DataStream.Write(ByteArray, 0, ByteArray.Length);
DataStream.Close();
//Initiate Call
HttpWebResponse Response = GetWebResponse(Request);
DataStream = Response.GetResponseStream();
StreamReader Reader = new StreamReader(DataStream);
// Read the content.
string responseFromServer = Reader.ReadToEnd();
// Display the content.
Reader.Close();
Response.Close();
return responseFromServer;
}
catch (System.Net.WebException ex)
{
var response = ex.Response as HttpWebResponse;
return "";
}
}
RestTemplate class is designed to call REST services, it should come as no surprise that its main methods are closely tied to REST’s underpinnings, which are the HTTP protocol’s methods: HEAD, GET, POST, PUT, DELETE, and OPTIONS. E.g. it’s methods are headForHeaders(), getForObject(), postForObject(), put() and delete() etc.
Read More and Source Code : Spring REST JSON Example
HTTP GET Method Example
1) Get XML representation of employees collection in String format
REST API Code
#RequestMapping(value = "/employees", produces =
MediaType.APPLICATION_XML_VALUE, method = RequestMethod.GET)
public String getAllEmployeesXML(Model model)
{
model.addAttribute("employees", getEmployeesCollection());
return "xmlTemplate";
}
REST Client Code
private static void getEmployees()
{
final String uri =
"http://localhost:8080/springrestexample/employees.xml";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri, String.class);
System.out.println(result);
}
2) Get JSON representation of employees collection in String format
REST API Code
#RequestMapping(value = "/employees", produces =
MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
public String getAllEmployeesJSON(Model model)
{
model.addAttribute("employees", getEmployeesCollection());
return "jsonTemplate";
}
REST Client Code
private static void getEmployees()
{
final String uri =
"http://localhost:8080/springrestexample/employees.json";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri, String.class);
System.out.println(result);
}
3) Using custom HTTP Headers with RestTemplate
REST API Code
#RequestMapping(value = "/employees", produces =
MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
public String getAllEmployeesJSON(Model model)
{
model.addAttribute("employees", getEmployeesCollection());
return "jsonTemplate";
}
REST Client Code
private static void getEmployees()
{
final String uri = "http://localhost:8080/springrestexample/employees";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>("parameters",
headers);
ResponseEntity<String> result = restTemplate.exchange(uri,
HttpMethod.GET, entity, String.class);
System.out.println(result);
}
4) Get data as mapped object
REST API Code
#RequestMapping(value = "/employees", produces =
MediaType.APPLICATION_XML_VALUE, method = RequestMethod.GET)
public String getAllEmployeesXML(Model model)
{
model.addAttribute("employees", getEmployeesCollection());
return "xmlTemplate";
}
REST Client Code
private static void getEmployees()
{
final String uri = "http://localhost:8080/springrestexample/employees";
RestTemplate restTemplate = new RestTemplate();
EmployeeListVO result = restTemplate.getForObject(uri,
EmployeeListVO.class);
System.out.println(result);
}
5) Passing parameters in URL
REST API Code
#RequestMapping(value = "/employees/{id}")
public ResponseEntity<EmployeeVO> getEmployeeById (#PathVariable("id")
int id)
{
if (id <= 3) {
EmployeeVO employee = new
EmployeeVO(1,"Lokesh","Gupta","howtodoinjava#gmail.com");
return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK);
}
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
REST Client Code
private static void getEmployeeById()
{
final String uri =
"http://localhost:8080/springrestexample/employees/{id}";
Map<String, String> params = new HashMap<String, String>();
params.put("id", "1");
RestTemplate restTemplate = new RestTemplate();
EmployeeVO result = restTemplate.getForObject(uri, EmployeeVO.class,
params);
System.out.println(result);
}
HTTP POST Method Example
REST API Code
#RequestMapping(value = "/employees", method = RequestMethod.POST)
public ResponseEntity<String> createEmployee(#RequestBody EmployeeVO
employee)
{
System.out.println(employee);
return new ResponseEntity(HttpStatus.CREATED);
}
REST Client Code
private static void createEmployee()
{
final String uri = "http://localhost:8080/springrestexample/employees";
EmployeeVO newEmployee = new EmployeeVO(-1, "Adam", "Gilly",
"test#email.com");
RestTemplate restTemplate = new RestTemplate();
EmployeeVO result = restTemplate.postForObject( uri, newEmployee,
EmployeeVO.class);
System.out.println(result);
}
HTTP PUT Method Example
REST API Code
#RequestMapping(value = "/employees/{id}", method = RequestMethod.PUT)
public ResponseEntity<EmployeeVO> updateEmployee(#PathVariable("id")
int id, #RequestBody EmployeeVO employee)
{
System.out.println(id);
System.out.println(employee);
return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK);
}
REST Client Code
private static void deleteEmployee()
{
final String uri =
"http://localhost:8080/springrestexample/employees/{id}";
Map<String, String> params = new HashMap<String, String>();
params.put("id", "2");
EmployeeVO updatedEmployee = new EmployeeVO(2, "New Name", "Gilly",
"test#email.com");
RestTemplate restTemplate = new RestTemplate();
restTemplate.put ( uri, updatedEmployee, params);
}
HTTP DELETE Method Example
REST API Code
#RequestMapping(value = "/employees/{id}", method =
RequestMethod.DELETE)
public ResponseEntity<String> updateEmployee(#PathVariable("id") int
id)
{
System.out.println(id);
return new ResponseEntity(HttpStatus.OK);
}
REST Client Code
private static void deleteEmployee()
{
final String uri =
"http://localhost:8080/springrestexample/employees/{id}";
Map<String, String> params = new HashMap<String, String>();
params.put("id", "2");
RestTemplate restTemplate = new RestTemplate();
restTemplate.delete ( uri, params );
}