简体   繁体   中英

Wicket SpringBean generates NotSerializableException on one panel but not another

I have a spring bean DAO class, that has a method reverseLookup() which returns a List<String>. I inject this bean into 2 wicket components, and make a call to the same method in an ajax call on each component.

In the first panel, it works fine with no problems. In the second panel, I get a NotSerializableException.

The DAO class is not Serializable, but it shouldn't have to be. I use @SpringBean to inject the bean (and have dozens of other beans injected with @SpringBean within this large application that all work just fine)

The error doesn't occur until the ajax call completes and the page is serialized. Then it fails on each successive request cycle.

I can't see anything special about the DAO class - it has no member variables or does anything special that other DAO classes do. I can't understand why it works fine in one panel but not in the other.

I've tried making the member variable transient in the offending panel and using Injector but it doesn't make a difference.

The DAO interface:

public interface StringResourceDAO extends EntityDAO<StringResource, Long> {

  .. other methods
  public List<String> reverseLookup( TranslationType p_type, String p_searchString, Locale p_locale, String p_style, String p_variation ) throws GetException;
}

The DAO class:

public class StringResourceJpaDAO extends AbstractEntityJpaDAO<StringResource> implements StringResourceDAO {
  ... other methods

  @Override
  public List<String> reverseLookup( TranslationType p_type, String p_searchString, Locale p_locale, String p_style, String p_variation ) throws GetException {
    ViewCriteria<StringResource> resourceCriteria = new ViewCriteria<>();
    resourceCriteria.addFilter( new EqualityFilter<String>( StringResource_.key, Operator.STARTS_WITH, p_type.getPrefix() ) );
    resourceCriteria.addFilter( EqualityFilter.equalFilter( StringResource_.localeCountry, p_locale == null ? null : StringUtils.defaultIfEmpty( p_locale.getCountry(), null ) ) );
    resourceCriteria.addFilter( EqualityFilter.equalFilter( StringResource_.localeLanguage, p_locale == null ? null : StringUtils.defaultIfEmpty( p_locale.getLanguage(), null ) ) );
    resourceCriteria.addFilter( new EqualityFilter<String>( StringResource_.value, Operator.LIKE, "%" + p_searchString + "%" ).setCaseSensitive( false ) );
    resourceCriteria.setDistinctResults( true );
    resourceCriteria.setMaxResults( 250 );

    List<String> matchingKeys = super.getOtherProperty( l_resourceCriteria, StringResource.class, String.class, StringResource_.key.getName() );
    return new ProxyList<String,String>( l_matchingKeys ) {

      private static final long serialVersionUID = 1L;

      @Override
      public String getItem( String p_proxy ) {
        return TranslationType.removePrefix( p_type, p_proxy );
      }

    };
  }

}

AbstractEntityJpaDAO is a parent class used by all the other DAO implementations. ProxyList is just a pre-stream() wrapper List implementation to allow for access to list properties without having to copy the contents of the list. ViewCriteria acts as a bridge between the JPA in the lower layers and the UI logic above for creating data queries.

The component that works fine (a panel not in a ModalWindow):

public abstract class ServiceLevelLookupPanel extends AbstractDialogPanel {

  @SpringBean
  protected StringResourceDAO m_resourceService;

  protected void onInitialize() {
    TextField<String> serviceLevelNumberField = new TextField<String>( "serviceLevelNumberField", m_serviceLevelNumberModel );
    // HAVE to set this to not required, otherwise the onchange event won't fire if the user empties the text field
    serviceLevelNumberField.setRequired( false );
    serviceLevelNumberField.setConvertEmptyInputStringToNull( true );
    serviceLevelNumberField.add( new AjaxFormComponentUpdatingBehavior("onchange") {

      private static final long serialVersionUID = 1L;

      @Override
      protected void onUpdate( AjaxRequestTarget p_target ) {
        String slNumber = getSearchString();
        // works just fine!
        List<String> translationReverseLookupCodes = m_resourceService.reverseLookup( TranslationType.SERVICE_LEVEL_DESCRIPTION, slNumber, getLocale(), null, null );
      }

    });
  }
}

The component that fails (a panel within a ModalWindow):

public class ChooseServiceLevelPanel extends Panel implements IAjaxIndicatorAware {

  @SpringBean
  protected StringResourceDAO m_resourceService;

  protected void onInitialize() {
   ...

    AjaxSubmitLink searchButton = new AjaxSubmitLink( "searchButton" ) {

      private static final long serialVersionUID = 1L;

      @Override
      public void onSubmit( AjaxRequestTarget p_target, Form<?> p_form ) {
        // once this is called, subsequent page serializations fail!
        List<String> matchingServiceLevelCodes = m_resourceService.reverseLookup( TranslationType.SERVICE_LEVEL_DESCRIPTION, m_descriptionModel.getObject(), getLocale(), null, null );
      }
    };
    searchForm.add( l_searchButton );
}

The only differences/things of note that I can see are:

  • The failing one is in an ajax form submit (the non-failing one doesn't use a form)
  • There are 2 forms on the failing page (one to submit the search params, the other to select a search result)
  • The failing one is a panel inside a ModalWindow

Has anyone had any similar problems?

Thanks

(posting in case anyone had similar issues)

The problem was because of the ProxyList - because I created an anonymous implementation of the ProxyList within the DAO class, and this was returned to put in the criteria, it meant that the StringResourceDAO had to be serialized as well.

By replacing the ProxyList with List.stream.filter.collect, it solved the problem.

(although I still don't understand why it worked for one panel but not the other)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM