faktor ips 找不到产品组件 class

faktor ips cannot find product component class

我想用 Faktor IPS 做一个既是模型项目又是产品定义项目的项目。我想和 UI 使用 Linkki。这是我的项目结构:

Project structure(堆栈溢出不允许我添加图像,我希望 link 有效)

在 src/main/java 文件夹中是制作 linkki UI 和 .model.hausrat[= 的 classes 56=] 是 faktor ips 生成策略组件代码的包。

策略组件和产品组件在rg/linkki_framework/fips/Hausrat_linkki_app/model/internal/faktorips-repository-toc.xml

下文件夹src/main/resources中的faktorips-repository-toc.xml

这是它的样子:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<FaktorIps-TableOfContents productDataVersion="0.0.1" xmlversion="3.0">
 <ProductComponent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.deckungen.Fahrraddiebstahl___2022__01" ipsObjectId="beispiel.Fahrraddiebstahl 2022-01" ipsObjectQualifiedName="deckungen.Fahrraddiebstahl 2022-01" kindId="beispiel.Fahrraddiebstahl" versionId="2022-01" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/deckungen/Fahrraddiebstahl 2022-01.xml"/>
 <ProductComponent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratGrunddeckungstyp" ipsObjectId="beispiel.HRD-Kompakt 2022-01" ipsObjectQualifiedName="deckungen.HRD-Kompakt 2022-01" kindId="beispiel.HRD-Kompakt" versionId="2022-01" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/deckungen/HRD-Kompakt 2022-01.xml"/>
 <ProductComponent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratGrunddeckungstyp" ipsObjectId="beispiel.HRD-Optimal 2022-01" ipsObjectQualifiedName="deckungen.HRD-Optimal 2022-01" kindId="beispiel.HRD-Optimal" versionId="2022-01" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/deckungen/HRD-Optimal 2022-01.xml"/>
 <ProductComponent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.deckungen.Ueberspannung___2022__01" ipsObjectId="beispiel.Ueberspannung 2022-01" ipsObjectQualifiedName="deckungen.Ueberspannung 2022-01" kindId="beispiel.Ueberspannung" versionId="2022-01" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/deckungen/Ueberspannung 2022-01.xml"/>
 <PolicyCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Deckung" ipsObjectId="hasurat.Deckung" ipsObjectQualifiedName="hasurat.Deckung"/>
 <ProductCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Deckungstyp" ipsObjectId="hasurat.Deckungstyp" ipsObjectQualifiedName="hasurat.Deckungstyp"/>
 <PolicyCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratGrunddeckung" ipsObjectId="hasurat.HausratGrunddeckung" ipsObjectQualifiedName="hasurat.HausratGrunddeckung"/>
 <ProductCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratGrunddeckungstyp" ipsObjectId="hasurat.HausratGrunddeckungstyp" ipsObjectQualifiedName="hasurat.HausratGrunddeckungstyp"/>
 <ProductCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratProdukt" ipsObjectId="hasurat.HausratProdukt" ipsObjectQualifiedName="hasurat.HausratProdukt"/>
 <PolicyCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratVertrag" ipsObjectId="hasurat.HausratVertrag" ipsObjectQualifiedName="hasurat.HausratVertrag"/>
 <PolicyCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratZusatzdekung" ipsObjectId="hasurat.HausratZusatzdekung" ipsObjectQualifiedName="hasurat.HausratZusatzdekung"/>
 <ProductCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratZusatzdekungstyp" ipsObjectId="hasurat.HausratZusatzdekungstyp" ipsObjectQualifiedName="hasurat.HausratZusatzdekungstyp"/>
 <ProductCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Produkt" ipsObjectId="hasurat.Produkt" ipsObjectQualifiedName="hasurat.Produkt"/>
 <PolicyCmptType implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Vertrag" ipsObjectId="hasurat.Vertrag" ipsObjectQualifiedName="hasurat.Vertrag"/>
 <EnumContent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Zahlweise" ipsObjectId="modell.hasurat.Zahlweise" ipsObjectQualifiedName="hasurat.Zahlweise.Type"/>
 <ProductComponent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratProdukt" ipsObjectId="beispiel.HR-Kompakt 2022-01" ipsObjectQualifiedName="produkt.HR-Kompakt 2022-01" kindId="beispiel.HR-Kompakt" versionId="2022-01" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/produkt/HR-Kompakt 2022-01.xml"/>
 <ProductComponent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.HausratProdukt" ipsObjectId="beispiel.HR-Optimal 2022-01" ipsObjectQualifiedName="produkt.HR-Optimal 2022-01" kindId="beispiel.HR-Optimal" versionId="2022-01" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/produkt/HR-Optimal 2022-01.xml"/>
 <TableContent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Tariftabelle" ipsObjectId="tabellen.Tariftabelle Kompakt" ipsObjectQualifiedName="tabellen.Tariftabelle Kompakt" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/tabellen/Tariftabelle Kompakt.xml"/>
 <TableContent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Tariftabelle" ipsObjectId="tabellen.Tariftabelle Optimal" ipsObjectQualifiedName="tabellen.Tariftabelle Optimal" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/tabellen/Tariftabelle Optimal.xml"/>
 <TableContent implementationClass="org.linkki_framework.fips.Hausrat_linkki_app.model.hasurat.Tarifzonentabelle" ipsObjectId="tabellen.Tarifzonentabelle" ipsObjectQualifiedName="tabellen.Tarifzonentabelle" xmlResource="org/linkki_framework/fips/Hausrat_linkki_app/model/tabellen/Tarifzonentabelle.xml"/>
