Following is the log of my current json body. And I want to add new property to this body. "NewPropertyName": "value". Since the value is in a database I am using a class mediator to add this property.
[2015-05-18 05:47:08,730] INFO - LogMediator To: /a/create-project, MessageID: urn:uuid:b7b6efa6-5fff-49be-a94a-320cee1d4406, Direction: request, _______BODY_______ =
{
"token": "abc123",
"usertype":"ext",
"request": "create"
}
Class mediator's mediate method,
public boolean mediate(MessageContext mc) {
mc.setProperty("key", "vale retrived from db");
return true;
}
but this doesn't work as I expected. I couldn't find any guide to add property to json body using class mediator, please help.
To inject a property to the body you have to use following code snippet,
JsonUtil.newJsonPayload(
((Axis2MessageContext) context).getAxis2MessageContext(),
transformedJson, true, true);
inside a class mediator. Following is an example of mediate method.
/**
* Mediate overridden method to set the token property.
*/#Override
public boolean mediate(MessageContext context) {
try {
// Getting the json payload to string
String jsonPayloadToString = JsonUtil.jsonPayloadToString(((Axis2MessageContext) context)
.getAxis2MessageContext());
// Make a json object
JSONObject jsonBody = new JSONObject(jsonPayloadToString);
// Adding the name:nameParam.
jsonBody.put("name", getNameParam());
String transformedJson = jsonBody.toString();
// Setting the new json payload.
JsonUtil.newJsonPayload(
((Axis2MessageContext) context).getAxis2MessageContext(),
transformedJson, true, true);
System.out.println("Transformed JSON body:\n" + transformedJson);
} catch (Exception e) {
System.err.println("Error occurred: " + e);
return false;
}
return true;
}
You will need json and other libraries for this. This is fully explained in following blog post.
json-support-for-wso2-esb-class-mediator
mc.setProperty is used to create a new property as if you were using property mediator.
If you want to add a new element inside your message, in java, you can handle it as if it were a XML message (for exemple, to get the first element :
OMElement element = (OMElement) context.getEnvelope().getBody().getFirstOMChild(); )
Sample to add a new element with a javascript :
<script language="js"><![CDATA[
var payloadXML = mc.getPayloadXML();
payloadXML.appendChild(new XML(<NewPropertyName>value</NewPropertyName>));
mc.setPayloadXML(payloadXML);
]]></script>
Log the message in XML with <log level="full"> and you get :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<jsonObject>
<token>abc123</token>
<usertype>ext</usertype>
<request>create</request>
<NewPropertyName>value</NewPropertyName>
</jsonObject>
</soapenv:Body>
</soapenv:Envelope>
Log the message in JSON with
<log>
<property name="JSON-Payload" expression="json-eval($.)"/>
</log>
and you get :
JSON-Payload = {"token":"abc123","usertype":"ext","request":"create","NewPropertyName":"value"}
Related
I want to put mapping for a field by JAVA API but failed. Following is detailed information:
My data structure is :
{
"mje-test-execution-id": "464b66ea6c914ddda217659c84a3cb9d",
"jvm-free-memory": 315245608,
"jvm-total-memory": 361758720,
"system-free-memory": 0,
"jvm-max-memory": 7600078848,
"system-total-memory": 34199306240,
"memory-time-stamp": "2020-03-12T05:12:16.835Z",
"mje-host-name": "CN-00015345",
"mje-test-suite-name": "SCF Test no mje version",
"mje-version": "1.8.7771-SNAPSHOT",
"mje-test-artifact-id": "msran-regression-tests",
"mje-test-version": "1.8.7771-SNAPSHOT",
"stp-id": "vran-stp",
"mje-test-location": {
"lat": 58.41,
"lon": 15.62
}
}
What I want to do is : put "mje-test-location" type to be "geo_point"
My code snippet :
public void postMapping(String indexName, String field, String type) throws IOException {
GetIndexRequest request = new GetIndexRequest(indexName);
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
if (!exists) {
LOGGER.info("index {} does not exist. Now to post mapping.", indexName);
PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.startObject("properties");
{
builder.startObject(field);
{
builder.field("type", type);
}
builder.endObject();
}
builder.endObject();
}
builder.endObject();
putMappingRequest.source(builder);
//
AcknowledgedResponse putMappingResponse = client.indices().putMapping(putMappingRequest,
RequestOptions.DEFAULT);
boolean acknowledged = putMappingResponse.isAcknowledged();
if (acknowledged) {
LOGGER.info("Succeed to put mapping: field:{}, type: {}", field, type);
}
}
LOGGER.info("Fail to put mapping due to index {} already exist, ", indexName);
}
Error info:
15:59:54.397 [main] DEBUG org.elasticsearch.client.RestClient - request [PUT http://seliiuapp00269.lmera.ericsson.se:9208/mje-scf-v2-20200313-post/_mapping?master_timeout=30s&timeout=30s] returned [HTTP/1.1 400 Bad Request]
org.elasticsearch.ElasticsearchStatusException: Elasticsearch exception [type=action_request_validation_exception, reason=Validation Failed: 1: mapping type is missing;]
ElasticSearch JAVA API Version : <elasticsearch.rest.high.level.client>7.0.0</elasticsearch.rest.high.level.client>
You need to specify the document type like this:
putMappingRequest.type("_doc");
And also need to specify the types of the fields in here:
builder.field("type", type);
Like: ("type", "text") or ("type", "long"), ("type", "date") ......
You can see the datatypes in here
I'll post #Mincong's comment as an answer because I was importing the wrong import that I found from github searchs:
What is the full name of your class "PutMappingRequest": org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest or org.elasticsearch.client.indices.PutMappingRequest? You should use the second one.
I have a problem with me web service which I created in Java. This web service is to send data to my mobile application created in Swift.
For now I just want to test communication between application and WebService, so I create one simple method which returns a string.
My WebService:
#WebService(serviceName = "mSetiWebService", targetNamespace = "http://javawebservices.dawidratajczak.pl")
#SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL, parameterStyle = ParameterStyle.WRAPPED)
public class mSetiWebService {
#WebMethod(operationName = "getMyOtherStuff", action="getMyOtherStuffAction")
public String getMyOtherStuff() {
return "Hello from WebService !";
}
}
The java package(namespace) name is pl.dawidratajczak.webservices. I test this WebService by Boomerang Plugin for chrome and it works fine. But when I use SOAPEngine for Swift a get an error.
My Swift code:
let soap = SOAPEngine()
soap.userAgent = "SOAPEngine"
soap.actionNamespaceSlash = true
soap.version = SOAPVersion.VERSION_1_1
soap.responseHeader = true // use only for non standard MS-SOAP service
soap.requestURL("http://localhost:8080/mSetiSoapService/mSetiWebService",
soapAction: "getMyOtherStuff",
completeWithDictionary: { (statusCode : Int,
dict : [NSObject : AnyObject]!) -> Void in
let result:Dictionary = dict as Dictionary
NSLog("%#", result)
}) { (error : NSError!) -> Void in
NSLog("%#", error)
}
The error is simple: (I change . in address to _)
SOAPEngine Server response: Unexpected wrapper element getMyOtherStuff found. Expected {[httpjavawebservices_dawidratajczak_pl}getMyOtherStuff.
2016-08-26 20:24:59.835 SETI Mobile[4658:200526] Error Domain=NSOSStatusErrorDomain Code=0 "Unexpected wrapper element getMyOtherStuff found. Expected {http://javawebservices_dawidratajczak_pl}getMyOtherStuff." UserInfo={NSLocalizedDescription=Unexpected wrapper element getMyOtherStuff found. Expected {javawebservices_dawidratajczak_pl}getMyOtherStuff.}**
When I put the soapAction like the error expect {url}getMyOtherStuff I get another error that character { is unrecognized. At the end when I put all url and soapActionme function is not found.
What I do wrong?
When trying to parse the JSON being returned by my Serlvet to my JSP page the following line of code is throwing a invalid character exception :
var obj = jQuery.parseJSON(data);
CLIENT SIDE CODE
<script type = "text/javascript">
function updateProgrammerDetails(site, Id) {
$.post('EngineAdminServlet',
{
action: "updateProgrammerMenu",
siteDetails: site,
ID: Id,
},
function(data, status){
var pid, name, sky, ip, eleven;
var obj = jQuery.parseJSON(data);
.........
}
}).fail(function(error) {
alert("Error retrieving details from server");
}); //end ajax call
}
</script>
JSON STRING GENERATED USING GSON
I've imported the GSON library in my Servlet class in order to convert my Java object 'ProgrammerForJSP' to a JSON string. This was recommended on other posts to avoid any typos when creating the JSON string myself. This is the string it returned:
{"ID":123,"siteName":"VEGAS","skyl":"WZ0019","ipAddress":"0.0.0.0","code":"L/BEG"}
SERVLET CODE
....
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
String gson = new Gson().toJson(myObject);
response.getWriter().write(gson);
} //end of method
I don't know if I'm missing a step or doing something wrong? My thought is that the IP address field might be throwing off the parser and breaking the code (hence the invalid character exception) because it contains period characters in it? I really have no idea.
EDIT
I'm using jquery-1.11.3.js
The error is because the $.post method has already detected a JSON response and parsed the result to an object for you. You are then trying to call parseJSON on an object instead of a JSON string, which results in the error you've seen. You simply need to remove the call to $.parseJSON. Try this:
function updateProgrammerDetails(site, Id) {
$.post('EngineAdminServlet', {
action: "updateProgrammerMenu",
siteDetails: site,
ID: Id,
}, function(data, status) {
var pid, name, sky, ip, eleven;
// work with the object in 'data' here, E.g:
console.log(data.ID, data.siteName); // = 123, 'VEGAS'
}).fail(function(error) {
alert("Error retrieving details from server");
}); //end ajax call
}
How to prepare XML with CDATA ,
I am preraring this response via Jaxb,
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<SOAP-ENV:Header/>
<soapenv:Body>
<tem:RequestData>
<tem:requestDocument>
<![CDATA[
<Request>
<Authentication CMId="68" Function="1" Guid="5594FB83-F4D4-431F-B3C5-EA6D7A8BA795" Password="poihg321TR"/>
<Establishment Id="4297867"/>
</Request>
]]>
</tem:requestDocument>
</tem:RequestData>
</soapenv:Body>
</soapenv:Envelope>
But from Jaxb i am not getting CDATA , how to put CDATA inside <tem:requestDocument> element.
Here is my Java Code :
public static String test1() {
try {
initJB();
String response = null;
StringBuffer xmlStr = null;
String strTimeStamp = null;
com.cultagent4.travel_republic.gm.Envelope envelope = null;
com.cultagent4.travel_republic.gm.Header header = null;
com.cultagent4.travel_republic.gm.Body body = null;
com.cultagent4.travel_republic.gm.RequestData requestData = null;
com.cultagent4.travel_republic.gm.RequestDocument requestDocument = null;
com.cultagent4.travel_republic.gm.RequestDocument.Request request = null;
com.cultagent4.travel_republic.gm.RequestDocument.Request.Authentication authentication = null;
com.cultagent4.travel_republic.gm.RequestDocument.Request.Establishment establishment = null;
ObjectFactory objFact = new ObjectFactory();
envelope = objFact.createEnvelope();
header = objFact.createHeader();
envelope.setHeader(header);
body = objFact.createBody();
requestData = objFact.createRequestData();
requestDocument = objFact.createRequestDocument();
request = new RequestDocument.Request();
authentication = new RequestDocument.Request.Authentication();
authentication.setCMId("68");
authentication.setGuid("5594FB83-F4D4-431F-B3C5-EA6D7A8BA795");
authentication.setPassword("poihg321TR");
authentication.setFunction("1");
request.setAuthentication(authentication);
establishment = new RequestDocument.Request.Establishment();
establishment.setId("4297867");
request.setEstablishment(establishment);
requestDocument.setRequest(request);
requestData.setRequestDocument(requestDocument);
body.setRequestData(requestData);
envelope.setBody(body);
jaxbMarshallerForBase = jaxbContextForBase.createMarshaller();
OutputStream os = new ByteArrayOutputStream();
System.out.println();
// output pretty printed
// jaxbMarshallerForBase.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// jaxbMarshallerForBase.marshal(envelope, System.out);
// jaxbMarshallerForBase.marshal(envelope, os);
jaxbMarshallerForBase.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
jaxbMarshallerForBase.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// jaxbMarshallerForBase.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);
// get an Apache XMLSerializer configured to generate CDATA
XMLSerializer serializer = getXMLSerializer();
// marshal using the Apache XMLSerializer
SAXResult result = new SAXResult(serializer.asContentHandler());
System.out.println("*************");
jaxbMarshallerForBase.marshal(envelope, result);
System.out.println("--------------");
return null;
} catch (JAXBException ex) {
Logger.getLogger(GM_TravelRepublic.class.getName()).log(Level.SEVERE, null, ex);
} finally {
return null;
}
}
private static XMLSerializer getXMLSerializer() {
// configure an OutputFormat to handle CDATA
OutputFormat of = new OutputFormat();
// specify which of your elements you want to be handled as CDATA.
// The use of the ; '^' between the namespaceURI and the localname
// seems to be an implementation detail of the xerces code.
// When processing xml that doesn't use namespaces, simply omit the
// namespace prefix as shown in the third CDataElement below.
of.setCDataElements(new String[]{"^Request","^Authentication","^Establishment"});
// set any other options you'd like
of.setPreserveSpace(true);
of.setIndenting(true);
StringWriter writer = new StringWriter();
// create the serializer
XMLSerializer serializer = new XMLSerializer(of);
serializer.setOutputByteStream(System.out);
return serializer;
}
Here I am getting same xml , but without CDATA. My server is not accepting the request without CDATA.Please help.
Can you make the logic from this
imports
import org.dom4j.CDATA;
import org.dom4j.DocumentHelper;
sample code
public static String appendCdata(String input) {
CDATA cdata = DocumentHelper.createCDATA(input);
return cdata.asXML();
}
You need to create an custom adapter class which extends the XMLAdapter class.
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class CDATAAdapter extends XmlAdapter<String, String> {
#Override
public String marshal(String inStr) throws Exception {
return "<![CDATA[" + inStr + "]]>";
}
#Override
public String unmarshal(String v) throws Exception {
return inStr;
}
}
Inside your Java Bean or POJO define XMLJavaTypeAdapter on the string required in CDATA
#XmlJavaTypeAdapter(value=CDATAAdapter.class)
private String message;
By default, the marshaller implementation of the JAXB RI tries to escape characters. To change this behaviour we write a class that
implements the CharacterEscapeHandler.
This interface has an escape method that needs to be overridden.
import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;
m.setProperty("com.sun.xml.internal.bind.characterEscapeHandler",
new CharacterEscapeHandler() {
#Override
public void escape(char[] ch, int start, int length,
boolean isAttVal, Writer writer)
throws IOException {
writer.write(ch, start, length);
}
});
Secondly, it cn also be done via Eclipse MOXy implementation.
CDATA is character data, it looks like your server wants the part of the XML starting with Request to come in as text. It may be enough for you to create an XmlAdapter to convert the instance of Request to a String. The resulting characters will be escaped not in CDATA but this May fit your use case.
Then if you really need it as CDATA in addition to the XmlAdapter you can apply one of the strategies described in the link below:
How to generate CDATA block using JAXB?
From the setCDataElements method description in the Apache docs :
Sets the list of elements for which text node children should be output as CDATA.
What I think that means is, the children of the tem:requestDocument element should all be part of one single text chunk (and not xml elements by themselves) in order for this to work. Once you've done that, probably a simple
of.setCDataElements(new String[]{"tem^requestDocument"});
should do the trick.
Try it and let me know :)
I think that in your private static XMLSerializer getXMLSerializer() method you are setting wrong the CDATA elements, because your CDATA element is <tem:requestDocument> instead of Request Authentication and Establishment which are the content. Try with:
of.setCDataElements(new String[]{"tem^requestDocument","http://tempuri.org/^requestDocument","requestDocument"});
instead of:
of.setCDataElements(new String[]{"^Request","^Authentication","^Establishment"});
Hope this helps,
Your server is expecting <tem:requestDocument> to contain text, and not
a <Request> element. CDATA is really just helpful for creating hand-written
XML so you don't have to worry about escaping embedded XML. The thing is,
JAXB handles escaping just fine and if your server is a good XML citizen it should
treat properly escaped XML the same as XML in a CDATA block.
So, instead of adding a request element inside your requestDocument like
you do in:
requestDocument = objFact.createRequestDocument();
request = new RequestDocument.Request();
...
requestDocument.setRequest(request);
You should first use JAXB to marshal request into a properly escaped String
and set that sa the requestDocument value:
requestDocument = objFact.createRequestDocument();
request = new RequestDocument.Request();
...
String escapedRequest = marshal(request);
requestDocument.setRequest(escapedRequest);
Implementing marshal(request) is left as an exercise. ;)
I am currently using Play v1.2.3. I have an endpoint to which I want to send a json object which will be deserialized into a Java object. So, I have something that looks like this:
public class UserController extends Controller {
public static class FullName {
public String first;
public String last;
}
public static void putName( FullName name ) { ... }
}
##### routes
PUT /user/name UserController.putName
With that in place, I would hope to call the endpoint with the given javascript:
$.ajax({
type: "PUT",
data: { first: "Michael", last: "Bailey" },
url: "/user/name"
});
Unfortunately, with the above setup, it seems that play is not wanting to send the entire data object, but is instead attempting to populate two parameters (first and last). Is there a way to define the endpoint to consume the complete body directly, or does it have to be done by hand?
To cast the entire input body into a Model class:
public static void create(JsonObject body) {
CaseFolder caseFolder = new Gson().fromJson(body, CaseFolder.class);
caseFolder.user = getConnectedUser();
if(caseFolder.validateAndSave()) {
renderJSON(
new JSONSerializer()
.exclude("*.class")
.exclude("user")
.serialize(caseFolder));
} else
error();
}
Also, the above code takes the resulting Model object and serializes it back out to JSON as the response body.
If you want to just access certain fields within the JSON request, you can use:
public static void update(JsonObject body) {
try {
Long id = (long) body.get("id").getAsInt();
CaseFolder cf = CaseFolder.loadAndVerifyOwner(getConnectedUser(), id);
cf.number = body.get("number").getAsString();
cf.description = body.get("description").getAsString();
if(cf.validateAndSave())
ok();
else
error();
}
catch (NullIdException e) {error();}
catch (NotFoundException e) {notFound();}
catch (NotOwnerException e) {forbidden();}
catch (Exception e) {e.printStackTrace(); error();}
}
Play's action method parameter binding mechanism does not accept JSON. You need to bind it manually. In your example, the code could be something like:
public static void putName( String data ) {
FullName fname = new Gson().fromJSON(data, FullName.class);
...
}
Note, Gson is provided with play!framework distribution, so you are free to use it
With your settings play is expecting params with names "name.first" and "name.last" and you are sending "first" and "last". Try with this ajax post
$.ajax({
type: "PUT",
data: {
name: {
first: "Michael",
last: "Bailey"
}
},
url: "/user/name"
});