Good day! Help understand the reason - the case is: Wicket + CDI + Glassfish4 + JEE7

beans.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="all"> </beans> 

pom.xml

 <properties> <wicket.core.version>7.1.0</wicket.core.version> <wicket.cdi.version>7.1.0</wicket.cdi.version> </properties> <build> <finalName>atbs-ui</finalName> <!--<directory>E:\projects\big_data\at-project-base-station\vagrant\app\containers\glassfish\webapps</directory>--> </build> <dependencies> <dependency> <groupId>ru.atbs</groupId> <artifactId>atbs-model</artifactId> <version>1.0</version> <scope>compile</scope> </dependency> <dependency> <groupId>ru.atbs</groupId> <artifactId>atbs-core</artifactId> <version>1.0</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.wicket</groupId> <artifactId>wicket-core</artifactId> <version>${wicket.core.version}</version> </dependency> <dependency> <groupId>org.apache.wicket</groupId> <artifactId>wicket-cdi-1.1</artifactId> <version>${wicket.cdi.version}</version> <exclusions> <exclusion> <artifactId>wicket-core</artifactId> <groupId>org.apache.wicket</groupId> </exclusion> </exclusions> </dependency> </dependencies> 

Part of the MenuPanel class

 public class MenuPanel extends Panel { @Inject private MenuItemHelper menuItemHelper; @Inject private Logger logger; public MenuPanel(String componentId) { super(componentId); initListView(); } private void initListView() { List<MenuCategory> menuCategoryList = menuItemHelper.createMenuItems(); ListView<MenuCategory> contacts = new ListView<MenuCategory>("menuItems", menuCategoryList) { protected void populateItem(ListItem<MenuCategory> item) { item.add(new Label("menuItem", item.getModelObject().getLabel())); } }; add(contacts); } 

MenuItemHelper

 public class MenuItemHelper { private static final String PAGE = "Page"; private static final String SEPARATOR = "."; private static final String PAGE_PACKAGE = "ru.cs.vsu.wicket.pages"; @Inject private MenuItemDao menuItemDao; @Inject private Logger logger; public List<MenuCategory> createMenuItems() { List<MenuCategory> items = new ArrayList<MenuCategory>(); List<MenuItem> menuItems = menuItemDao.listAll(); Collections.sort(menuItems, new Comparator<MenuItem>() { @Override public int compare(MenuItem o1, MenuItem o2) { return o1.getSortIndex().compareTo(o2.getSortIndex()); } }); for(MenuItem item : menuItems) { try { items.add(new MenuCategory(Model.of(item.getName()), getClassPage(item))); } catch (ClassNotFoundException e) { try { logger.info(new String("Не удалось загрузить один из пунктов меню".getBytes("UTF-8"))); } catch (UnsupportedEncodingException e1) { logger.info(e.getMessage()); } logger.info(e.getMessage()); } } return items; } private Class<? extends Page> getClassPage(MenuItem item) throws ClassNotFoundException { return (Class<Page>)Class.forName(PAGE_PACKAGE + SEPARATOR + item.getCode() + PAGE); } } 

MenuCategory

 public class MenuCategory implements Serializable { private final IModel<String> label; private final Class<? extends Page> page; public MenuCategory(IModel<String> textLabel, Class<? extends Page> page) { this.label = textLabel; this.page = page; } public IModel<String> getLabel() { return label; } public Class<? extends Page> getPage() { return page; } } 

When initListView() executed, initListView() get this exception:

org.jboss.weld.exceptions.IllegalArgumentException: WELD-000070 Simple bean [EnhancedAnnotatedTypeImpl] class cannot be a non-static class

Something remotely similar google / saw - someone referred to cdi. I tried different versions of the wicket - the problem is the same. Maybe my code is not correct? Please help

    2 answers 2

    Maybe because of this, the org.jboss.weld.exceptions.IllegalArgumentException: WELD-000070 Simple bean [EnhancedAnnotatedTypeImpl] class cannot be a non-static inner class

    If you expect that the menuItemHelper in the MenuPanel class will be initialized using the CDI at the time of the first use of this field, then you are badly mistaken.

    As we can see, menuItemHelper used in the initListView method, which is called from the constructor. So, CDI fills in the fields only after working out the constructor. So in the absence of other errors, you would have to get a NullPointerException.

    In order to perform initialization with CDI, an initialization method is created with the @PostConstruct annotation. Then CDI will execute it after calling the constructor and injecting dependencies.

     public class MenuPanel { @Inject private MenuItemHelper menuItemHelper; public MenuPanel() { // Здесь @Inject поля ещё не тронуты CDI } ... @PostConstruct public void init() { // Здесь все @Inject поля уже заполнены CDI } ... 

    Another error is that CDI uses a parameterless constructor, which is not observed for the MenuPanel class. As at the same time swears CDI, I do not even remember.

    • Answered below deployed. But in general, confuses - and how will you transmit the component id? if you only have a default constructor. And injecting the fields goes, not the MenuPanel itself. Here, with the initialization of the CDI fields, I strongly disagree, and this is a confirmation of that (and logging too). I have a project with old libs - and there similar constructions work out. In other classes of the current project there are logging-type injections, and even in this class everything is OK - everything is written - if, for example, I remove the ListView and insert the usual Label. And there is no, and I can not yet reveal the difference - Artem Bardakov
    • So wicket is probably messing with cdi. I won't say anything about wicket, because I don't know. - Sergey

    If you expect that the menuItemHelper in the MenuPanel class will be initialized using the CDI at the time of the first use of this field, then you are badly mistaken.

    As we can see, menuItemHelper is used in the initListView method, which is called from the constructor. So, CDI fills in the fields only after working out the constructor. So in the absence of other errors, you would have to get a NullPointerException.

    In my opinion, you are badly mistaken, I use such initialization in more than one application, and there is no NPE there — CDI initializes everything perfectly at the right moment. Even here I was going through the debugger - I get all the menu items and the menuItemHelper is initialized and operational.

    Now another moment

    Another error is that CDI uses a parameterless constructor, which is not observed for the MenuPanel class. As at the same time swears CDI, I do not even remember.

    Why does CDI go to MenuPanel ??? I do not use the injection to create it - (created manually - the constructor is called)

     public abstract class BasePage extends WebPage { protected HeaderPanel headerPanel; protected FooterPanel footerPanel; protected MenuPanel menuPanel; protected BasePage() { super(); initBasePage(); } protected final void initBasePage() { add(headerPanel = new HeaderPanel("headerPanel")); add(menuPanel = new MenuPanel("menuPanel")); add(footerPanel = new FooterPanel("footerPanel")); } } 

    The injection passes inside the panel. It turns out either an error in another, or it is not clear why the container wants to create a MenuPanel