为什么在我的 Vaadin Spring Boot 应用程序中 @PostConstruct 期间 ApplicationProperties 为 null?

问题描述 投票:0回答:1

我正在使用 Spring Boot 开发 Vaadin 应用程序,并且在 MenuLayout 类中的 @PostConstruct 方法期间遇到了 ApplicationProperties 为 null 的问题。这会导致菜单项无法正确设置,并且我在日志中看到以下警告:

2024-09-03T13:09:08.059+03:00  WARN 6988 --- [io-8080-exec-10] c.r.application.layouts.MenuLayout       : ApplicationProperties is null. Menu items will not be set up.
2024-09-03T13:09:08.067+03:00  INFO 6988 --- [io-8080-exec-10] c.r.a.config.ApplicationProperties       : Unique Categories with Folders: {Transactions=[ObjectTransfers], Organizations=[Organization, Department], Metadata=[ResearcherComment, InfoText], Occurrences=[Event], Sources=[BookSource, OralHistorySource, ArchivalSources, WebSources, SourcePassageCollection, NewspaperPeriodical, Bibliography, SourcePassage], Entities=[Material, Persons, Objects, Collection, Route, DigitalObject, Objects]}

这是我的 MenuLayout 类的相关代码:

@Lazy
@Component
@DependsOn("applicationProperties")
public class MenuLayout extends HybridMenu implements RouterLayout {

    private static final long serialVersionUID = 1L;
    private static final Logger logger = Logger.getLogger(MenuLayout.class.getName());

    private final ApplicationProperties appProperties;

    @Autowired
    public MenuLayout(@Qualifier("applicationProperties") ApplicationProperties appProperties) {
        this.appProperties = appProperties;
    }

    @PostConstruct
    public void postConstruct() {
        // Check if ApplicationProperties is null
        if (this.appProperties == null) {
            logger.log(Level.SEVERE, "ApplicationProperties is null in postConstruct of MenuLayout.");
            throw new IllegalStateException("ApplicationProperties is null in postConstruct of MenuLayout.");
        }

        // Ensure VaadinSession is available
        VaadinSession vaadinSession = VaadinSession.getCurrent();
        if (vaadinSession == null) {
            throw new IllegalStateException("VaadinSession is not available.");
        }

        // Initialize the menu
        init(vaadinSession, UI.getCurrent());
    }

    @Override
    public boolean init(VaadinSession vaadinSession, UI ui) {
        initMenu();
        return true;
    }

    private void initMenu() {
        withConfig(new MenuConfig());
        getConfig().setTheme(ETheme.Lumo);

        if (appProperties != null) {
            setupMenuItems();
        } else {
            logger.log(Level.WARNING, "ApplicationProperties is null. Menu items will not be set up.");
        }
    }

    private void setupMenuItems() {
        // Menu setup code...
    }
}

这是应用程序属性:

package com.ricontrans.application.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@Primary
@Component
@ConfigurationProperties(prefix = "application")
public class ApplicationProperties {
    private final Map<String, Category> acceptedCategories = new HashMap<>();
    private final List<Description> descriptions = new ArrayList<>();
    private static final Logger logger = Logger.getLogger(ApplicationProperties.class.getName());

    public ApplicationProperties() {
        logger.log(Level.INFO, "ApplicationProperties constructor called.");
        loadProperties();
    }

