Spring Resttemplate unexpected field "session" in the post data - java

{
"platform": "iOS",
"device": {
"os_name": "iPhone OS",
"manufacturer": "Apple",
"type": "iPhone3",
"version": "1",
"os_version": "5.1.1"
},
"app_version": "1.0",
"device_id": "",
"app_key": "1234567890",
"developer_key": "",
"app_name": "test",
"session": { // here
"platform": "iOS",
"device": {
"os_name": "iPhone OS",
"manufacturer": "Apple",
"type": "iPhone3",
"version": "1",
"os_version": "5.1.1"
},
"app_version": "1.0",
"device_id": "",
"app_key": "1234567890",
"developer_key": "",
"app_name": "test"
}
}
This is the data generated by MappingJacksonConverter but I don't know how to disable the "session" field containing the whole recursive data.
HttpEntity<OlSession> sessionEntity = new HttpEntity<OlSession>(new OlSession());
ResponseEntity<String> response = restTemplate.postForEntity("http://localhost:3000/test/abcd", sessionEntity, String.class);
This is the code to post the above data. Is there any part that I need to add to disable the "session" field?

There are two simple solution.
1) Use jackson annotation to ignore that property.
But in this way, session in OlSession property will not be serialized everywhere.
#JsonIgnore
Object getSession() {
return session
}
Take a look this doc JacksonAnnotation
2) Just set null before you send.

Related

GSON serialize of SNSEvent resulting in lower case fields which lambda expects Capitalize words

I have a lambda function which takes SNSEvent(http://javadox.com/com.amazonaws/aws-lambda-java-events/1.1.0/com/amazonaws/services/lambda/runtime/events/SNSEvent.html) as the input and then works on that. For writing the some integration test cases, I wanted to call this lambda with the SNSEvent serialized using using lambda.invoke in which the message would be string.
So, for that, I was doing GSON.toJson([object of SNSEvent type]) and from this, I was getting a string. But the problem is, when I am using this string the invoke the lambda, I am getting an exception that deserialization of this string is failing.
Eg. GSON.toJson is deserializing to :
{
"records": [
{
"eventSource": "aws:sns",
"eventVersion": "1.0",
"eventSubscriptionArn": "arn:aws:sns:us-west-2:{{{accountId}}}:ExampleTopic",
"sns": {
"type": "Notification",
"messageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
"topicArn": "arn:aws:sns:us-west-2:{{accountId}}:ExampleTopic",
"subject": "example subject",
"message": "example message",
"timestamp": "1970-01-01T00:00:00.000Z",
"signatureVersion": "1",
"signature": "EXAMPLE",
"signingCertUrl": "EXAMPLE",
"unsubscribeUrl": "EXAMPLE",
"messageAttributes": {
"test": {
"type": "String",
"value": "TestString"
},
"testBinary": {
"type": "Binary",
"value": "TestBinary"
}
}
}
}
]
}
while, the actual, it wants is (with capital letters):
{
"Records": [
{
"EventSource": "aws:sns",
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:sns:us-west-2:{{{accountId}}}:ExampleTopic",
"Sns": {
"Type": "Notification",
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
"TopicArn": "arn:aws:sns:us-west-2:{{accountId}}:ExampleTopic",
"Subject": "example subject",
"Message": "example message",
"Timestamp": "1970-01-01T00:00:00.000Z",
"SignatureVersion": "1",
"Signature": "EXAMPLE",
"SigningCertUrl": "EXAMPLE",
"UnsubscribeUrl": "EXAMPLE",
"MessageAttributes": {
"Test": {
"Type": "String",
"Value": "TestString"
},
"TestBinary": {
"Type": "Binary",
"Value": "TestBinary"
}
}
}
}
]
}
Any idea why is it so? And how can I fix it? Should I use some other object instead of SNSEvent while invoking the lambda.

Elasticsearch nested sort - mismatch between document and nested object used for sorting

I've been developing a new search API with AWS Elasticsearch (version 6.2) as backend.
Right now, I'm trying to support "sort" options for the API.
My mapping is as follows (unrelated fields not included):
{
"properties": {
"id": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
},
"description": {
"type": "text"
},
"materialDefinitionProperties": {
"type": "nested",
"properties": {
"id": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
},
"analyzer": "case_sensitive_analyzer"
},
"value" : {
"type": "nested",
"properties": {
"valueString": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
}
}
}
}
I'm attempting to allow the users sort by property value (path: materialDefinitionProperties.value.valueLong.raw).
Note that it's inside 2 levels of nested objects (materialDefinitionProperties and materialDefinitionProperties.value are nested objects).
To sort the results by the value of property with ID "PART NUMBER", my request for sorting is:
{
"fieldName": "materialDefinitionProperties.value.valueString.raw",
"nestedSort": {
"path": "materialDefinitionProperties",
"filter": {
"fieldName": "materialDefinitionProperties.id",
"value": "PART NUMBER",
"slop": 0,
"boost": 1
},
"nestedSort": {
"path": "materialDefinitionProperties.value"
}
},
"order": "ASC"
}
However, as I examined the response, the "sort" field does not match with document's property value:
{
"_index": "material-definition-index-v2",
"_type": "default",
"_id": "development_LITL4ZCNE",
"_source": {
"id": "LITL4ZCNE",
"description": [
"CPU, Intel, Cascade Lake, 8259CL, 24C, 210W, B1 Prod"
]
"materialDefinitionProperties": [
{
"id": "PART NUMBER",
"description": [],
"value": [
{
"valueString": "202-001193-001",
"isOriginal": true
}
]
}
]
},
"sort": [
"100-000018"
]
},
The document's PART NUMBER property is "202-001193-001", the "sort" field says "100-000018", which is the part number of another document.
It seems that there's a mismatch between the master document and nested object used for sorting.
This request worked well when there's only a small number of documents in the cluster. But once I backfill the cluster with ~1 million of records, the symptom appears. I've also tried creating a new ES cluster but the results are the same.
Sorting by other non-nested attributes worked well.
Did I misunderstand the concept of nested objects, or misuse the nested sort feature?
Any ideas appreciated!
This is a bug in Elasticsearch. Upgrading to 6.4.0 fixed the issue.
Issue tracker: https://github.com/elastic/elasticsearch/pull/32204
Release note: https://www.elastic.co/guide/en/elasticsearch/reference/current/release-notes-6.4.0.html