</FaktorIps-TableOfContents>

有一次我尝试获取所有产品组件的列表,这些组件是 HausratProdukt 的实例。像这样:

private final List<HausratProdukt> produkte;
private IRuntimeRepository repository;

this.repository = PolicyRuntimeRepositoryLookup.getInstance().getRuntimeRepository();
this.produkte = repository.getAllProductComponents(HausratProdukt.class);

class PolicyRuntimeRepositoryLookup 看起来像这样:

public class PolicyRuntimeRepositoryLookup implements IRuntimeRepositoryLookup {

    private static final long serialVersionUID = 1L;

    private static final PolicyRuntimeRepositoryLookup SINGLETON = new PolicyRuntimeRepositoryLookup();

    private static final String TOC_PATH = "org/linkki_framework/fips/Hausrat_linkki_app/model/internal/faktorips-repository-toc.xml";
                                        //"de/faktorzehn/ipm/core/model/internal/faktorips-repository-toc.xml";

    private transient IRuntimeRepository runtimeRepository;

    private PolicyRuntimeRepositoryLookup() {
        runtimeRepository = ClassloaderRuntimeRepository.create(TOC_PATH);
    }

    public static PolicyRuntimeRepositoryLookup getInstance() {
        return SINGLETON;
    }

    @Override
    public IRuntimeRepository getRuntimeRepository() {
        return runtimeRepository;
    }

    private Object readResolve() {
        return SINGLETON;
    }
}

它在以下行崩溃:

this.produkte = repository.getAllProductComponents(HausratProdukt.class);

出现以下错误:

