Attribute “xmlns:ns2” was already specified for element …

Hi, all:

It is surely cold here in northeast right now. January does have its own teeth! ūüė¶

I am posting something I found during a SOAP Webservice invocation, which I hope can help you save some time in your development.

There was an error message when a SOAP client gets and parses a response from a SOAP Webservice and it started to complain about something like:

Attribute “xmlns:ns2” was already specified for element …..

It puzzled me at the first glance because in the actual captured SOAP response, the element the error is complaining about has no prefix “ns2” at all. After a couple days of not knowing what is wrong, I finally noticed that the element in the SOAP response has an empty seemingly benign namespace attribute:

xmlns=””

This one is actually the culprit! The error is actually indicating that the element SHOULD have a namespace based on the WSDL/XSD (in this case it was designed to have namespace of http://www.w3.org/2005/08/addressing). ¬†The empty namespace xmlns=”” triggered the error during parsing! ¬†After fixing at the server side to ensure the SOAP response has the correct namespace designated for the element as¬†http://www.w3.org/2005/08/addressing, the problem went away!

Now, the question remains why the error is complaining about the xmlns:ns2? i.e. where does the ns2 prefix come from? It is actually quite obvious when I look at the whole SOAP response. The ns2 prefix is mapped to the URI http://www.w3.org/2005/08/addressing at the root element of the SOAP response, thus, the error is referring to that prefix throughout the whole document.

Next time when we see similar error message to this, we can easily find out what namespace the element of concern should have and enforce it to be assigned correctly.

Stay warm!

-Tony

Advertisements

log4j AsyncAppender missing class/method/line numbers???

Hi, There:

This post is about Log4j again. We keep getting three ?:?:? in our log4j logging files for the Class name:Method name and Line Number. Basically we want to have this %F:%M:%L  in the ConversionPattern but got no information back but ?:?:?.

The reason is that we use org.apache.log4j.AsyncAppender for better performance. This AsyncAppender references to org.apache.log4j.RollingFileAppender. Because AsyncAppender uses another thread when write the logging event to the FileAppender, the location information about class/method/line are lost in the FileAppender.

The simple fix to this is to set the boolean attribute LocationInfo to true, it will then preserve the calling thread information from the AsyncAppender to the next FileAppender.

<appender name=”AsyncAppender” class=”org.apache.log4j.AsyncAppender”>
¬† ¬†<appender-ref ref=”FileAppender” />
¬† ¬†<param name=”LocationInfo” value=”true”/>
</appender>

The log file now have all the class/method/line number we can use during debugging.

Cheers!

 

-TY

 

Adding system environment properties to log4j filename

Hi, Happy Friday!

The holiday is just around corner! ¬†I feel like posting something before the holiday is really here. And it happens I do have something worth posting. ūüôā

This week we found that in a cluster environment, log4j may encounter an issue with writing log entries to FileAppender. The problem is essentially that when multiple nodes from the same cluster are trying to write to the same log file, the competing threads can cause some of the events to be dropped without being written to the file. The losing rate depends on how heavy the logging events.

We found a way to mitigate this issue by adding a hostname to the logging filename. This way, each node will be writing to its own logging file, avoiding IO contention.

How to achieve this involves two steps. First, adding a system variable in your application startup process, such as:

System.setProperty(“HostName“, InetAddress.getLocalHost().getHostName());¬†

Then reference this HostName system variable in your Log4j.xml configuration file, something like the following:

<appender name=”FileAppender” class=”org.apache.log4j.RollingFileAppender”>
¬†<param name=”file”¬†value=”/tmp/logs/app_${HostName}.log” />
¬†<param name=”MaxFileSize” value=”1024KB” />
¬†<param name=”MaxBackupIndex” value=”30″ />
¬†<param name=”Threshold” value=”DEBUG” />
¬†<layout class=”org.apache.log4j.PatternLayout”>
¬† <param name=”ConversionPattern” value=”%5p [%d] [%t] (%F:%M:%L) – %m%n” />
 </layout>
</appender>

The application will write logging entries to the logging file with an actual host name in its filename. Another beautiful side effect of this is that one can quickly tell where the logging event is originated from, which often provides valuable information about the host in the cluster.

Of course, if you want to add more environment variables besides the HostName, it can be done in similar fashion. Also, the variables don’t need to be in the filename, it can be in the content of the logging message.

Cheers and have a happy holiday season!

-T. Y.

 

 

 

JAX-WS error: java.util.HashMap cannot be cast to com.sun.xml.ws.transport.Headers

Happy Black Friday!

We are upgrading our JEE application from Weblogic 11g to 12c. On one of our staging servers, we got this error:

Java agent causing error: Caused by: java.lang.ClassCastException: java.util.HashMap cannot be cast to com.sun.xml.ws.transport.Headers

This error, however, doesn’t happen in our development environment. We have scratched our heads for many days for this issue. From googling, this link comes up at the top:¬†http://www.ca.com/us/services-support/ca-support/ca-support-online/knowledge-base-articles.tec1210346.html¬†This apparently indicates there are some jax-ws libraries that are polluting our environment in that staging server. Following this thought, we have tuned and reconfigured many ways to let the application use the jax-ws jar we want it to, in vain.

Eventually, a server admin found out that the Introscope Wily that is installed on the staging server is the culprit that contaminated the Java Classpath for the jax-ws. When we go back to the link above, that’s of course from Wily’s vendor CA! ! The fix is easy just follow the link above to change the introscope properties to what’s described in that link.

It’s ironic that the link is from CA at the first place, and it didn’t ring the bell for me that the issue was caused by Wily in the first place.

Cheers and happy holidays!

-TY

Element Object doesn’t support property or method ‘remove’ In IE

Hi, There:

Happy Thanksgiving!  Drop a few a lines here to record an IE issue, from a version of angularJS datetime picker. The error only happens in IE:

Object doesn’t support property or method ‘remove’.¬†The Code related were something like this:

el.remove();

It is due to that IE doesn’t support remove() function for DOM element. ¬†But if you change to the following, things work much better!

el.parentNode && el.parentNode.removeChild(el);

Hopefully this will help anyone is scratching their heads for this IE issue that doesn’t happen in Chrome or Firefox.

Best,

-Tony

 

 

Custom DataSource for DataHandler: how to get byte[] into DataHandler

Hi there:

Happy Friday!

We use javax.activation.DataHandler Routinely in SOAP Webservice invocation. However, when DataHandler constructs with DataSource, it only comes in with two types, FileDataSource, URLDataSource. A lot of times in production applications, neither is useful. For example, in memory data in byte[] or other forms cannot be used readily with these two types of DataSource. This can be easily solved by implementing your own DataSource. Here is an example that you can use

 

public class MyDataSource implements DataSource {

private InputStream is;
private String name, contentType;

@Override
public String getContentType() {
return contentType;
}
public void setContentType(String ct){
this.contentType = ct;
}

@Override
public InputStream getInputStream() throws IOException {
return is;
}

public void setInputStream(InputStream is){
this.is = is;
}

@Override
public String getName() {
return name;
}
public void setName(String name){
this.name = name;
}

@Override
public OutputStream getOutputStream() throws IOException {
// TODO Auto-generated method stub
return null;
}
}

 

To use the DataSource, inject byte[] into it before instantiate DataHandler with the DataSource.

 

MyDataSource ds = new MyDataSource ();

byte[] data = ¬†… ;

InputStream is =  new ByteArrayInputStream(data);

ds.setInputStream(is);

ds.setContentType(“application/octet-stream”);

ds.setName(“some content¬†name”);

DataHandler dataHandler = new DataHandler(ds);

 

DataHandler will then fetch the data from the underlying InputStream from the Custom DataSource.

Cheers!

 

-Tony

ApacheXMLDSig Signature Provider Not found

Hello, Happy Friday!  It has been a heck of week or two. Finally the dust has come down and I have enjoyed a couple of relatively quiet days of coding.

During this period, this issue bothered me for a couple of days and just found a solution to it.

I am using WSSecSignature to sign SOAP request and everything works fine in Maven tests until I deployed this to Tomcat 8 under JDK8. The error I got is always something like ApacheXMLDSig not found, no matter how I tweaked it.

javax.xml.crypto.NoSuchMechanismException: java.security.NoSuchAlgorithmException: class configured for XMLSignatureFactory (provider: ApacheXMLDSig) cannot be found

I feel Tomcat is doing something funny under the hood so the default ApacheXML Digital Signer is not visible to my WSSecSignature, maybe it is due to some Classpath loader structure?

I had to eventually explicitly specify the Digital Signer as below:

System.setProperty(“jsr105Provider”, “org.jcp.xml.dsig.internal.dom.XMLDSigRI”);

This ensures I know what Signer is to be used from the Santuario package and it works without any failures in Tomcat.

Cheers!