I am trying to capture a ValidationEvent
with characters that are not allowed in the XML rules. (e.g, "&")
Also, I set up ValidationEventHandler
to check for unmarshal errors. I tried to unmarshal using an InputStream
, but the event handler does not catch the error. The handleEvent
method is not executed at all. On the other hand, using StringReader
will work normally.
I've already read the Javadoc that describes the unmarshal
method. However, I did not see that it could not capture the ValidationEvent.
Unmarshal XML data from the specified InputStream and return the resulting content tree. Validation event location information may be incomplete when using this form of the unmarshal API.
On the last attempt, I did try searching online but I couldn't find anything.
Any help will be appreciated :D
I am sorry to add a question. (The POJO class has changed a bit ...)
I defined the POJO class field with @XmlPath
Annotation differently from the XML element name, but it does not seem to work. Should I use it as an XmlElement?
import org.eclipse.persistence.oxm.annotations.XmlPath;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
@XmlRootElement
class Article {
private String title;
private String category;
private List<ArticleImage> imageList;
public String getTitle() {
return title;
}
@XmlElement
public void setTitle(String title) {
this.title = title;
}
public String getCategory() {
return category;
}
@XmlElement
public void setCategory(String category) {
this.category = category;
}
public List<ArticleImage> getImageList() {
return imageList;
}
// for Extra Question... :D
@XmlPath("image")
public void setImageList(List<ArticleImage> imageList) {
this.imageList = imageList;
}
}
class ArticleImage {
private String url;
private String ext;
public String getUrl() {
return url;
}
@XmlAttribute
public void setUrl(String url) {
this.url = url;
}
public String getExt() {
return ext;
}
@XmlAttribute
public void setExt(String ext) {
this.ext = ext;
}
}
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.ValidationEventLocator;
class CustomValidationHandler implements ValidationEventHandler {
// This method is not reached when debugging.
@Override
public boolean handleEvent(ValidationEvent event) {
if (event.getSeverity() == ValidationEvent.FATAL_ERROR ||
event.getSeverity() == ValidationEvent.ERROR) {
ValidationEventLocator locator = event.getLocator();
throw new RuntimeException("Error in EventHandler. line number: " + locator.getLineNumber());
}
return true;
}
}
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
public class SomeTest {
public void someMethod() {
String xmlString = "<article type=\"item\">\n"
+ " <title>M&A</title>\n"
+ " <category>1234-1234</category>\n"
+ " <image url=\"hello\" ext=\"jpg\"/>\n"
+ "</article>";
try (InputStream fileInputStream = new ByteArrayInputStream(xmlString.getBytes())) {
JAXBContext context = JAXBContextFactory.createContext(new Class[]{Article.class}, null);
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setEventHandler(new CustomValidationHandler());
Article article = (Article) unmarshaller.unmarshal(fileInputStream);
System.out.println(article.getTitle());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new SomeTest().someMethod();
}
}
Initially suggested to replace
JAXBContext context = JAXBContextFactory.createContext(new Class[]{Article.class}, null);
to
JAXBContext context = JAXBContext.newInstance(Article.class);
In the implementation of JAXBContextFactory.createContext you can see that the classesToBeBound, which in your case you pass Article, perform some checks which result in exception for being "Unable to find a JAXB implementation to delegate". This is the problem I had when running your code and I assumed you had as well. Then your event handler was called (at least in my setup).
Later you had issues with "... Class has two properties of the same name "value" ..." and I proposed to check this link which explains the reason it happens.
the link is: What is the difference between using @XmlElement before field and before getter declaration?
Edit to reply to new question:
If you don't mind me asking what are you trying to do with @XmlPath("image")
?
Your POJO structure does not match the xml. Remove the annotation and change the setter method for image, as below:
@XmlRootElement
class Article {
private String title;
private String category;
private List<ArticleImage> imageList;
public String getTitle() {
return title;
}
@XmlElement
public void setTitle(String title) {
this.title = title;
}
public String getCategory() {
return category;
}
@XmlElement
public void setCategory(String category) {
this.category = category;
}
public List<ArticleImage> getImage() {
return imageList;
}
// for Extra Question... :D
// method name changed!
public void setImage(List<ArticleImage> imageList) {
this.imageList = imageList;
}
}
class ArticleImage {
private String url;
private String ext;
public String getUrl() {
return url;
}
@XmlAttribute
public void setUrl(String url) {
this.url = url;
}
public String getExt() {
return ext;
}
@XmlAttribute
public void setExt(String ext) {
this.ext = ext;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With