java.lang.RuntimeException: Can't load class org.linkki_framework.fips.Hausrat_linkki_app.model.deckungen.Ueberspannung___2022__01
    at org.faktorips.runtime.internal.AbstractTocBasedRuntimeRepository.getClass(AbstractTocBasedRuntimeRepository.java:272)
    at org.faktorips.runtime.internal.AbstractClassLoadingRuntimeRepository.getAllProductComponentsInternal(AbstractClassLoadingRuntimeRepository.java:329)
    at org.faktorips.runtime.internal.AbstractRuntimeRepository.getAllProductComponents(AbstractRuntimeRepository.java:265)
    at org.linkki_framework.fips.Hausrat_linkki_app.pmo.AngebotSectionPmo.<init>(AngebotSectionPmo.java:44)
    at org.linkki_framework.fips.Hausrat_linkki_app.page.AngebotPage.createContent(AngebotPage.java:37)
    at org.linkki_framework.fips.Hausrat_linkki_app.view.AngebotView.enter(AngebotView.java:47)
    at com.vaadin.navigator.Navigator.performNavigateTo(Navigator.java:778)
    at com.vaadin.navigator.Navigator.lambda$navigateToa874efd(Navigator.java:702)
    at com.vaadin.navigator.ViewBeforeLeaveEvent.navigate(ViewBeforeLeaveEvent.java:54)
    at com.vaadin.navigator.View.beforeLeave(View.java:79)
    at com.vaadin.navigator.Navigator.runAfterLeaveConfirmation(Navigator.java:730)
    at com.vaadin.navigator.Navigator.navigateTo(Navigator.java:701)
    at com.vaadin.navigator.Navigator.navigateTo(Navigator.java:678)
    at org.linkki_framework.fips.Hausrat_linkki_app.menu.AngebotMenuItem.lambda[=15=](AngebotMenuItem.java:27)
    at com.vaadin.ui.MenuBar.changeVariables(MenuBar.java:210)
    at com.vaadin.server.communication.ServerRpcHandler.changeVariables(ServerRpcHandler.java:616)
    at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:468)
    at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:411)
    at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:275)
    at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:91)
    at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
    at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1637)
    at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:464)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.ClassNotFoundException: org.linkki_framework.fips.Hausrat_linkki_app.model.deckungen.Ueberspannung___2022__01
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    at org.faktorips.runtime.internal.AbstractTocBasedRuntimeRepository.getClass(AbstractTocBasedRuntimeRepository.java:269)
    ... 60 more

我注意到 faktorips-repository-toc.xml 使用任何策略 class 的 implementationClass 保存产品组件,它们是

的一个实例

例如beispiel.HRD-Kompakt 2022-1有一个实现类...hasurat.HausratGrunddeckungstyp,但是那些实际上是 Zusatzdeckungstyp 实例的产品组件保存在 toc.xml 文件中,并在 implementationClass 中使用它们的实际名称。

例如 ...deckungen.Ueberspannung___2022__01 而不是 ...hasurat.HausratZusatzdekungstyp,我实际上会期望。

我不知道为什么它只以不同的方式保存这些,或者如何更改它,因为这是 faktor ips 的内置组件。

也许内置方法 repository.getAllProductComponents(...) 在 src/main/java 文件夹(所有其他 classes 所在的文件夹)中搜索 classes 并且没有在 src/main/resources 文件夹中找不到这些特定的?

但这也是自动生成的,我不知道如何更改它。当然,我可以手动将 classes 移动到 src/main/java 文件夹中,但这有点违背了自动生成它的目的。有人可以帮忙吗?

具体实现的原因类是因为你在那些产品中使用了公式。使用带 Faktor-IPS 的公式时,有两个选项:

  1. 为它们生成和编译 Java 代码
  2. 在他们的 XML 文件中生成 Java 代码并在运行时用 Groovy 公式计算器解释它

您可以选择在 'Faktor-IPS Code Generator Settings' 中的项目中使用哪个选项(右键单击项目 -> 属性 -> 'Faktor-IPS Code Generator Settings' 或在 .ipsproject 的 XML文件)。对于第一个选项,属性 'Formula Compiling' 可以设置为 'Subclass',对于第二个选项,可以设置为 'XML'。默认值 'Both' 会像第一个选项一样生成 table-of-contents-entries 和 Java 类,并且会像第二个选项一样在 XML 中生成 Java 代码。

在您的项目中使用 Maven 时,您需要适应您选择的变体。对于变体 1,您需要确保 src/main/resources 中的 Java 文件也按照 https://www.faktorzehn.org/dokumentation/verwendung-von-faktor-ips-projekten-als-maven-dependencies/ 中的描述进行编译:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals><goal>add-source</goal></goals>
            <configuration>
                <sources>
                    <source>${project.basedir}/derived</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

如果您选择第二个选项,您需要添加对 https://mvnrepository.com/artifact/org.faktorips/faktorips-runtime-groovy 的依赖,并将公式计算器添加到您的存储库

repository.setFormulaEvaluatorFactory(new GroovyFormulaEvaluatorFactory());