Escape Sequence in Camel restlet / rest dsl - rest

Camel Route -
rest("/servicenow").post("/{operation}").consumes("application/json").type(Model.class).produces(MediaType.APPLICATION_JSON).to("direct:servicenow");
from("direct:servicenow")
.setHeader("operationSelector", simple("${header.operation}"))
.process(new PreProcessor())
.recipientList().simple("servicenow://${header.instance}?userName=${header.name}&password=${header.password}&apiUrl=${header.apiUrl}")
.process(new PostProcessor());
and PostProcessor Class -
Object msg = exchange.getIn().getBody();
GsonBuilder builder = new GsonBuilder();
builder.setLenient();
Gson gson = builder.create();
JsonElement element = gson.toJsonTree(msg);
JsonObject result = new JsonObject();
if (element.isJsonArray()) {
JsonArray array = (JsonArray) element;
result.add("result", array);
System.out.println(result.toString());
exchange.getOut().setBody(result.toString());
} else {
result.add("result", element);
System.out.println(result.toString());
exchange.getOut().setBody(result.toString());
}
Example result contains escape sequences in the JSON Array/Object while returning to the Client
"{\"result\":[{\"parent\":\"\",\"made_sla\":\"true\",\"caused_by\":\"\"
Please do help to modify in the restlet configuration if required so I get response without escape sequence in JSON response.

Instead of using this line :
JsonObject result = new JsonObject();
Use this prefered answer :
Map<DataType,DataType> result = new HashMap<DataType,DataType>();
result.put("result", array);
exchange.getOut().setBody(result);
The restlet will bind the map object to a jsonObject.

Related

How to get a generic map as a response from restTemplate exchange method?

We have a rest service that returns a byte array inside a map of type . While receiving the response if I use Map without the generics, the byte array data is converted to a String. Is it possible to send just the byte data from the server, if so how to retrieve that data from the client using RestTemplate?
ResponseEntity<Map<String, byte[]>> result result = restTemplate.exchange("http://localhost:8085/api/fetchContent?Id=" + contentId+"&userName=trump", HttpMethod.GET, entity, Map.class, params);
The above code will give a compilation issue as the return type is a map.
Use ParameterizedTypeReference<T>:
ParameterizedTypeReference<Map<String, byte[]>> responseType =
new ParameterizedTypeReference<Map<String, byte[]>>() {};
ResponseEntity<Map<String, byte[]>> responseEntity =
restTemplate.exchange("http://example.org", HttpMethod.GET, entity, responseType);

javax.ws.rs.core.Response convert to string in java1.6

I want to convert Response to string
Response response = ClientBuilder.newBuilder().sslContext(sslContext).build().target(url)
.request(MediaType.APPLICATION_JSON).get();
// I have tried as below.. It didn't work
String result = (String)response.getEntity();
Error is java.lang.ClassCastException: org.glassfish.jersey.client.HttpUrlConnector$1 cannot be cast to java.lang.String
Please not i am using Java 1.6 version and i cannot find methods like readEntity(String.class) and getEntity(String.class) from Response class.
Alternate way works as below by giving String.class in get.
But i need Response object First to check the status code then i want to convert it to String.
String response = ClientBuilder.newBuilder().sslContext(sslContext).build().target(url)
.request(MediaType.APPLICATION_JSON).get(String.class);
Please assist in solving this
The readEntity() method is the way to go:
Response response = ...
String value = response.readEntity(String.class);
I don't understand why you are saying that such method is not available for you: the ClientBuilder class (just like the readEntity() method) was also introduced in JAX-RS 2.0 (Java EE 7) as part of the Client API.
Don't you have any JAX-RS 1.x dependencies in the classpath?
If we don't use Jersey client jar, then we don't get readEntity(class) and getEntity(class). These methods are not part of javax.ws.rs.core.Response they are part of Jersey clientjar. So if we are using javax.ws.rs.core.Response, then we have to manually convert as below
javax.ws.rs.core.Response response;
String result = readInputStreamAsString((InputStream) response.getEntity());
public static String readInputStreamAsString(InputStream in) {
try {
BufferedInputStream bis = new BufferedInputStream(in);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int result = bis.read();
while (result != -1) {
byte b = (byte) result;
buf.write(b);
result = bis.read();
}
return buf.toString();
} catch (IOException ex) {
return null;
}
}

How to parse AEM DAM JSON InputStream and create JSON Object

I have a requirement where-in I have to read the JSON file which exists in AEM DAM. So, I have created a query to read the JSON file in inputStream. With the below line of code, i could get the JSON file in Input Stream. Now, I need to know If there is any standard library to read the input stream and create the JSON Object?
InputStream is = asset.getOriginal().getStream();
There are many libraries for serializing/deserializing JSON in java, the most notable is Google’s Gson: https://github.com/google/gson
I’ve used gson in all my AEM projects that require JSON manipulation. That does not mean you can’t use another library.
As mentioned above there are many libraries like Google’s Gson, Jackson an etc. I think the below code snippet can help you,
public JSONObject getJsonFromFile(ResourceResolver resolver,String filePath){
JSONObject jsonObj=new JSONObject();
Resource resource= resolver.getResource(filePath);
try {
Node jcnode = resource.adaptTo(Node.class).getNode("jcr:content");
InputStream content=jcnode.getProperty("jcr:data").getBinary().getStream();
StringBuilder sb = new StringBuilder();
String line;
BufferedReader br = new BufferedReader(new
InputStreamReader(content,StandardCharsets.UTF_8));
while ((line = br.readLine()) != null) {
sb.append(line);
}
jsonObj = new JSONObject(sb.toString());
}catch (RepositoryException | JSONException | IOException e) {
LOGGER.error(e.getMessage(),e);
}
return jsonObj;
}

