Get parameters from soap request - java

my app receive a soap request; this is an example:
<SOAP-ENV:Body>
<ns1:authorize>
<params>AppSender</params>
<params>url.appsender.local</params>
<params>GET /applic/ HTTP/1.1</params>
<params>2017-01-4T09:38:00.601Z#NCODER08F839F#myapp.sch</params>
<params>/applic/</params>
<params>2.0.00</params>
<params></params>
<params>d1c714fe-cae1-4150-934f-bb3e61ad85f2</params>
<params>Authentication-Instant</params><params>2017-01-</params>
<params>fiscalCode</params><params>NTSDNT80R085454</params>
<params>userName</params><params>user</params>
<params>levelVerification</params><params>10</params>
<params>AuthenticationType</params><params>BASIC</params>
</ns1:authorize>
Can i have an example that i take this request and i set the value of the tag "params" in a JavaBean???
Thank you

You must process the request with some java library for XML processing.
Example:
org.w3c.dom.Document doc = null;
doc = builder.parse(request);
doc.getDocumentElement().normalize();
org.w3c.dom.Node nodeRoot = doc.getFirstChild();
if(nodeRoot.getNodeName().equals("authorize")) {
... doc.getElementsByTagName("params")...;

You can do it with JAXB, here you have more info ...
http://theopentutorials.com/examples/java/jaxb/generate-java-class-from-xml-schema-in-eclipse-ide/

Related

Java DOM: transforming a node to a root element

I have the following XML file (SOAP response) that I'm trying to map to a Java object :
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:AffaireByTiersResponse xmlns:ns2="http://service.hibernate.com/">
<Affaire>
<code_produit>Cred</code_produit>
<id>1</id>
<montant_fin>2000.0</montant_fin>
<id_tier>1</id_tier>
</Affaire>
<Affaire>
<code_produit>Cred</code_produit>
<id>2</id>
<montant_fin>25000.0</montant_fin>
<id_tier>1</id_tier>
</Affaire>
</ns2:AffaireByTiersResponse>
</soap:Body>
</soap:Envelope>
in order to marshall the file I need to keep only the tag <AffaireByTiersResponse> as root element and change its name to <Affaires>.
What is the best way to do this?
Extracting the underlying content from the SOAP envelop can be done using javax.xml.soap.MessageFactory.
String example = new String(Files.readAllBytes(Paths.get("input.xml")), StandardCharsets.UTF_8);
SOAPMessage message = MessageFactory.newInstance().createMessage(null,
new ByteArrayInputStream(example.getBytes()));
Document doc = message.getSOAPBody().extractContentAsDocument();
Element root = doc.getDocumentElement();
The root node can then be renamed
doc.renameNode(root, root.getNamespaceURI(), "Affaires");
and this document can then be passed into the JAXB unmarshaller
Unmarshaller unmarshaller = JAXBContext.newInstance(Affaires.class).createUnmarshaller();
Affaires farm = (Affaires) unmarshaller.unmarshal(doc);

solr response in xml format

I am trying to query Solr using certain fields and I want the response in XML format. Somehow I am not able to get the response in XML format even though I have set the parser to XMLResponseParser. Please check the code and let me know what is wrong in here:
HttpSolrServer solr = new HttpSolrServer(urlString);
String queryString ="*:*";
SolrQuery query = new SolrQuery(queryString);
query.setQuery(queryString);
query.setFields("type", "typestring");
query.addFilterQuery("id");
query.setStart(0);
query.setRows(100);
solr.setParser(new XMLResponseParser());
QueryResponse resp = solr.query(query);
SolrDocumentList results = resp.getResults();
for (int i = 0; i < results.size(); ++i) {
// I need this results in xml format
System.out.println(results.get(i));
}
Your code is using SolrJ as a Solr client. It's precisely done to avoid dealing with XML responses, and it provides a clean way to get Solr results back in your code as objects.
If you want to get the raw xml response, just pick up any java HTTP Client, build the request and send it to Solr. You'll get a nice XML String...
NOTE : You can use ClientUtils.toQueryString(SolrParams params, boolean xml) to build the query part of your URL
As Grooveek already wrote, SolrJ is intended to take XML parsing away from you as a user of the library. If you want to see the XML, you need to fetch the response on your own.
SolrQuery query = new SolrQuery("*:*");
// set indent == true, so that the xml output is formatted
query.set("indent", true);
// use org.apache.solr.client.solrj.util.ClientUtils
// to make a URL compatible query string of your SolrQuery
String urlQueryString = ClientUtils.toQueryString(query, false);
String solrURL = "http://localhost:8080/solr/shard-1/select";
URL url = new URL(solrURL + urlQueryString);
// use org.apache.commons.io.IOUtils to do the http handling for you
String xmlResponse = IOUtils.toString(url);
// have a look
System.out.println(xmlResponse);

How to add child element in soap header in java

How to add child element in soap header in java spring webservice.
I have tried two approach but nothing is working please suggest me what need to be done?
first approach :-
soapHeaderString.append("<tem:Culture>en_Us</tem:Culture><tem:AgentCode>PumpkinSafari</tem:AgentCode><tem:PartnerID></tem:PartnerID><tem:Password>PMP22#in</tem:Password>");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
// Here we create a Source Tree
StringSource stringSource = new StringSource(soapHeaderString.toString());
transformer.transform(stringSource, soapHeader.getResult());
but it is giving me error
The prefix "tem" for element "tem:Culture" is not bound.
2nd Approach :-
SoapHeaderElement headerElement=soapMessage.getSoapHeader().addHeaderElement(new QName("http://tempuri.org/", "SOAPHeaderAuth","tem"));
headerElement.setText(soapHeaderString.toString());
It produce unescaped sequqnce so service provider give error as it was not able to understand the request.
Please help me what need to be done to solve the problem.
Yes, in my case too it prompts the same error, The prefix "username" for element "wsse:username" is not bound. I tried doing everything to add namespace declaration. But, it doesn't worked!
"Finally", I was able to do it last night with a workaround, converting some way from Spring org.springframework.ws.soap.SoapHeader to javax.xml.soap.SOAPHeader. And no issues now!
SOAPMessage soapMessage = ((SaajSoapMessage) message).getSaajMessage();
SOAPHeader header = soapMessage.getSOAPHeader();
SOAPHeaderElement security = header.addHeaderElement(new QName(SCHEMA, "Security", SCHEMA_PREFIX));
SOAPElement usernameToken = security.addChildElement("UsernameToken", SCHEMA_PREFIX);
SOAPElement usernameElement = usernameToken.addChildElement("Username", SCHEMA_PREFIX);
SOAPElement passwordElement = usernameToken.addChildElement("Password", SCHEMA_PREFIX);
usernameElement.setTextContent(username);
passwordElement.setTextContent(password);
Through this I was able to add namespace declarations to spring soap header child elements!
JAX-WS Users
I would recommend using a message handler:
http://www.javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-web-service-client
Spring Web Services Users
A similar concept exists:
http://arcanetechnotes.blogspot.com/2008/12/modifying-soap-headers-with-spring-web.html
The question states that it cannot understand the tem namespace, so perhaps register the namespace in the header:
soapHeader.addNamespaceDeclaration("tem", "http://whatever.namespace.com/");
Use "header=true" property in webparam
Like
#WebMethod(operationName = "someMethod")
public String someMethod(#WebParam(name = "yourBeanObj") YourBeanObjClass yourBeanObj,
#WebParam(header = true, mode = WebParam.Mode.IN, name = "username") String userName,
#WebParam(header = true, mode = WebParam.Mode.IN, name = "password") String pwd) {
//todo stuff
}
As per above example "yourBeanObj" wil be added into soap body, "username" and "password" are add in soap header.

XML Data is sorted

I am constructing XML code using Java. See my code snippet.
Document document = null;
String xml = "";
ReportsDAO objReportsDAO = null;
try
{
logger.info("Getting XML data for Consumable Report Starts...");
objReportsDAO = new ReportsDAO();
List consumableDTOLst = objReportsDAO.getConsumableData(issuedBy, issuedTo, employeeType, itemCode, itemName, className, transactionFromDate, transactionToDate, machineCode, workOrderNumber, jobName, customerId);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.newDocument();
Element rootElmnt = (Element) document.createElement("items");
document.appendChild(rootElmnt);
Element elmt = null;
ConsumableDTO objConsumableDTO = null;
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
for (int i = 0; i < consumableDTOLst.size(); i++)
{
objConsumableDTO = (ConsumableDTO)consumableDTOLst.get(i);
elmt = (Element) document.createElement("item");
elmt.setAttribute("IssuedBy", objConsumableDTO.getIssuedBy());
elmt.setAttribute("IssuedTo", objConsumableDTO.getIssuedTo());
elmt.setAttribute("EMPLOYECADRE", objConsumableDTO.getEmployeeType());
elmt.setAttribute("ITEMCODE", objConsumableDTO.getItemCode());
elmt.setAttribute("ITEMNAME", objConsumableDTO.getItemName());
elmt.setAttribute("ITEMCLASS", objConsumableDTO.getClassName());
elmt.setAttribute("DATE", sdf.format(objConsumableDTO.getTransactionDate()));
elmt.setAttribute("machineCode", objConsumableDTO.getMachineCode());
elmt.setAttribute("JOB", objConsumableDTO.getJobName());
elmt.setAttribute("WORKORDERNUMBER", objConsumableDTO.getWorkOrderNumber());
elmt.setAttribute("CustomerName", objConsumableDTO.getCustomerName());
elmt.setAttribute("RoleName", objConsumableDTO.getGroupName());
elmt.setAttribute("VendorName", objConsumableDTO.getVendorName());
elmt.setAttribute("QTY", String.valueOf(Math.abs(objConsumableDTO.getQuantity())));
elmt.setAttribute("unitDescription", objConsumableDTO.getUnitDescription());
elmt.setAttribute("RATEPERQTY", String.valueOf(objConsumableDTO.getRate()));
elmt.setAttribute("AMOUNT", String.valueOf(objConsumableDTO.getAmount()));
rootElmnt.appendChild(elmt);
}
The problem is all the attributes are sorted automatically. How to restrict it?
For eg,
<empdetails age="25" name="john"/>
but i want
<empdetails name="john" age="25"/>
Please suggest some idea.
Thanks,
Duplicate: Order of XML attributes after DOM processing
From the accepted answer:
Look at section 3.1 of the XML
recommendation. It says, "Note that
the order of attribute specifications
in a start-tag or empty-element tag is
not significant."
If a piece of software requires
attributes on an XML element to appear
in a specific order, that software is
not processing XML, it's processing
text that looks superficially like
XML. It needs to be fixed.
If it can't be fixed, and you have to
produce files that conform to its
requirements, you can't reliably use
standard XML tools to produce those
files.
Credit to Robert Rossney
XML attributes are not ordered. How they're output is dependent on the XML output mechanism you use.
Consequently you could write your on output mechanism, but you shouldn't rely on any consumer to consume them in an ordered fashion. If you want/need ordering, you should instead specify a sequence of XML elements below this node.

NamespaceContext and using namespaces with XPath

Resolving an xpath that includes namespaces in Java appears to require the use of a NamespaceContext object, mapping prefixes to namespace urls and vice versa. However, I can find no mechanism for getting a NamespaceContext other than implementing it myself. This seems counter-intuitive.
The question: Is there any easy way to acquire a NamespaceContext from a document, or to create one, or failing that, to forgo prefixes altogether and specify the xpath with fully qualified names?
It is possible to get a NamespaceContext instance without writing your own class. Its class-use page shows you can get one using the javax.xml.stream package.
String ctxtTemplate = "<data xmlns=\"http://base\" xmlns:foo=\"http://foo\" />";
NamespaceContext nsContext = null;
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLEventReader evtReader = factory
.createXMLEventReader(new StringReader(ctxtTemplate));
while (evtReader.hasNext()) {
XMLEvent event = evtReader.nextEvent();
if (event.isStartElement()) {
nsContext = ((StartElement) event)
.getNamespaceContext();
break;
}
}
System.out.println(nsContext.getNamespaceURI(""));
System.out.println(nsContext.getNamespaceURI("foo"));
System.out.println(nsContext
.getNamespaceURI(XMLConstants.XMLNS_ATTRIBUTE));
System.out.println(nsContext
.getNamespaceURI(XMLConstants.XML_NS_PREFIX));
Forgoing prefixes altogether is likely to lead to ambiguous expressions - if you want to drop namespace prefixes, you'd need to change the document format. Creating a context from a document doesn't necessarily make sense. The prefixes have to match the ones used in the XPath expression, not the ones in any document, as in this code:
String xml = "<data xmlns=\"http://base\" xmlns:foo=\"http://foo\" >"
+ "<foo:value>"
+ "hello"
+ "</foo:value>"
+ "</data>";
String expression = "/stack:data/overflow:value";
class BaseFooContext implements NamespaceContext {
#Override
public String getNamespaceURI(String prefix) {
if ("stack".equals(prefix))
return "http://base";
if ("overflow".equals(prefix))
return "http://foo";
throw new IllegalArgumentException(prefix);
}
#Override
public String getPrefix(String namespaceURI) {
throw new UnsupportedOperationException();
}
#Override
public Iterator<String> getPrefixes(
String namespaceURI) {
throw new UnsupportedOperationException();
}
}
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
xpath.setNamespaceContext(new BaseFooContext());
String value = xpath.evaluate(expression,
new InputSource(new StringReader(xml)));
System.out.println(value);
Neither the implementation returned by the StAX API nor the one above implement the full class/method contracts as defined in the doc. You can get a full, map-based implementation here.
I've just been working through using xpath and NamespaceContexts myself. I came across a good treatment of the issue on developerworks.
I found a convenient implementation in "Apache WebServices Common Utilities" called NamespaceContextImpl.
You can use the following maven dependency to obtain this class:
<dependency>
<groupId>org.apache.ws.commons</groupId>
<artifactId>ws-commons-util</artifactId>
<version>1.0.1</version>
</dependency>
I've use it in the following manner (I know its built for sax, but after reading the code, its o.k):
NamespaceContextImpl nsContext = new NamespaceContextImpl();
nsContext.startPrefixMapping("foo", "my.name.space.com");
You don't need to called endPrefixMapping.
If you are using the Spring framework you can reuse their NamespaceContext implementation
org.springframework.util.xml.SimpleNamespaceContext
This is a similar answer like the one from Asaf Mesika. So it doesn't give you automatic a NamespaceContext based on your document. You have to construct it yourself. Still it helps you because it at least gives you an implementation to starts with.
When we faced a similar problem, Both the spring SimpleNamespaceContext and the "Apache WebServices Common Utilities" worked. We wanted to avoid to the addition jar dependency on Apache WebServices Common Utilities and used the Spring one, because our application is Spring based.
If you are using Jersey 2 and only have a default XML namespace (xmlns="..."), you can use SimpleNamespaceResolver:
<?xml version="1.0" encoding="UTF-8"?>
<Outer xmlns="http://host/namespace">
<Inner />
</Outer>
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
docBuilderFactory.setNamespaceAware(true);
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document document = docBuilder.parse(new File("document.xml"));
String query = "/t:Outer/t:Inner";
XPath xpath = XPathFactory.newInstance().newXPath();
String xmlns = document.getDocumentElement().getAttribute("xmlns");
xpath.setNamespaceContext(new SimpleNamespaceResolver("t", xmlns));
NodeList nodeList = (NodeList) xpath.evaluate(query, document, XPathConstants.NODESET);
//nodeList will contain the <Inner> element
You can also specify xmlns manually if you want.

Categories