Dynamic response of Retrofit

My answer Json depends on whether it succeeds or not.
Unsuccessful example:
{
"success": false,
"errors": {
"email": "Could not find email address"
}
}
Successful example:
{
"success": true,
"user": {
"id": 6,
"fname": "XXXXXX",
"lname": "XXXXXX",
"email": "Username#mail.ca",
"roles": [
"Player"
"Coach"
"manager",
"Admin"
]
"date_registered": "2018-03-16T17: 49: 05.000Z"
}
"Token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzaWQiOiJiNjU1MDVkOGJiYzZhMTg1Y2E5MjU5NDlmNTU0OTc0MTgzM2Y2N2NiNjFjYThkMzNkMTUxY2U2MDhjMTBmNTllIiwiaWF0IjoxNTI3MjY3MzEwLCJleHAiOjE1Mjc4NzIxMTB9.p5pTlNjTsr-8N_8B3M5fW3T6PTTrcFo8D77N0WWgA3c"
}
Now, I want to have a POJO for both at the same time with retrofit.
Thank you
Edit : I just solved the problem by changing the form of JSON to :
{
"success": true,
"data": {
"user": {
"id": 6,
"fname": "XXXXXXX",
"lname": "XXXXXXXX",
"email": "Username#mail.ca",
"roles": [
"player",
"coach",
"manager",
"admin"
],
"activation_state": 0,
"date_registered": "2018-03-16T17:49:05.000Z"
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzaWQiOiI0MTFlZmI5Y2ExYzY1ZWFlYzQ4Yzg1ZjJkYTQwOThmODBjOTk1NWNjNjcyOTNlODI5NmI4N2RjZWY5OTMzYzljIiwiaWF0IjoxNTI4NDI0MDA1LCJleHAiOjE1Mjg0MjQ2MDl9.lTsQ867Lk78RV2ruaQFyxUNfm58bHpfzEsZnvKJQMXQ"
},
"errors": {}
}
Thank you for help
You could simply return a String Retrofit, and then parse it manually.
If not, then you have to create a POJO object that contains all variables from both objects.
And then at runtime you check if "success" is true/false, and then try to access the underlying varaibles.
Copy your json response and past http://pojo.sodhanalibrary.com/
Then submit
You will get multiple pojo class with respect to your response ,

Json Pagination not working from PageImpl

I have this controller:
#RequestMapping("/api")
public ResponseEntity<?> a(Pageable pageable) throws IOException {
ObjectMapper mapper = new ObjectMapper( );
File file = new File( "samplejson.json" );
JsonNode jsonNode = mapper.readTree( file );
List<JsonNode> nodes = new ArrayList<>();
if ( !jsonNode.isArray() )
nodes.add( jsonNode );
else
for ( JsonNode node : jsonNode )
nodes.add( node );
return new ResponseEntity<Object>( new PageImpl( nodes, pageable, nodes.size() ), HttpStatus.OK );
}
and when i postman it, it gives me this response:
{
"content": [
{
"id": 1,
"first_name": "Dode",
"email": "dcardall0#zimbio.com",
"gender": "Female",
"timestamp": "11/12/1981"
},
{
"id": 2,
"first_name": "Andrus",
"email": "amcgeever1#jigsy.com",
"gender": "Male",
"timestamp": "10/25/1988"
},
{
"id": 3,
"first_name": "Allyn",
"email": "afakes2#samsung.com",
"gender": "Male",
"timestamp": "9/3/1997"
},
{
"id": 4,
"first_name": "Merell",
"email": "mmoreton3#census.gov",
"gender": "Male",
"timestamp": "3/7/2009"
}
],
"last": true,
"totalElements": 10,
"totalPages": 1,
"size": 20,
"number": 0,
"sort": [
{
"direction": "DESC",
"property": "id",
"ignoreCase": false,
"nullHandling": "NATIVE",
"descending": true,
"ascending": false
}
],
"first": true,
"numberOfElements": 10 }
in the URI i have this
http://localhost:8080/api?sort=id, desc
However the pagination isn't working. As you can see, the sort direction in the response says "DESC". So it's supposed to be in descending order, right? But it's not working. I think because it's inside an object content which was created by pagination. But i don't know how to access what's inside content.
in order to apply PageRequest options like sort etc. you need to use PagingAndSortingRepository (see Spring Paging documentation)
So the sorting and getting the page is executed inside repository logic. See org.springframework.data.jpa.repository.support.SimpleJpaRepository.readPage
You can also go through this tutorial: https://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-part-seven-pagination/

Determine Glassfish HTTP port number from java code without request

I'm using Glassfish 3.1.2.2. Is it possible to determine http port number (http-listener-1) from java (EJB) code? I don't have any connections or requests, so reading ServletRequest is not an option.
Yes, this is possible. You can use the Glassfish Admin REST API to retrieve nearly every property of the server.
For the properties of the http-listener-1 use the following url: http://localhost:4848/management/domain/configs/config/server-config/network-config/network-listeners/network-listener/http-listener-1
A normal GET request will give you a HTML response, set the Accept header to application/json to retrieve the response in JSON.
In your EJB you just have to issue an HTTP request to the url from above with the right header. Here is an example:
String url = "http://localhost:4848/management/domain/configs/config/server-config/network-config/network-listeners/network-listener/http-listener-1";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestProperty("Accept", "application/json");
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
This will give you a result similar to this:
{
"message": "",
"command": "http-listener-1",
"exit_code": "SUCCESS",
"extraProperties": {
"commands": [
{
"path": "create-ssl",
"method": "POST",
"command": "create-ssl"
}
],
"methods": [
{
"name": "GET"
},
{},
{
"messageParameters": {
"address": {
"defaultValue": "0.0.0.0",
"optional": "true",
"type": "string",
"key": "false"
},
"enabled": {
"defaultValue": "true",
"optional": "true",
"type": "boolean",
"key": "false"
},
"jkConfigurationFile": {
"defaultValue": "${com.sun.aas.instanceRoot}/config/glassfish-jk.properties",
"optional": "true",
"type": "string",
"key": "false"
},
"jkEnabled": {
"defaultValue": "false",
"optional": "true",
"type": "boolean",
"key": "false"
},
"name": {
"optional": "false",
"type": "string",
"key": "true"
},
"port": {
"optional": "false",
"type": "int",
"key": "false"
},
"protocol": {
"optional": "false",
"type": "string",
"key": "false"
},
"threadPool": {
"optional": "true",
"type": "string",
"key": "false"
},
"transport": {
"optional": "false",
"type": "string",
"key": "false"
}
},
"name": "POST"
},
{
"messageParameters": {
"target": {
"acceptableValues": "",
"defaultValue": "server",
"optional": "true",
"type": "string"
}
},
"name": "DELETE"
}
],
"entity": {
"address": "0.0.0.0",
"enabled": "true",
"jkConfigurationFile": "${com.sun.aas.instanceRoot}/config/glassfish-jk.properties",
"jkEnabled": "false",
"name": "http-listener-1",
"port": "8080",
"protocol": "http-listener-1",
"threadPool": "http-thread-pool",
"transport": "tcp"
},
"childResources": {
"find-http-protocol": "http://localhost:4848/management/domain/configs/config/server-config/network-config/network-listeners/network-listener/http-listener-1/find-http-protocol",
"property": "http://localhost:4848/management/domain/configs/config/server-config/network-config/network-listeners/network-listener/http-listener-1/property"
}
}
}
As you can see the result contains the port (8080 in this case).
You can either parse the value manually from the response string or use some JSON library to convert the response to an JSON object from which you can easily retrieve the property.
This procedure should work if your Glassfish Admin interface is unprotected, if you have enabled secure administration you may have to send authorization parameters with your HTTP request.
See also:
Oracle GlassFish 3.1 Administration Guide - Using REST Interfaces to Administer GlassFish Server

Categories