Wicket SpringBean在一个面板上生成NotSerializableException,但不生成另一个面板

时间:2017-03-14 10:55:15

标签: java spring wicket wicket-6

我有一个spring bean DAO类,它有一个方法reverseLookup(),它返回一个List< String>。我将这个bean注入2个wicket组件,并在每个组件的ajax调用中调用相同的方法。

在第一个面板中,它没有任何问题。在第二个面板中,我得到一个NotSerializableException。

DAO类不是可序列化的,但它不应该是。我使用@SpringBean来注入bean(并且在这个大型应用程序中使用@SpringBean注入了许多其他bean,这些bean都可以正常工作)

在ajax调用完成并且页面被序列化之前,错误不会发生。然后它在每个连续的请求周期中失败。

我无法看到有关DAO类的任何特殊内容 - 它没有成员变量或做其他DAO类所做的任何特殊操作。我无法理解为什么它在一个面板中工作正常但在另一个面板中却没有。

我已尝试在违规面板中使用Injector创建成员变量瞬态,但它并没有产生影响。

DAO界面:

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

DAO课程:

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是所有其他DAO实现使用的父类。 ProxyList只是一个pre-stream()包装器List实现,允许访问列表属性而无需复制列表的内容。 ViewCriteria充当较低层的JPA和上面的UI逻辑之间的桥梁,用于创建数据查询。

工作正常的组件(不在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 );
      }

    });
  }
}

失败的组件(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 );
}

我能看到的唯一差异/注意事项是:

  • 失败的是ajax表单提交(非失败者不使用表单)
  • 失败页面上有两个表单(一个用于提交搜索参数,另一个用于选择搜索结果)
  • 失败的是ModalWindow中的面板

有没有人有类似的问题?

由于

1 个答案:

答案 0 :(得分:2)

(如果有人遇到类似问题,可以发布)

问题是因为ProxyList - 因为我在DAO类中创建了ProxyList的匿名实现,并且这被返回到标准中,这意味着StringResourceDAO也必须被序列化。

通过用List.stream.filter.collect替换ProxyList,它解决了这个问题。

(虽然我仍然不理解为什么它适用于一个小组而不是另一个小组)