    private void loadProperties() {
        logger.log(Level.INFO, "Loading properties from configuration.properties.");
        Properties properties = new Properties();
        try (InputStream input = getClass().getClassLoader().getResourceAsStream("configuration.properties")) {
            if (input == null) {
                logger.log(Level.WARNING, "configuration.properties not found.");
                return;
            }
            properties.load(input);

            // Load accepted categories (existing functionality)
            properties.forEach((key, value) -> {
                String keyString = (String) key;
                String valueString = (String) value;

                String[] keyParts = keyString.split("\\.");
                if (keyParts.length == 4 && "acceptedCategories".equals(keyParts[1])) {
                    String categoryName = keyParts[2];
                    String property = keyParts[3];

                    // Ensure that the category exists
                    Category category = acceptedCategories.computeIfAbsent(categoryName, k -> new Category());

                    // Update the category based on the property
                    switch (property) {
                        case "folder":
                            category.setFolder(valueString);
                            break;
                        case "schema":
                            category.setSchema(valueString);
                            break;
                        case "label":
                            category.setLabel(valueString);
                            break;
                        case "icon":
                            category.setIcon(valueString);
                            break;
                        case "tableProperties":
                            category.setTableProperties(valueString);
                            break;
                        case "Pie":
                            category.setPie(valueString);
                            break;
                        case "PieCategories":
                            category.setPieCategories(valueString);
                            break;
                        case "Map":
                            category.setMap(valueString);
                            break;
                        case "Time":
                            category.setTime(valueString);
                            break;
                        case "chartTypes":
                            category.setChartTypes(valueString);
                            break;
                        case "category":
                            category.setCategory(valueString);
                            break;
                        default:
                            break;
                    }
                }
            });

            logger.log(Level.INFO, "Accepted Categories: {0}", acceptedCategories);

            // Load descriptions for texts and images (new functionality)
            int index = 1;
            while (true) {
                String textPath = properties.getProperty("application.description." + index + ".text");
                String imagePath = properties.getProperty("application.description." + index + ".image");

                if (textPath == null && imagePath == null) {
                    break; // No more descriptions to load
                }

                Description description = new Description();
                if (textPath != null) {
                    description.setTextPath(textPath);
                    description.setLeft(Boolean.parseBoolean(properties.getProperty("application.description." + index + ".text.left", "false")));
                    description.setCenter(Boolean.parseBoolean(properties.getProperty("application.description." + index + ".text.center", "false")));
                    description.setRight(Boolean.parseBoolean(properties.getProperty("application.description." + index + ".text.right", "false")));
                }

                if (imagePath != null) {
                    description.setImagePath(imagePath);
                    description.setLeft(Boolean.parseBoolean(properties.getProperty("application.description." + index + ".image.left", "false")));
                    description.setCenter(Boolean.parseBoolean(properties.getProperty("application.description." + index + ".image.center", "false")));
                    description.setRight(Boolean.parseBoolean(properties.getProperty("application.description." + index + ".image.right", "false")));
                }

                description.setAlignWithLast(Boolean.parseBoolean(properties.getProperty("application.description." + index + ".alignWithLast", "false")));

                descriptions.add(description);
                index++;
            }

            logger.log(Level.INFO, "Descriptions loaded: {0}", descriptions);

        } catch (IOException ex) {
            logger.log(Level.SEVERE, "IOException occurred while loading properties", ex);
        }
    }

    public Map<String, Category> getAcceptedCategories() {
        return acceptedCategories;
    }

    public List<Description> getDescriptions() {
        return descriptions;
    }

    public String getCategoryFolder(String categoryName) {
        Category category = acceptedCategories.get(categoryName);
        return category != null ? category.getFolder() : null;
    }

    public Map<String, List<String>> getUniqueCategoriesWithFolders() {
        Map<String, List<String>> categoryFoldersMap = new HashMap<>();

        acceptedCategories.values().forEach(category -> {
            String categoryName = category.getCategory();
            String folder = category.getFolder();

            if (categoryName != null && folder != null) {
                // Get the list of folders for this category, or create a new one if it doesn't exist
                List<String> folders = categoryFoldersMap.computeIfAbsent(categoryName, k -> new ArrayList<>());
                // Add the folder to the list
                folders.add(folder);
            }
        });

        logger.log(Level.INFO, "Unique Categories with Folders: {0}", categoryFoldersMap);
        return categoryFoldersMap;
    }

    public static class Category {
        private String folder;
        private String schema;
        private String label;
        private String icon;
        private String tableProperties;
        private String Pie;
        private String PieCategories;
        private String Time;
        private String Map;
        private String chartTypes;
        private String category;
        private Properties properties = new Properties();

        // Getters and setters
        public String getFolder() {
            return folder;
        }

        public void setFolder(String folder) {
            this.folder = folder;
        }

        public String getSchema() {
            return schema;
        }

        public void setSchema(String schema) {
            this.schema = schema;
        }

        public String getLabel() {
            return label;
        }

        public void setLabel(String label) {
            this.label = label;
        }

        public String getIcon() {
            return icon;
        }

        public void setIcon(String icon) {
            this.icon = icon;
        }

        public String getTableProperties() {
            return tableProperties;
        }

        public void setTableProperties(String tableProperties) {
            this.tableProperties = tableProperties;
        }

        public String getPie() {
            return Pie;
        }

        public void setPie(String pie) {
            Pie = pie;
        }

        public String getPieCategories() {
            return PieCategories;
        }

        public void setPieCategories(String pieCategories) {
            PieCategories = pieCategories;
        }

        public String getTime() {
            return Time;
        }

        public void setTime(String time) {
            Time = time;
        }

        public String getMap() {
            return Map;
        }

