1

I'm writing an MVC Java program, using JAXB to generate XML and send to a display jsp. The code runs and the XML is displayed correctly in the browser, but I'm still getting a JAXBException in the IDE console.

I've referred to a couple of pages on the topic here and here. I've added the JAXB annotations as suggested, but the error hasn't gone away.

Can anyone help?

Web Servlet

@WebServlet(name = "GetAllFilms", value = "/GetAllFilms")
public class GetAllFilms extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setCharacterEncoding("UTF-8");
        String jspDisplayString = "";

        String dataFormat = request.getParameter("format");
        if (dataFormat == null) dataFormat = "json";

        FilmDAO filmDAO = new FilmDAO();
        ArrayList<Film> allFilms = filmDAO.getAllFilms();

        request.setAttribute("films", allFilms);

        String viewJspFilePath = "";

        if (dataFormat.equals("json")) {
            response.setContentType("application/json");
            viewJspFilePath = "/WEB-INF/results/films-json.jsp";

            jspDisplayString = jsonGenerator(allFilms);

        } else if (dataFormat.equals("xml")) {
            response.setContentType("text/xml");
            viewJspFilePath = "/WEB-INF/results/films-xml.jsp";

            try {
                jspDisplayString = xmlGenerator(allFilms);
            } catch (JAXBException e) {
                e.printStackTrace();
            }

        } else {
            response.setContentType("text/plain");
            viewJspFilePath = "/WEB-INF/results/films-string.jsp";

            jspDisplayString = stringGenerator(allFilms);
        }

        RequestDispatcher dispatcher =
                request.getRequestDispatcher(viewJspFilePath);
        dispatcher.include(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

    private String xmlGenerator(ArrayList<Film> allFilms)
            throws JAXBException, FileNotFoundException {

        FilmList filmList = new FilmList();
        filmList.setFilmList(allFilms);

        JAXBContext jaxbContext = JAXBContext.newInstance(FilmList.class);
        Marshaller marshaller = jaxbContext.createMarshaller();

        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        StringWriter stringWriter = new StringWriter();
        marshaller.marshal(allFilms, stringWriter);

        return stringWriter.toString();
    }
}

Film Model Class (with JAXB Annotation)

package model_beans;

@XmlRootElement(name = "film")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = { "id", "title", "year", "director", "stars", "review" })

public class Film {

    public Film() {

    }

    public Film(int id, String title, int year, String director, String stars,
                String review) {
        super();
        this.id = id;
        this.title = title;
        this.year = year;
        this.director = director;
        this.stars = stars;
        this.review = review;
    }

    int id;
    String title;
    int year;
    String director;
    String stars;
    String review;

    *getters / setters excluded for ease of reading*

    @Override
    public String toString() {
        return "Film [id=" + id + ", title=" + title + ", year=" + year
                + ", director=" + director + ", stars=" + stars + ", review="
                + review + "]";
    }
}

FilmList Model Class (with JAXB Annotation)

package model_beans;

@XmlRootElement(namespace = "model_beans")
@XmlAccessorType(XmlAccessType.FIELD)
public class FilmList {

    @XmlElementWrapper(name = "filmList")
    @XmlElement(name = "film")
    private ArrayList<Film> filmList;

    public ArrayList<Film> getFilmList() {
        return filmList;
    }

    public void setFilmList(ArrayList<Film> filmList) {
        this.filmList = filmList;
    }
}

JSP Xml Data Format

<?xml version="1.0" encoding="UTF-8"?>
<%--@elvariable id="films" type="model_beans.Film"--%>
<%@taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core"%>
<films>
  <headings>
    <heading>Film ID</heading>
    <heading>Title</heading>
    <heading>Year</heading>
    <heading>Director</heading>
    <heading>Stars</heading>
    <heading>Review</heading>
  </headings>
  <c:forEach items="${films}" var="f">
    <film>
      <id>${f.id}</id>
      <title>${f.title}</title>
      <year>${f.year}</year>
      <director>${f.director}</director>
      <stars>${f.stars}</stars>
      <review>${f.review}</review>
    </film>
  </c:forEach>
</films>

Stack Trace

javax.xml.bind.JAXBException: class java.util.ArrayList nor any of its super class is known to this context.
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:567)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:467)
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308)
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236)
    at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:116)
    at controller_servlets.GetAllFilms.xmlGenerator(GetAllFilms.java:125)
    at controller_servlets.GetAllFilms.doGet(GetAllFilms.java:68)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
mcooling
  • 107
  • 2
  • 14

