2015-11-16 4 views
0

я получаю следующее сообщение об ошибке при работе с калиткой 6.19:Ошибка: Не отдельные модели нашли

Caused by: org.apache.wicket.core.util.objects.checker.CheckingObjectOutputStream$ObjectCheckException: Not detached model found! 
A problem occurred while checking object with type: com.test.web.components.CurrentUserModel 
Field hierarchy is: 
    [class=com.test.web.base.pages.HomePage, path=0] 
    private java.lang.Object org.apache.wicket.MarkupContainer.children [class=[Ljava.lang.Object;] 
     java.lang.Object org.apache.wicket.Component.data[1] [class=com.test.web.HeaderPanel, path=0:headerPanel] 
     private java.lang.Object org.apache.wicket.MarkupContainer.children [class=[Ljava.lang.Object;] 
      private java.lang.String org.apache.wicket.markup.html.image.resource.LocalizedImageResource.variation[2] [class=com.test.web.LoginStatusPanel, path=0:headerPanel:loginStatusPanel] 
      java.lang.Object org.apache.wicket.Component.data [class=com.test.web.components.CurrentUserModel] <----- field that is causing the problem 

Код:

@RequireHttps 
public class HomePage extends WebPage { 
    private HeaderPanel headerPanel; 
    private LoginStatusPanel loginStatusPanel; 
    private MenuPanel menuPanel; 

    public HomePage(String id) { 
     super(); 
     initialize(); 
    } 

    public HomePage(String id, PageParameters parameters) { 
     super(parameters); 
     initialize(); 
    } 

    @Override 
    protected void onInitialize() { 
     Request request = RequestCycle.get().getRequest(); 
     if (request instanceof ServletWebRequest) 
     { 
      ServletWebRequest wr = (ServletWebRequest) request; 
      HttpSession session = wr.getContainerRequest().getSession(); 
      if (session != null) { 
      } 
     } 
     super.onInitialize(); 
    } 

    public String getApplicationId(){ 
     return applicationId; 
    } 

    private void initialize() { 
     add(headerPanel = new HeaderPanel("headerPanel")); 
     headerPanel.add(loginStatusPanel = new LoginStatusPanel("loginStatusPanel")); 
     headerPanel.add(menuPanel = new MenuPanel("menuPanel")); 
    } 
} 

public class HeaderPanel extends Panel { 
    private Label headerTitleLbl; 

    public HeaderPanel(String id) { 
     super(id); 
     add(headerTitleLbl=new Label("headerTitle", WebApplication.getAppTitle())); 
     headerTitleLbl.setOutputMarkupId(true); 
    } 
} 

public class LoginStatusPanel extends Panel { 

    public LoginStatusPanel(String id) { 
     super(id, new CurrentUserModel()); // Line 1 
    } 

    protected void onInitialize() { 
     IModel<Authentication> authModel = (IModel<Authentication>) getDefaultModel(); 
     final Authentication auth = authModel.getObject(); 

     if (auth != null && auth.isAuthenticated() && !(auth instanceof AnonymousAuthenticationToken)) 
     { 
      Fragment fragment = new Fragment("frag", "loggedInFragment", this); 
      Label status; 
      fragment.add(status = new Label("status", "Logged in as ")); 
      fragment.add(new Label("userId", new PropertyModel<String>(authModel, "name"))); 
      add(fragment); 
     } 
     else 
     { 
      Fragment fragment = new Fragment("frag", "loggedOutFragment", this); 
      fragment.add(new Label("status", "Logged out")); 
      fragment.add(new ExternalLink("login", "/LoginPage", "Log In")); 
      add(fragment); 
     } 
     super.onInitialize(); 
    } 
} 

public class MenuPanel extends Panel { 
    public MenuPanel(String id) { 
     super(id); 
     add(new MenuPanel("menu", WebApplication.getMenuList())); 
    } 
} 

public class CurrentUserModel extends LoadableDetachableModel<Authentication> { 
    protected Authentication load() { 
     return SecurityContextHolder.getContext().getAuthentication(); 
    } 
} 

Примечания: Если я обновляю код в комментариях пометили как «Line 1' со следующим:

super(id, new Model(SecurityContextHolder.getContext().getAuthentication())); 

ошибка не появляется, это может быть потому, что его не в LoadableDetachableModel.

Возможно ли передать экземпляр класса LoadableDetachableModel в конструктор класса Component?

Я получаю ту же ошибку в следующем коде, а также:

tree = new NestedTree<TreeItem>("tree", provider, state); 

Где состояние представляет собой экземпляр следующего класса:

private class TreeItemExpansionModel extends LoadableDetachableModel<Set<TreeItem>> 
{ 
    private static final long serialVersionUID = 1L; 
    private final String treePanelId; 

    public TreeItemExpansionModel(String treePanelId) { 
     this.treePanelId = treePanelId; 
    } 

    @Override 
    protected Set<TreeItem> load() { 
     return TreeItemExpansion.get(treePanelId); 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj instanceof TreeItemExpansionModel) { 
      return ((TreeItemExpansionModel) obj).treePanelId.equals(treePanelId); 
     } 
     return false; 
    } 

    @Override 
    public int hashCode() { 
     return treePanelId.hashCode(); 
    } 
} 

И ошибка выглядит следующим образом:

Caused by: org.apache.wicket.core.util.objects.checker.CheckingObjectOutputStream$ObjectCheckException: Not detached model found! 
A problem occurred while checking object with type: com.test.web.components.TreeItemProvider$TreeItemModel 
Field hierarchy is: 
    [class=com.test.web.admin.pages.HomePage, path=0] 
    private java.lang.Object org.apache.wicket.MarkupContainer.children [class=[Ljava.lang.Object;] 
     java.util.List com.test.web.components.WhistlePanel.selectionList[2] [class=com.test.web.NavPanel, path=0:navPanel] 
     private java.lang.Object org.apache.wicket.MarkupContainer.children [class=org.apache.wicket.extensions.markup.html.repeater.tree.NestedTree, path=0:navPanel:tree] 
      private java.lang.Object org.apache.wicket.MarkupContainer.children [class=org.apache.wicket.extensions.markup.html.repeater.tree.nested.Subtree, path=0:navPanel:tree:subtree] 
      private java.lang.Object org.apache.wicket.MarkupContainer.children [class=org.apache.wicket.markup.repeater.RefreshingView, path=0:navPanel:tree:subtree:branches] 
       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.extensions.markup.html.repeater.tree.nested.BranchItem, path=0:navPanel:tree:subtree:branches:1] 
        java.lang.Object org.apache.wicket.Component.data [class=com.test.web.components.TreeItemProvider$TreeItemModel] <----- field that is causing the problem 

Заранее спасибо.

+2

Я не могу определить причину проблемы в коде вы публикуемую, но сообщение об ошибке ясно: Вы держать экземпляр CurrentUserModel в вашем дереве компонентов, которые не отделиться, т.е. это не модель по умолчанию для компонента-владельца. – svenmeier

+1

@svenmeier Спасибо за ваш ответ, я обновил свой вопрос с дополнительной информацией. – Leejoy

ответ

2

Проблема заключается в комбинации средства проверки Serialization и управления жизненным циклом моделей.

Когда вы помещаете LoadableDetachableModel и вы инициализируете модель, которая НЕ является Serializable, калибровочная проверка генерирует исключение, которое вы пытаетесь сериализовать данные, которые не являются Serializable. Это правильное поведение.

Причина, почему это происходит в

  1. Аутентификация не Сериализуемый
  2. Вы называете getDefaultModel(). Получить(), который загружает объект модели, даже если это ленивый загрузки модели

См. NotDetachedModelCheckerhttps://github.com/apache/wicket/blob/build/wicket-6.20.0/wicket-core/src/main/java/org/apache/wicket/core/util/objects/checker/NotDetachedModelChecker.java

Отдается Фикс:

I. Использование AbstractReadOnlyModel вместо LoadableDetachableModel

public class CurrentUserModel extends AbstractReadOnlyModel<Authentication> { 
     protected Authentication getObject() { 
      return SecurityContextHolder.getContext().getAuthentication(); 
     } 
    } 

Если вам действительно нужно сохранить значение (я думаю, что это не требуется, потому что весна аутентификационный контекст возвращает все те же значения при каждой попытке), оберните LoadableDetachbleModel с помощью AbstractReadOnlyModel.

II. Отсоедините модель: позвоните authModel.отсоединить(); прежде чем вернуть управление потоком обратно в калитку

protected void onInitialize() { 
    IModel<Authentication> authModel = (IModel<Authentication>) getDefaultModel(); 
    final Authentication auth = authModel.getObject(); 

    if (auth != null && auth.isAuthenticated() && !(auth instanceof AnonymousAuthenticationToken)) 
    { 
     Fragment fragment = new Fragment("frag", "loggedInFragment", this); 
     Label status; 
     fragment.add(status = new Label("status", "Logged in as ")); 
     fragment.add(new Label("userId", new PropertyModel<String>(authModel, "name"))); 
     add(fragment); 
    } 
    else 
    { 
     Fragment fragment = new Fragment("frag", "loggedOutFragment", this); 
     fragment.add(new Label("status", "Logged out")); 
     fragment.add(new ExternalLink("login", "/LoginPage", "Log In")); 
     add(fragment); 
    } 
    authModel.detach(); 
    super.onInitialize(); 
} 
-1

Я знаю, что информация, которую я предоставил себя здесь неполна для любого, чтобы дать правильное решение.

Я разместил тот же запрос на другом форуме и получил решение. Поэтому я подумал о том, чтобы поделиться этой ссылкой here, так что это может быть полезно для людей, которые посещают эту страницу.

Благодаря