        public void setMap(String map) {
            Map = map;
        }

        public String getChartTypes() {
            return chartTypes;
        }

        public void setChartTypes(String chartTypes) {
            this.chartTypes = chartTypes;
        }

        public String getCategory() {
            return category;
        }

        public void setCategory(String category) {
            this.category = category;
        }

        @Override
        public String toString() {
            return "Category{" +
                    "folder='" + folder + '\'' +
                    ", schema='" + schema + '\'' +
                    ", label='" + label + '\'' +
                    ", icon='" + icon + '\'' +
                    ", tableProperties='" + tableProperties + '\'' +
                    ", Pie='" + Pie + '\'' +
                    ", PieCategories='" + PieCategories + '\'' +
                    ", Time='" + Time + '\'' +
                    ", Map='" + Map + '\'' +
                    ", chartTypes='" + chartTypes + '\'' +
                    ", category='" + category + '\'' +
                    '}';
        }
    }

    public static class Description {
        private String textPath;
        private String imagePath;
        private boolean left;
        private boolean center;
        private boolean right;
        private boolean alignWithLast;
        private String image;
        private String text;

        // Getters and setters
        public String getTextPath() {
            return textPath;
        }

        public void setTextPath(String textPath) {
            this.textPath = textPath;
        }

        public String getImagePath() {
            return imagePath;
        }

        public void setImagePath(String imagePath) {
            this.imagePath = imagePath;
        }

        public boolean isLeft() {
            return left;
        }

        public void setLeft(boolean left) {
            this.left = left;
        }

        public boolean isCenter() {
            return center;
        }

        public void setCenter(boolean center) {
            this.center = center;
        }

        public boolean isRight() {
            return right;
        }

        public void setRight(boolean right) {
            this.right = right;
        }

        public boolean isAlignWithLast() {
            return alignWithLast;
        }

        public void setAlignWithLast(boolean alignWithLast) {
            this.alignWithLast = alignWithLast;
        }

        @Override
        public String toString() {
            return "Description{" +
                    "textPath='" + textPath + '\'' +
                    ", imagePath='" + imagePath + '\'' +
                    ", left=" + left +
                    ", center=" + center +
                    ", right=" + right +
                    ", alignWithLast=" + alignWithLast +
                    '}';
        }

        public String getImage() {
            return image;
        }

        public void setImage(String image) {
            this.image = image;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }
    }
}

我在这里试图实现的主要功能是我可以为我的所有视图设置一个动态布局混合菜单,并且有关菜单选项的信息在configuration.properties文件中设置,其中加载这些属性都完成到ApplicationProperties.java中! 所以我猜测这里的问题是,由于某种原因,menulayout 总是首先从 applicationProperties 初始化,因为它们都是组件,也许它需要先完成一些工作。

我尝试了很多事情,如你所见:

  • 延迟加载

  • 取决于应用程序属性

  • 构建后。

    另外,如果我删除 post 构造方法,我会遇到一个有关 VaadinSession 为空的问题,因为菜单布局被标记为组件,并且会话目前不可用!

java spring-boot components vaadin vaadin24
1个回答
0
投票

让我们来剖析一下这个问题:

  • if If
    postconstruct
    运行它应该抛出,如果
    appProperties
    是 空
  • 但它似乎很高兴地工作并调用了
    init
    ,它再次调用
    initMenu
  • inside
    initMenu
    appProperties
    现在为空,但它是最终的并且 除了c'tor应该能够改变它之外什么都没有

任何一件事都必须为真:

  • 这不是[MRE]
  • 日志输出并不代表完整的时间线,事实上 是两个不同的物体在起作用

对于后者,有一个解释:

RouterLayout
由 Spring 间接管理,但直接通过 Vaadin 管理 -- 访问该站点将为该站点创建视图及其布局 通过
Instantiator
设施查看。 如果 Spring 正在发挥作用,则相反
DefaultInstantiator
SpringInstantiator
最终会做 工作。

但是没有必要/需要为 Spring-DI 配置

RouterLayout
和 在这里它只会造成伤害。

  • @Lazy
    会将实例延迟到需要时;瓦丁需要 照顾这个
  • @Component
    使其成为单例,必须删除
  • @DependsOn("applicationProperties")
    充其量是没用的 最坏的情况是出现问题,因为布局是由于使用而实现的 在
    @Route
    注释中

所以除非这里有其他东西在起作用,否则我希望这能起作用一次 所有注释均从

RouterLayout
中删除。

© www.soinside.com 2019 - 2024. All rights reserved.