How to transform PageRequest object to query string?

I'm writing an RESTful API which consumes another RESTful Data API, and I'm using Spring Data.
The client side send the page request using query params like:
http://api.mysite.com/products?page=1&size=20&sort=id,asc&sort=name,desc
And I transform the params to PageRequest object and transfer it to the Service Layer.
In the service, I would like to use TestTemplate to interact with the Data API which use a URL, and How can I transform the PageRequest object to a query string like
page=1&size=20&sort=id,asc&sort=name,desc
then I can request data like:
restTemplate.getForEntity("http://data.mysite.com/products?page=1&size=20&sort=id,asc&sort=name,desc",String.class)
I know I am a bit late on this answer, but I too was not able to found an already implemented way to do this. I ended up developing my own routine for doing this:
public static String encodeURLComponent(String component){
try {
return URLEncoder.encode(component, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("You are dumm enough that you cannot spell UTF-8, are you?");
}
}
public static String queryStringFromPageable(Pageable p){
StringBuilder ans = new StringBuilder();
ans.append("page=");
ans.append(encodeURLComponent(p.getPageNumber() + ""));
// No sorting
if (p.getSort() == null)
return ans.toString();
// Sorting is specified
for(Sort.Order o : p.getSort()){
ans.append("&sort=");
ans.append(encodeURLComponent(o.getProperty()));
ans.append(",");
ans.append(encodeURLComponent(o.getDirection().name()));
}
return ans.toString();
}
It is not complete, there probably are a couple of details that I am missing, but for my user case (and I think for most of them) this works.
you can pass as new :
new PageRequest(int page,int size)
And in repository layer you can write as:
Page<User> findByName(String name,Pageable page)
in place of Pageable page you have to pass new PageRequest(int page,int size)
For ascending order you can refer this:
List<Todo> findByTitleOrderByTitleAsc(String title);
I think you just need to iterate through the request parameters from your other API request, and then pass all the parameters values into the new Url for a new API request.
sudo code could be:
//all query params can be found in Request.QueryString
var queryParams = Request.QueryString;
private string ParseIntoQuery(NameValueCollection values)
{
//parse the identified parameters into a query string format
// (i.e. return "?paramName=paramValue&paramName2=paramValue2" etc.)
}
in your code, you will then do this:
restTemplate.getForEntity(urlAuthority + ParseIntoQuery(Request.QueryString));
simple as that. Hope that answers?
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl("http://data.mysite.com/products");
addRequestParam(uriComponentsBuilder, "page", pageable.getPageNumber());
addRequestParam(uriComponentsBuilder, "size", pageable.getPageSize());
String uri = uriComponentsBuilder.toUriString() + sortToString(pageable.getSort());
addRequestParam method:
private static void addRequestParam(UriComponentsBuilder uriBuilder, String parameterName, Object parameter) {
if (parameter != null) {
uriBuilder.queryParam(parameterName, parameter);
}
}
implement sortToString(Sort sort) method as #Shalen. You have to obtain something like this: &sort=name,asc&sort=name2,desc. Return "" if Sort is null;

HTTP CacheControl with Jersey and json implementation

I want to add the CacheControl intormation to a GET service that use the json binding.
I found that to add the cacheControl to a response the REST service sound like this:
#GET
#Path("cacheheadertest")
#Produces({"*/*"})
def testcache():javax.ws.rs.core.Response {
val rb:Response.ResponseBuilder = javax.ws.rs.core.Response.ok("chached test message")
val cc = new CacheControl()
cc.setMaxAge(60)
cc.setNoCache(false)
rb.cacheControl(cc).build()
}
but I have a REST service that produce json messages and the jersey library transform automaticcally the java object from java to xml/json.
#GET
#Path("jsontestcache")
#Produces(Array(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML))
def myjsontestservice(#HeaderParam("X-TOKENID") tokenId: String,
#QueryParam("clientId") clientId: String):com.test.MyResultClass = {
val response= new com.test.MyResultClass
[...]
response
}
How can I add the cache control to the response of myjsontestservice service? Do I need to use a filter and append the cachecontrol once the response has been created by jersey?
thanks million
Flavio
You would still need to return a Response object.
def somejson() : Response = {
val builder = Response.ok(new com.test.MyResultClass);
val cc = new CacheControl()
cc.setMaxAge(60)
cc.setNoCache(false)
builder.cacheControl(cc).build()
}
Jersey's interceptors will automatically convert your class into a JSON object.