Getting an Array from a SOAP XML response in NodeJS - node.js

I'm working on a SOAP client in NodeJS. I've managed to consume using SOAPUi,the thing is that the response for the request I'm getting has an Array inside the body.
The XML request looks like this:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xe="http://www.w3.org/2001/04/xmlenc#">
<soap:Header>
<xe:AuthenticationHeader>
<!--Optional:-->
<xe:UserName>user</xe:UserName>
<!--Optional:-->
<xe:Password>password</xe:Password>
</xe:AuthenticationHeader>
</soap:Header>
<soap:Body>
<xe:GetRegistration>
<!--Optional:-->
<xe:id>123456</xe:id>
</xe:GetRegistration>
</soap:Body>
</soap:Envelope>
And the response XML looks like this:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetRegistrationResponse xmlns="http://www.w3.org/2001/04/xmlenc#">
<GetRegistrationResult>
<ErrorInQuery>false</ErrorInQuery>
<ErrorInfo>Success!</ErrorInfo>
<ArrayRegistration />
</GetRegistrationResult>
</GetRegistrationResponse>
</soap:Body>
</soap:Envelope>
What I'm trying to get from the response is that ArrayRegistration which will be processed by a decrypting process to give me the plain text results.
I managed to do it on C# but since the proyect needs to be done in NodeJS I have been struggling with it.
This is the code that worked for me in C#
public partial class RRegistration : object, System.ComponentModel.INotifyPropertyChanged {
private bool errorQuery;
private string errorInformation;
private Registration[] arrayRegistrationField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
public bool ErrorInQuery {
get {
return this.errorQuery;
}
set {
this.errorQuery = value;
this.RaisePropertyChanged("ErrorQuery");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=1)]
public string ErrorInformation {
get {
return this.errorInformation;
}
set {
this.errorInformation = value;
this.RaisePropertyChanged("ErrorInformation");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlArrayAttribute(Order=2)]
public Registration[] ArrayRegistration {
get {
return this.arrayRegistration;
}
set {
this.arrayRegistration = value;
this.RaisePropertyChanged("ArrayRegistration");
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName) {
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if ((propertyChanged != null)) {
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
Honestly any help would be greatly appreciated, in NodeJS I've used Node-Soap and easy-soap-request but I'm not sure how to get the Array that I need to send to the decrypting method.

At the end the xml that I was sending was missing the xe: notation in each of the custom tags.

Related

How to filter big XML nodes with some matching attribute

I have big XML files (between 500MB and 1GB) and I'm trying to filter them in order to keep only nodes with some specified attributes, in this case Prod_id.
I have about 10k Prod_id that I need to filter and currently XML contains about 60k items.
Currently I'm using XSL with node.js (https://github.com/fiduswriter/xslt-processor) but it's really slow (I never saw one of them finished in 30-40 minutes).
Is there a way to increase the speed of this process?
XSL is not a requirement, I can use everything.
XML Example:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<products>
<Product Quality="approved" Name="WL6A6" Title="BeBikes comfort WL6A6" Prod_id="BBKBECOMFORTWL6A6">
<CategoryFeatureGroup ID="10030">
<FeatureGroup>
<Name Value="Dettagli tecnici" langid="5"/>
</FeatureGroup>
</CategoryFeatureGroup>
<Gallery />
</Product>
...
<Product Quality="approved" Name="WL6A6" Title="BeBikes comfort WL6A6" Prod_id="LAL733">
<CategoryFeatureGroup ID="10030">
<FeatureGroup>
<Name Value="Dettagli tecnici" langid="5"/>
</FeatureGroup>
</CategoryFeatureGroup>
<Gallery />
</Product>
</products>
XSL I'm using
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="
products/Product
[not(#Prod_id='CEESPPRIVAIPHONE4')]
...
[not(#Prod_id='LAL733')]"
/>
</xsl:stylesheet>
Thanks
I solved using an approach similar to this answer https://stackoverflow.com/a/13851518/1152049
Thanks
private static void filter(InputStream fileInputStream, final Set<String> prodIdToExclude) throws SAXException, TransformerException, FileNotFoundException {
XMLReader xr = new XMLFilterImpl(XMLReaderFactory.createXMLReader()) {
private boolean skip;
#Override
public void startElement(String uri, String localName, String qName, Attributes atts)
throws SAXException {
if (qName.equals("Product")) {
String prodId = atts.getValue("Prod_id");
if (prodIdToExclude.contains(prodId)) {
skip = true;
} else {
super.startElement(uri, localName, qName, atts);
skip = false;
}
} else {
if (!skip) {
super.startElement(uri, localName, qName, atts);
}
}
}
public void endElement(String uri, String localName, String qName) throws SAXException {
if (!skip) {
super.endElement(uri, localName, qName);
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (!skip) {
super.characters(ch, start, length);
}
}
};
Source src = new SAXSource(xr, new InputSource(fileInputStream));
Result res = new StreamResult(new FileOutputStream("output.xml"));
TransformerFactory.newInstance().newTransformer().transform(src, res);
}

HTTP client with spring-integration

I need to write a simple HTTP client to make simple GET request and get JSON response using Spring integration.
Call fails with no message in exception: org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error.
I tried debugging Spring code and did it successfully till I have source code, namely till
in the method AbstractMessageHandler.handleMessage(Message message)
abstract handleMessageInternal(Message message) has been called which threw
exception saying that request with
URL = http://example.com?q={q}&authKey={authKey}&rows={rows}&page={page}&filter={filter}
failed. URL looked exactly as I quoted, i.e. expressions have not been executed.
Payload in the message was always as it should be - instance if ZtInput with correct field values.
Could anyone give me an idea what to do?
Here is spring-integration-zt-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xmlns:oxm="http://www.springframework.org/schema/oxm"
xsi:schemaLocation="http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http-2.1.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">
<int:channel id="InChannelZt"></int:channel>
<int:channel id="OutChannelZt"></int:channel>
<!-- Gateway Start -->
<int:gateway id="ZtGateway" default-request-timeout="5000" default-reply-timeout="5000"
default-request-channel="InChannelZt" service-interface="com.example.service.ZtService">
<int:method name="getResults" request-channel="InChannelZt" reply-channel="OutChannelZt" />
</int:gateway>
<int-http:outbound-gateway id="locationZtGateway"
request-channel="InChannelZt"
reply-channel="OutChannelZt"
url="${zt_url}?q={q}&authKey={authKey}&rows={rows}&page={page}&filter={filter}"
http-method="GET"
reply-timeout='5000'
expected-response-type="com.example.vo.ZtResponse">
<int-http:uri-variable name="q" expression="payload.getQ()"/>
<int-http:uri-variable name="authKey" expression="payload.getAuthKey()"/>
<int-http:uri-variable name="rows" expression="payload.getRows()"/>
<int-http:uri-variable name="page" expression="payload.getPage()"/>
<int-http:uri-variable name="filter" expression="payload.getFilter()"/>
</int-http:outbound-gateway>
and two classes mentioned in it:
import com.xxxx.vo.ZtInput;
import com.xxxx.vo.ZtResponse;
public interface ZtService {
ZtResponse getSearchResults(ZtInput ztInput);
}
Payload:
public class ZtInput {
private String q; //=pink
private String authKey = "baef7f8e39c53f852c8a14b7f6018b58";
private String rows="20";
private String page="1";
private String filter = "";
public ZtInputVO() {
}
public String getQ() {
return q;
}
public void setQ(String q) {
this.q = q;
}
public String getAuthKey() {
return authKey;
}
public void setAuthKey(String authKey) {
this.authKey = authKey;
}
public String getRows() {
return rows;
}
public void setRows(String rows) {
this.rows = rows;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public String getFilter() {
return filter;
}
public void setFilter(String filter) {
this.filter = filter;
}
}
The URI in the exception is the original (unexpanded URI); the expansion is performed into a different variable. (We should/will change that to log the expanded URI). But the bottom line is your server didn't like the expanded URI and returned a 500 internal server error.
You can use a network/tcp monitor (eclipse has one built in or you can use wireshark) to examine the actual URL sent to the server. You can also look at the server logs, if enabled.
Or, in the debugger, step down to line 415 (in the current source code - version 4.0.4) and examine realUri.
EDIT: The exception now includes the expanded URI (currently available in 4.0.5.BUILD-SNAPSHOT and 4.1.0.BUILD-SNAPSHOT).

Can we have space in a bean's id value in spring

I am getting this error:
org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 'duke duke' is not a valid value for 'NCName'.
I am using this spring-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
bean id="duke duke"
class="Juggler"/>
/beans>
My bean id's value has spaces in between.
This is my main class:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args)
{
ApplicationContext ctx=new ClassPathXmlApplicationContext("config/spring-config.xml");
Juggler jg=(Juggler)ctx.getBean("duke duke");
jg.perform();
}
}
However if I change the xsd in spring-config to spring-beans-3.1.xsd. I don't get this error. Why is it so??

Jersey Restful Web Service - MessageBodyProviderNotFoundException

I'm new to Java Web Services and I'm struggling with a basic problem.
After finding a bunch of outdated examples I managed to get something working with XML however the same code wont work when I ask it to return JSON.
Initially I thought it was a missing JSON formatter but JAXB should be taking care of the conversion from POJO to JSON so I don't believe that's the problem.
The error being thrown within Tomcat is:
javax.servlet.ServletException: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class resttest.model.Todo, genericType=class resttest.model.Todo
WEB.XML
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>testtest</display-name>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>resttest.jaxb;resttest.model</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Todo.java
package resttest.model;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Todo {
public Todo(){};
private String summary;
private String description;
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
TodoResource.Java
package resttest.jaxb;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import resttest.model.Todo;
#Path("/todo")
public class TodoResource {
#GET
#Produces("application/json")
public Todo getTodo() {
Todo todo = new Todo();
todo.setSummary("This is my first todo");
todo.setDescription("This is my first todo");
return todo;
}
}
Any ideas why the JSON isn't being returned and the error thrown?
I searched a lot of the responses myself and this is what I ended up doing. In addition to your TodoResource class, you need a class that extends Application, and class such as the MOXyJsonContextResolver class below to implement the ContextResolver interface. These help define the Jersey context along with a selected Json converter and optional customizations to the Json output. Put the classes in the same package as your resource class and Jersey will find it. MOXy is now the default for Jersey (I use 2.5.1) and the only json converter that I could get working without receiving your error. Also, make sure you have the MOXy jar included in your build or maven pom.xml (jersey-media-moxy-2.5.1.jar).
Note: nothing is in my application's web.xml. That was in the older documentation examples and not needed as of Jersey 2.5.1.
#javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {
public ApplicationConfig() {
this.initMethods();
}
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
addRestResourceClasses(resources);
return resources;
}
private void initMethods() {
try {
...some classes you might need instantiated, etc, for your resource class
} catch (Exception e) {
e.printStackTrace();
}
}
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(MOXyJsonContextResolver.class);
}
}
And here is the MOXyJsonContextResolver.class that I used to customize the Json response:
public class MOXyJsonContextResolver implements ContextResolver<MoxyJsonConfig> {
private final MoxyJsonConfig config;
public MOXyJsonContextResolver() {
config = new MoxyJsonConfig()
.setAttributePrefix("")
.setValueWrapper("value")
.property(JAXBContextProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
}
#Override
public MoxyJsonConfig getContext(Class<?> objectType) {
return config;
}
}
You forgot to add the attribute: #XmlAccessorType(XmlAccessType.FIELD)
Example:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Todo {
...
You have mentioned #XmlRootElement at class level in todo class. #XmlRootElement is only required if you want to produce your response in xml format, and also provide #Path at method level in TodoResource class, its a good practice.
mention #Produces(MediaType.APPLICATION_JSON) at method level. Hope this will work for you!

JSF - custom component, problem with expression for attribute

I want to create custom component with attribute "title" that can have expression but I get this error:
Unable to convert string "#{myBean.text}" to class "javax.el.ValueExpression" for attribute "title": Property Editor not registered with the PropertyEditorManager
Caused by:
org.apache.jasper.JasperException - Unable to convert string "#{myBean.text}" to class "javax.el.ValueExpression" for attribute "title": Property Editor not registered with the PropertyEditorManager
My classes:
<d:ticker title="#{myBean.text}">
<f:verbatim>Hello JSF Custom Component</f:verbatim>
</d:ticker>
MyBean.java
public class MyBean {
private String text = "TITLE!!!!";
public String getText() {
return text;
}
}
TickerTag.java
private ValueExpression title = null;
public void setTitle(ValueExpression title)
{
this.title = title;
}
protected void setProperties(UIComponent component) {
super.setProperties(component);
if (title != null) {
if (!title.isLiteralText()) {
component.setValueExpression("title", title);
} else {
component.getAttributes().put("title",title.getExpressionString());
}
}
taglib.tld
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee web-jsptaglibrary_2_1.xsd">
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>d</short-name>
<uri>http://jsftutorials.com/</uri>
<tag>
<name>ticker</name>
<tag-class>ticker.TickerTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>title</name>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
anybody see the problem?
I encountered the same problem, and was able to solve it by including the deferred-value tag in my taglib.tld file. It's required when the component has an attribute that can be set with an EL expression. The 'type' tag is the type that the EL expression should evaluate to.
taglib.tld:
<tag>
<name>CustomComponent</name>
<tag-class>com.test.components.CustomComponent</tag-class>
<attribute>
<name>someAttribute</name>
<description>The custom attribute</description>
<deferred-value>
<type>java.lang.String</type>
</deferred-value>
</attribute>
</tag>

Resources