In Jersey, how to return an object with 400 response code different than the 200 response object - rest

I am new to Jersey and to REST in general, so this might be a stupid question....
In my code, I send a request (TemplateValidationRequest) to try to validate an object. If the object fails to validate, I want to return a String. How do I do this?
In the second code snippet at the bottom, you can see that I'm looking for TemplateValidationResponse object. How can I change my code so that:
I can return a string, and
I can get a String instead of a TemplateValidationResponse object.
Is this possible?
#POST
#Path("validate/modelTemplate")
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
#Operation(
summary = "Convert model template to AMBOS interaction model and validate the result",
tags = { BLUEPRINTS_TAG },
requestBody = #RequestBody(
content = #Content(
schema = #Schema(
implementation = TemplateValidationRequest.class
)
)
),
responses = {
#ApiResponse(
responseCode = "200",
description = "Success.",
content = #Content(
schema = #Schema(
implementation = TemplateValidationResponse.class
)
)
),
#ApiResponse(
responseCode = "400",
description = "Failure",
content = #Content(
schema = #Schema(
implementation = String.class
)
)
)
}
)
#CustomerIdentityRequired
#AcceptsLanguageRequired
#AAA(serviceName = SERVICE_NAME, operationName = BLUEPRINTS_GET)
ModelTemplateValidationResponse validateModelTemplate(TemplateValidationRequest);
 
fun validateModelTemplate(modelTemplate: InteractionModel,
sampleData: Map<String, Any>): TemplateValidationResponse {
val request = TemplateValidationRequest()
request.modelTemplate = modelTemplate
request.sampleData = sampleData
return temp.validateModelTemplate(request)//this is where I call the above code
//If this request fails and results in a 400 error, I want to get a String
}

What about something like:
public Class YourResponse {
private boolean isError;
private String setThisWhenThereIsError;
private YourObject setThisWhen200;
}

Related

How to send POST request to another microservice containing enum #RequestParam in kotlin?

I tried to send request to another service containing enum #RequestParam but it always fails.
Here's the example of my request;
fun upsertExclusionOverride(
request: request
): ExcOve? {
val builder = UriComponentsBuilder.fromUriString("/v1/p-b/e/bulk")
val httpEntity = RestTemplateUtils.getHttpEntityCustomHeaders(request, headers)
try {
val body = restTemplate
.exchange(
builder.toUriString(),
HttpMethod.POST,
httpEntity,
Response::class.java
)
.body
?: throw Exception("Fail")
return body.toDomain()
} catch (e: RestClientException) {
log.error(e.message)
throw Exception("Fail")
}
}
This is the other microservice;
#PostMapping("/e/bulk")
#ApiOperation("Exclude")
fun exclusionsInBulk(
#RequestParam(name = "operation", required = true) operation: Operation,
#RequestPart("file") #ApiParam(
value = "File",
required = true,
format = "byte"
) file: MultipartFile
): ResponseEntity<Response> {
.....
}
How should I prevent 400 Bad Request?
I added enum converter but it didn't work.
I expect it to not to get 400 Bad Request.

springdoc multiple 404 responses using #ApiResponse (java annotations)

How to create multiple 404 responses (or more broadly, multiple same HTTP code responses) using java annotations.
I've tried:
#ApiResponse(
responseCode = "404",
description = "Not Found 1"
)
#ApiResponse(
responseCode = "404",
description = "Not Found 2"
)
And also mulitple #Content:
#ApiResponse(
responseCode = "404",
content = {
#Content(schema = #Schema(name = "404-1", description = "404-1")),
#Content(schema = #Schema(name = "404-2", description = "404-2"))
}
)
The only way I can get something similar to multiple is by using #ExampleObject[]:
#ApiResponse(
responseCode = "404",
content = #Content(
mediaType = "application/json",
examples = {
#ExampleObject(name = "404-1", description = "Not Found 1 desc"),
#ExampleObject(name = "404-2", description = "Not Found 2 desc")
}
)
)
This is not ideal because it requires human interaction to view all of them and is just not wanted; the expectation is to have:
- 200
- 404 Description 1
- 404 Description 2
- 404 Description 3
or even better:
- 200
- 404 Description 1
Description 2
Description 3
I'm using springdoc and the following dep:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.4.3</version>
</dependency>
By design, and not springdoc, but OpenAPI-Specification, all the responses are stored in a type ApiResponses which extends LinkedHashMap.
https://github.com/OAI/OpenAPI-Specification/blob/3.0.1/versions/3.0.1.md#responsesObject
Eeach HTTP code, for an operation can only have one ApiResponse object assigned.
Using examples is a good way to go.
If your multiple 404 responses have different structure, you can use oneof as follow:
#RestController
public class HelloController {
#GetMapping("/hello")
#ApiResponses({
#ApiResponse(responseCode = "200"),
#ApiResponse(description = "Not found", responseCode = "404",
content = #Content(mediaType = "application/json", schema = #Schema(oneOf = {
Foo.class, Bar.class }))) })
String hello() {
return null;
}
#Schema(description = "this is bar")
class Bar {
private String bar;
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}
#Schema(description = "this is foo")
class Foo {
private String foo;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
}
I solved my issue by just adding an HTML <br/> tag to the description where I wanted a new line:
#Operation(
responses = {
#ApiResponse(responseCode = "404", content = #Content,
description =
"This is potential 404 #1 <br/>" +
"This is potential 404 #2"
)
}
)
Alternatively,
You could create an annotation to make this more readable, for example something like #ApiResponse404 and add it to the operation via OperationCustomizer:
#Override
public Operation customize(Operation operation, HandlerMethod handlerMethod) {
ApiResponse404 notFounds = handlerMethod.getMethodAnnotation(ApiResponse404.class);
if (notFounds != null)
operation.getResponses()
.addApiResponse("404", new ApiResponse()
.description(String.join("<br/>", notFounds.value()))
);
return operation;
}
Of course you would have to take into consideration the #Content, which you can easily add to the annotation, but I don't need it my scenario, I just need the description.
Then in a controller you can use the annotation:
#GetMapping("/helloworld")
#ApiResponse404({"This is potential 404 #1", "This is potential 404 #2"})
String getHelloWorld() {
return "Hello. World.";
}

