avoid null pointer excpetion while parsing the xml - java

This is my xml to parse
<metadata>
<groupId>org.chromium</groupId>
<artifactId>chromedriver-win32</artifactId>
<versioning>
<release>2.14</release>
<versions>
<version>2.14</version>
</versions>
<lastUpdated>20150610112540</lastUpdated>
</versioning>
</metadata>
While I am trying to parse the above XML, I am getting NullPointerException even though I have handled the null check. Below is the code
private String getVersionFromNode(Element eElement) {
String version = null;
// Get the latest version
String tagName = "latest";
try {
version = eElement.getElementsByTagName(tagName).item(0).getTextContent();
// If latest version is not available take the release
// version
if ( version.isEmpty() || null == version || "null" == version) {
tagName = "release";
version = eElement.getElementsByTagName(tagName).item(0).getTextContent();
}
}
catch (NullPointerException e) {
System.out.println("not able to parse " + tagName + " tag " + e.getMessage());
}
return version;
}
When the version is null, it should enter in below block.
if ( version.isEmpty() || null == version || "null" == version) {
tagName = "release";
version = eElement.getElementsByTagName(tagName).item(0).getTextContent();
}
What should be solution for this problem?

Your String tagName is "latest" and in your xml file, there is no element named latest and so your version remains null and therefore a NullPointerException is generated when the code:
version.isEmpty()
is executed in your if statement. Because version is null. And your code tries to check if null is empty. Which it cannot. And so, a NullPointerException is generated here.
To handle this situation, first check if version is null. Secondly check if the string version is equal to string "null". And thirdly check if it is empty. So change the sequence of conditions in your if statement from:
if ( version.isEmpty() || null == version || "null" == version)
to
if (null == version || "null" == version || version.isEmpty())
By the way, as a side tip, use:
"null".equals(version)
rather than
"null" == version

Change your condition
if ( version.isEmpty() || null == version || "null" == version)
to
if (null == version || "null".equals(version) || version.isEmpty())

When chaining together method calls, you risk a NullPointerException at every step. For example, in your line
version = eElement.getElementsByTagName(tagName).item(0).getTextContent();
there are 4 opportunities for a NullPointerException:
if eElement is null, trying to call getElementsByTagName(tagName)
if calling getElementsByTagName(tagName) when tagName is null
if getElementsByTagName(tagName) returns null, trying to call item(0)
if item(0) returns null, trying to call getTextContent()
Not all of these will be possible in your code because tagName is specified, but you should always beware.
An alternative approach for your problem would be to use XPath
See also How to read XML using XPath in Java

Related

Problem with NullValueCheckStrategy.ALWAYS (mapstruct 1.3.1)