1 Answers1

2

modify the FilmList class as follows,

  1. add the @XmlRootElement annotation to the class
  2. remove @XmlElementWrapper annotation from class

FilmList.java

    @XmlRootElement(name="filmList")
    public class FilmList {

        private ArrayList<Film> listFilm;

        @XmlElement(name = "film")
        public ArrayList<Film> getFilmList() {
            return listFilm;
        }

        public void setFilmList(ArrayList<Film> listFilm) {
            this.listFilm = listFilm;
        }
    }

Film.java

@XmlRootElement(name = "film")
@XmlType(propOrder = { "id", "title", "year", "director", "stars", "review" })
public class Film {

    public Film() {

    }

    public Film(int id, String title, int year, String director, String stars,
                String review) {
        super();
        this.id = id;
        this.title = title;
        this.year = year;
        this.director = director;
        this.stars = stars;
        this.review = review;
    }

    int id;
    String title;
    int year;
    String director;
    String stars;
    String review;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public String getDirector() {
        return director;
    }

    public void setDirector(String director) {
        this.director = director;
    }

    public String getStars() {
        return stars;
    }

    public void setStars(String stars) {
        this.stars = stars;
    }

    public String getReview() {
        return review;
    }

    public void setReview(String review) {
        this.review = review;
    }

    @Override
    public String toString() {
        return "Film [id=" + id + ", title=" + title + ", year=" + year
                + ", director=" + director + ", stars=" + stars + ", review="
                + review + "]";
    }
}

Marshaller.java

public class Marshaller {

    public static void main(String[] args) {
    
        ArrayList<Film> listFilm = new ArrayList<>();
        StringWriter stringWriter = new StringWriter();
        FilmList filmList = new FilmList();

        Film film = new Film();
        film.setDirector("a");
        film.setId(1);
        film.setReview("b");
        film.setStars("c");
        film.setTitle("e");
        film.setYear(2020);
        listFilm.add(film);
        filmList.setFilmList(listFilm);
    
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(FilmList.class);
            javax.xml.bind.Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true);
            jaxbMarshaller.marshal(filmList, stringWriter);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        System.out.println(stringWriter);
    }
}

output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<filmList>
    <film>
        <id>1</id>
        <title>e</title>
        <year>2020</year>
        <director>a</director>
        <stars>c</stars>
        <review>b</review>
    </film>
</filmList>

Edited

reason for following error is a used the same name (filmList) for both @XmlRootElement and ArrayList<Film>. hence, please change the name of ArrayList<Film> to listFilm

Note. please set @XmlElement annotation to get method

Last Edited

in above servlet, you try to marshal the java collection (list of Film (allFilms)) in xmlGenerator method.

marshaller.marshal(allFilms, stringWriter);

but cannot marshal the collection and java collection class does not have JAXB annotation.

in your case, created the FilmList object, but it does not use to marshal. i think it is your mistake. please marshal the filmList as follows

marshaller.marshal(filmList, stringWriter);
Lakshan
  • 1,404
  • 3
  • 10
  • 23
  • Thanks for the reply @Lakshan. Tried making those changes but just get a different error. `com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions Class has two properties of the same name "filmList" this problem is related to the following location: at public java.util.ArrayList model_beans.FilmList.getFilmList() at model_beans.FilmList this problem is related to the following location: at private java.util.ArrayList model_beans.FilmList.filmList at model_beans.FilmList` – mcooling Feb 24 '21 at 19:44
  • @mcooling please refer above modified answer – Lakshan Feb 25 '21 at 02:42
  • thanks @Lakshan. I've made those suggested changes, but still getting the error unfortunately – mcooling Feb 26 '21 at 19:35
  • @mcooling above solution works fine for me. please update the your question – Lakshan Feb 27 '21 at 03:44
  • afraid not @Lakshan. I've been through with my uni tutor as well, and he can't explain it either. I'm told it won't affect marks, so I'm just going to live with it unless someone can resolve. – mcooling Mar 05 '21 at 22:34
  • the error is the same. I've updated my code though, in case that helps. Now added the full servlet, the view jsp for the xml format and updated model class beans with JAXB annotations. Thank you.. – mcooling Mar 06 '21 at 10:41
  • 1
    @mcooling please refer above modified answer. i was not careful about marshalling in your question previously. sorry for the inconvenience. – Lakshan Mar 06 '21 at 18:59
  • That's worked @Lakshan!! Thank you so much for all your help. Really do appreciate it :-) – mcooling Mar 07 '21 at 11:02