Passing a map in GET, JAVA

How do i Pass a Map of Key Value pairs to a GET REST API,
Here is the call to the resource .. I am getting a method not allowed
String queryMap= String.format("{'softwareversion':'%s','peril':'%s','analysistype':'%s', 'region':'%s'}", "HD18", "Flood", "EP", "USFL");
String url = String.format("http://localhost:%d/templates/modelprofile?queryMap=%s", API_APPLICATION_RULE.getLocalPort(),queryMap);
Response response = ClientBuilder.newClient()
.target(url)
.request()
.header("Authorization", getToken())
.get();
I have the resource as below
#GET
#Path("/{templateType}")
#Timed
#Produces(MediaType.APPLICATION_JSON)
#ApiOperation(value = "Get templates based on peril/region,version and type",
httpMethod = ApiConstants.GET)
#ApiResponses(value = {
#ApiResponse(code = ApiConstants.INT_200,
message = "TemplateReader was retrieved successfully from the database."),
#ApiResponse(code = ApiConstants.INT_400,
message = "Bad request (wrong or missing inputs)"),
#ApiResponse(code = ApiConstants.INT_500,
message = ApiConstants.INTERNAL_SERVER_ERROR)
})
public Template getTemplate(#ApiParam(hidden = true) #Auth User user,
#ApiParam(name = "templateType", value = "templateType")
#PathParam("templateType") String templateType,
#ApiParam(name = "queryMap", value = "queryMap")
#RequestParameters Map<String,String> queryMap
) throws ApiException
You can pass it using request parameter as below.
#RequestMapping(name = "/url/", method = RequestMethod.GET)
public void method_name(#RequestParam(name = "map_name")Map<String, Object> requestMap){
//Process map and perform your logic
}

Tridion CoreService create component missing metadata

i got exception = {"Unable to find uuid:5708986b-390f-4728-b0c7-b49bd3d8f407:Metadata."}
schemaId = UpdatePubId(schemaId, containerId);
SchemaData schemaData = (SchemaData)client.Read(schemaId, null);
string xml = string.Format("<{0} xmlns=\"{1}\">{2}</{0}>", schemaData.RootElementName, schemaData.NamespaceUri, fields);
ComponentData componentData = new ComponentData
{
Content = xml,
ComponentType = ComponentType.Normal,
Title = title,
Schema = new LinkToSchemaData { IdRef = schemaId },
LocationInfo = new LocationInfo { OrganizationalItem = new LinkToOrganizationalItemData { IdRef = containerId } },
Id = "tcm:0-0-0",
MetadataSchema = schemaData.MetadataSchema,
Metadata = schemaData.Metadata
};
try
{
componentData = client.Save(componentData, new ReadOptions()) as ComponentData;
componentData = client.CheckIn(componentData.Id, new ReadOptions()) as ComponentData;
message.Set("Component", title + ", successfully");
}
catch (Exception exception)
{
message.Set("Component", exception.Message);
}
thanks Tridion experts
You are on the correct path, but the error indicates that you have not provided the Metadata fields for the component that you are trying to create.
This line is incorrect:
Metadata = schemaData.Metadata
It should pretty much, like that one where you create the content fields:
Metadata = String.Format("<Metadata xmlns=\"{0}\">{1}</Metadata>",schemaData.NamespaceUri, "YOUR METADATA XML")

How to store data for the application via REST post call

Hi am developing my first grails RESTful application... In that i have mapped the post request to save method.its showing some error like, Internal server Error..Can any one please help me to brief how to use the post method to save the data via REST Post request...?
My save method is as follows..
def save = {
def xml = request.XML
def post = new ImageProperties()
post.content = xml.content.text()
def markup
if (post.save()) { markup = { status("OK") } }
else { markup = { status("FAIL") } }
render contentType: "text/xml; charset=utf-8", markup } }
and ImageProperties class as follows...
class ImageProperties {
static hasMany={categories:Categories}
String name
String place
String description
String path
String category
Categories categories
}
Your are assigning the posted data to an expected content property of your ImageProperties
def post = new ImageProperties()
post.content = xml.content.text()
but where in your Entity is that property?
class ImageProperties {
static hasMany={categories:Categories}
String name
String place
String description
String path
String category
Categories categories
}
Update: If you want to simply populate all properties you can use the domain class constructor:
def post = new ImageProperties(xml.content)
See more in the section REST and Data Binding of the Grails manual.
Hi after a long trial and error method i found the answer.. Hope this will be helpful for many users...
def save = {
def xml = request.XML
def post = new ImageProperties()
post.name = xml.name.text()
post.place = xml.place.text()
post.path = xml.path.text()
post.description = xml.description.text()
post.category = xml.category.text()
post.categories = Categories.get(xml.categories.#id.text())
def markup
if (post.save()) {
markup = {
status("OK")
}
} else {
markup = {
status("FAIL")
}
}
render contentType: "text/xml; charset=utf-8",
markup
}