After upgrading mapstruct from 1.2.0 to 1.3.1 I noticed that the annotation #Mapper(nullValueCheckStrategy=NullValueCheckStrategy.ALWAYS) in not in effect.
Is it a bug of new mapstruct version?
Example:
The code below:
String id = getTestId( testId);
if ( id != null ) {
testCase.setTestCaseId( id );
}
else {
testCase.setTestCaseId( null );
}
while the right is:
String id = getTestId( testId);
if ( id != null ) {
testCase.setTestCaseId( id );
}
The behaviour has been made more consequent with the advent of NullValuePropertyMapping. I think that was mentioned in the release notes as well. Checkout the documentation:
1: update methods (#MappingTarget)
https://mapstruct.org/documentation/stable/reference/html/#mapping-result-for-null-properties
2: regular (non update) methods
https://mapstruct.org/documentation/stable/reference/html/#checking-source-property-for-null-arguments

Apache Camel header set to null after performing a get

What could cause a header to be set to null as a result of getting it from the exchange?
My current workaround is to set the header again after reading but this is terribly hacky.
Example:
String header = exchange.getIn().getHeader("headerKey", String.class);
String theSameHeader = exchange.getIn().getHeader("headerKey", String.class);
System.out.printf("header is %s.\n", (header == null) ? "null" : "not null");
System.out.printf("theSameHeader is %s.\n", (theSameHeader == null) ? "null" : "not null");
Output:
header is not null.
theSameHeader is null.
Are you header a String type, it does however smell as if the header type is streaming based, and then you end up as what is described in this FAQ:
http://camel.apache.org/why-is-my-message-body-empty.html

NoraUI - "Cannot infer Type argument" error using Result.Warning<> in a custom step

I need to raise a warning during one of my scenario but i don't stop to have this error appearing : "Cannot infer type arguments for Result.Warning<>"
I actually tried to raise the Warning the same way i was raising Failure until now :
new Result.Warning<>(targetKey, Messages.format(TaroMessages.WARNING_RESOURCES_VALUE_DIFFERENCE_AFTER_REAFFECTATION, existing_value, new_value), true, oscarAccesClientPage.getCallBack());
The custom step i am using it inside is the following : I'm trying to go over a list of Element and checking that the existing value of them is the same or not as the one saved before.
protected void checkXyResourcesValue(Integer xyIterator, List<WebElement> elements, String keyParameter) throws TechnicalException, FailureException {
try {
Integer resIterator = 1;
for(WebElement element : elements) {
String targetKey = "XY" + xyIterator + "RES" + resIterator + keyParameter;
String new_value = element.getAttribute(VALUE) != null ? element.getAttribute(VALUE) : element.getText();
String existing_value = Context.getValue(targetKey) != null ? Context.getValue(targetKey) : targetKey;
if (new_value != existing_value) {
new Result.Warning<>(targetKey, Messages.format(TaroMessages.WARNING_RESOURCES_VALUE_DIFFERENCE_AFTER_REAFFECTATION, existing_value, new_value), true, oscarAccesClientPage.getCallBack());
}
resIterator++;
}
} catch (Exception e) {
new Result.Failure<>(e.getMessage(), Messages.format(TaroMessages.FAIL_MESSAGE_ACCES_CLIENT_XY_CHECK_RESOURCES_VALUE, keyParameter, xyIterator), true, oscarAccesClientPage.getCallBack());
}
}
For the method to check and saved value I actually inspired myself for the piece of code from NoraUI to save a value on Context or read it from.
I'm using Eclipse Luna 4.4.2 and i try to compile using JDK1.8.0_131.
It may be more related to me not knowing how this work in Java than a real problem so thank you in advance for your help or insights. Don't hesitate to ask if you need more information on the piece of code or the context.
new Result.Warning<>(targetKey, Messages.format(TaroMessages.WARNING_RESOURCES_VALUE_DIFFERENCE_AFTER_REAFFECTATION, existing_value, new_value), true, 0);
use 0 if you do not use any Model (data serialized) or use id of your Object in the serial.

AllRowsReader class with token range

This is an example of using AllRowsReader class from Astyanax recipes:
reader = new AllRowsReader.Builder<>(keyspace, columnFamily)
.withPageSize(1000)
.withConcurrencyLevel(10)
.withPartitioner(null)
.withConsistencyLevel(ConsistencyLevel.CL_ONE)
.withIncludeEmptyRows(false)
.withTokenRange(startToken, endToken)
.forEachRow(new Function<Row<String, String>, Boolean>() {
#Override
public Boolean apply(#Nullable Row<String, String> row) {
startToken = keyspace.getPartitioner().getTokenForKey(row.getRawKey());
// some other statements
return true;
}
})
.build();
reader.call();
where
startToken = keyspace.getPartitioner().getMinToken();
lastToken = keyspace.getPartitioner().getMaxToken();
If to run AllRowsReader without "withTokenRange(startToken, endToken)" then all works fine. But with "withTokenRange(startToken, endToken)" not all rows are fetched during column family reading.
AllRowsReader's source has this code:
if (this.concurrencyLevel != null || startToken != null|| endToken != null) {
List<TokenRange> tokens = partitioner.splitTokenRange(
startToken == null ? partitioner.getMinToken() : startToken,
endToken == null ? partitioner.getMinToken() : endToken,
this.concurrencyLevel == null ? 1 : this.concurrencyLevel);
for (TokenRange range : tokens) {
subtasks.add(makeTokenRangeTask(range.getStartToken(), range.getEndToken()));
}
}
Later partitioner.getMinToken() reverts to maxToken. So I don't understand what is the difference from my approach? Why AllRowsReader with minToken/maxToken works differnt from AllRowsReader without them?
If operation is teminated, I execute it again with the last startToken (so it must be a shift). But in this case I see some rows were fetched before. And this is confusing me too...
P.S. Astyanax automatically determines Murmur3Partitioner.
Thanks for any help.
Links:
AllRowsReader source,
Murmur3Partitioner source
Dmitry,
Treat the token range as a ring,as the circle completes start will be equal to end.Thats why in astyanax code there are setting the same token as min and max.
startToken == null ? partitioner.getMinToken() : startToken,
endToken == null ? partitioner.getMinToken() : endToken
I hope this clarifies your answer.Let me know if you have doubts

Java XML parser error Invalid character Unicode 0x1A when copy/paste from Word

Sorry to double post. But my earlier post was based on Flex:
Flex TextArea - copy/paste from Word - Invalid unicode characters on xml parsing
But now I'm posting this on the Java side.
The issue is:
We have an email functionality (part of our application) where we create an XML string & put it on the queue. Another application picks it up, parses the XML & sends out emails.
We get an XML parser exception when the email text (<BODY>....</BODY) is copy/pasted from Word:
Invalid character in attribute value BODY (Unicode: 0x1A)
As we use Java as well, I'm trying to remove the invalid characters from the String using:
body = body.replaceAll("‘", "");
body = body.replaceAll("’", "");
//Strip invalid characters
public String stripNonValidXMLCharacters(String in) {
StringBuffer out = new StringBuffer(); // Used to hold the output.
char current; // Used to reference the current character.
if (in == null || ("".equals(in))) {
return ""; // vacancy test.
}
for (int i = 0; i < in.length(); i++) {
//NOTE: No IndexOutOfBoundsException caught here; it should not happen.
current = in.charAt(i);
if ((current == 0x9)
|| (current == 0xA)
|| (current == 0xD)
|| ((current >= 0x20) && (current <= 0xD7FF))
|| ((current >= 0xE000) && (current <= 0xFFFD))
|| ((current >= 0x10000) && (current <= 0x10FFFF)))
out.append(current);
}
return out.toString();
}
//Strip once more
private String stripNonValidXMLCharacter(String in) {
if (in == null || ("".equals(in))) {
return null;
}
StringBuffer out = new StringBuffer(in);
for (int i = 0; i < out.length(); i++) {
if (out.charAt(i) == 0x1a) {
out.setCharAt(i, '-');
}
}
return out.toString();
}
//Replace the special characters if any
emailText = emailText.replaceAll("[\\u0000-\\u0008\\u000B\\u000C"
+ "\\u000E-\\u001F"
+ "\\uD800-\\uDFFF\\uFFFE\\uFFFF\\u00C5\\u00D4\\u00EC"
+ "\\u00A8\\u00F4\\u00B4\\u00CC\\u2211]", " ");
emailText = emailText.replaceAll("[\\x00-\\x1F]", "");
emailText = emailText.replaceAll(
"[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]", "");
emailText = emailText.replaceAll("\\p{C}", "");
But they still do not work. Also the XML string starts with:
<?xml version="1.0" encoding="UTF-8"?>
<EMAILS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNameSpaceSchemaLocation=".\\SMTPSchema.xsd\">
I think the issue occurs when there are multiple Tabs in the Word doc. Like for eg.
Text......text
<newLine>
<tab><tab><tab> text...text
<newLine>
The resulting xml string is:
<?xml version="1.0" encoding="UTF-8"?> <EMAILS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNameSpaceSchemaLocation=".\SMTPSchema.xsd"> <EMAIL SOURCE="t#t.com" DEST="t#t.com" CC="" BCC="t#t.com" SUBJECT="test 61" BODY="As such there was no mechanism constructed to migrate the enrollment user base to Data Collection or to keep security attributes for common users in sync between the two systems. The purpose of this document is to outline two strategies for bring the user base between the two applications into sync.? It still is the same. ** Please note: This e-mail message was sent from a notification-only address that cannot accept incoming e-mail. Please do not reply to this message."/> </EMAILS>
Please note then the "?" is where there are multiple tabs in the Word doc. Hope my question is clear & someone can help in resolving the issue
Thanks
Have you tried using an XML library such as TagSoup / JSoup / JTidy to sanitize your XML?
The invalid (hidden) character was from the UI (Flex TextArea). So had to take care of that in the UI so that it does not pass over to Java as well. Handled & removed it using the chagingHandler in the Flex textArea to restrict the characters.

Categories

Resources