Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB ValidationEventHandler's handleEvent method not being called

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

Extra question:

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?


POJO class:

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;
    }
}


ValidationEventHandler:

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;
    }
}


Unmarshal code:

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();
    }
}
like image 326
Madplay Avatar asked May 17 '19 17:05

Madplay


1 Answers

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;
    }
}
like image 66
martidis Avatar answered Sep 29 '22 12:09

martidis