Search code examples
wicketwicket-6

Wicket NotSerializableException populating ListView


I'm working on a Web application which uses Spring and Hibernate frameworks. Right now I would like to remove the Serializable interface implementation from my Viaggio.java class, a JPA Entity. Entities of this class are displayed inside my Wicket page through a PageableListView. When I render the web page I get a NotSerializableException. Here's a snippet of the code that instantiate the ListView:

        final LoadableDetachableModel<List<Viaggio>> viaggiListModel = new LoadableDetachableModel<List<Viaggio>>() {
        @Override
        protected List<Viaggio> load() {
            List<Viaggio> viaggi = utenteService.findAllViaggiForDataAndUsername(dataSelected, utente);
            return viaggi;
        }
    };

    final WebMarkupContainer container = new WebMarkupContainer("tableResult");
    container.setOutputMarkupId(true);
    PageableListView repeating = new PageableListView("repeating", viaggiListModel, 10) {
        @Override
        protected void populateItem(ListItem item) {
            final Viaggio viaggio = (Viaggio) item.getModelObject();
            String date = new SimpleDateFormat("dd-MM-yyyy").format(viaggio.getData());
            item.add(new Label("data", date));
            item.add(new Label("automezzo", new PropertyModel(viaggio, "targaMotrice")));
            item.add(new Label("autista", new PropertyModel(viaggio, "primoAutista")));
            item.add(new EnumLabel("status", new PropertyModel(viaggio, "status")));
......

I append down here the stacktrace printed:

    24/02/2018 09:06:22,629 ERROR -JavaSerializer - Error serializing object class it.loginet.buonicarico.presentation.ViaggioListPage [object=[Page class = it.loginet.buonicarico.presentation.ViaggioListPage, id = 2, render count = 1]]
    org.apache.wicket.core.util.objects.checker.CheckingObjectOutputStream$ObjectCheckException: The object type is not Serializable!
A problem occurred while checking object with type: it.loginet.buonicarico.domain.utente.Viaggio
Field hierarchy is:
  2 [class=it.loginet.buonicarico.presentation.ViaggioListPage, path=2]
    private java.lang.Object org.apache.wicket.MarkupContainer.children [class=[Ljava.lang.Object;]
      private java.lang.Object org.apache.wicket.MarkupContainer.children[5] [class=org.apache.wicket.markup.html.WebMarkupContainer, path=2:tableResult]
        private java.lang.Object org.apache.wicket.MarkupContainer.children [class=[Ljava.lang.Object;]
          private java.lang.Object org.apache.wicket.MarkupContainer.children[0] [class=org.apache.wicket.markup.html.navigation.paging.PagingNavigator, path=2:tableResult:navigator]
            private java.lang.Object org.apache.wicket.MarkupContainer.children [class=[Ljava.lang.Object;]
              private java.lang.Object org.apache.wicket.MarkupContainer.children[0] [class=org.apache.wicket.markup.html.navigation.paging.PagingNavigation, path=2:tableResult:navigator:navigation]
                private java.lang.Object org.apache.wicket.MarkupContainer.children [class=org.apache.wicket.markup.html.list.LoopItem, path=2:tableResult:navigator:navigation:0]
                  private java.lang.Object org.apache.wicket.MarkupContainer.children [class=org.apache.wicket.markup.html.navigation.paging.PagingNavigationLink, path=2:tableResult:navigator:navigation:0:pageLink]
                    protected final org.apache.wicket.markup.html.navigation.paging.IPageable org.apache.wicket.markup.html.navigation.paging.PagingNavigationLink.pageable [class=org.apache.wicket.markup.html.list.PageableListView, path=2:tableResult:repeating]
                      private java.lang.Object org.apache.wicket.MarkupContainer.children [class=org.apache.wicket.markup.html.list.ListItem, path=2:tableResult:repeating:0]
                        private java.lang.Object org.apache.wicket.MarkupContainer.children [class=[Ljava.lang.Object;]
                          java.lang.Object org.apache.wicket.Component.data[1] [class=org.apache.wicket.markup.html.basic.Label, path=2:tableResult:repeating:0:automezzo]
                            java.lang.Object org.apache.wicket.Component.data [class=org.apache.wicket.model.PropertyModel]
                              private java.lang.Object org.apache.wicket.model.ChainingModel.target [class=it.loginet.buonicarico.domain.utente.Viaggio] <----- field that is causing the problem
    at org.apache.wicket.core.util.objects.checker.CheckingObjectOutputStream.internalCheck(CheckingObjectOutputStream.java:362)
    at org.apache.wicket.core.util.objects.checker.CheckingObjectOutputStream.check(CheckingObjectOutputStream.java:341)

It clearly states my Viaggio field inside PropertyModel is not serializable, it finally points the finger to the "automezzo" Label i'm adding to the ListItem.

Where am I missing the point? LoadableDetachableModel that wraps my list of Viaggio entities seems to be used correctly.


Solution

  • All your labels reference PropertyModels, which themselves directly reference your entity.

    As a rule of thumb you should never call IModel#getObject() and keep its result around longer than needed:

        final WebMarkupContainer container = new WebMarkupContainer("tableResult");
        container.setOutputMarkupId(true);
        PageableListView<Viaggio> repeating = new PageableListView<Viaggio>("repeating", viaggiListModel, 10) {
            @Override
            protected void populateItem(ListItem<Viaggio> item) {
                final IModel<Viaggio> viaggio = item.getModel();
    
                item.add(new Label("data", new AbstractReadOnlyModel<String>() {
                    public String getObject() {
                        return new SimpleDateFormat("dd-MM-yyyy").format(viaggio.getObject().getData())
                    }
                });
                item.add(new Label("automezzo", new PropertyModel(viaggio, "targaMotrice")));
                item.add(new Label("autista", new PropertyModel(viaggio, "primoAutista")));
                item.add(new EnumLabel("status", new PropertyModel(viaggio, "status")));
    ......
    

    Instead of the AbstractReadOnlyModel you could use a PropertyModel too, and let a Converter do the formatting of the date.