Setup

Einrichtung des Faktor-IPS-Product Designers mit eigenen Produktprojekten

Im Folgenden wird der Prozess zur manuellen Einrichtung des Produktdesigners als lokale Spring-Boot-Anwendung mit eigenen Produktprojekten, sowie zur anschließenden Bereitstellung via Docker-Deployment beschrieben.

Aktualisieren der Faktor-IPS Dependencies:

Der Produkt Designer setzt die neueste Faktor-IPS-Version (24.7) sowie Java 21 voraus . Im ersten Schritt müssen daher zunächst die Faktor-IPS-Dependencies aktualisiert und zudem in einem passenden Eclipse via der Updatesite das aktuelle Faktor-IPS installiert und nachfolgend die Modellprojekte einmal neu gebaut werden.

Für weitere Informationen zu Kompatibilitäten zwischen Faktor-IPS und Eclipse bitte diese Übersicht beachten.

Anlage eines Maven-Projekts:

Im zweiten Schritt wird ein neues Maven-Projekt mit Dependencies für den Product Designer, Modellprojekte und Spring-Boot-Starter angelegt.

Bitte beachten: Neben der im Folgenden beschriebenen manuellen Anlage, besteht auch die Möglichkeit, ein Maven Product Designer-Projekt mithilfe eines Archetypes zu generieren. Weitere Informationen dazu sind im Kapitel 'Produkt Designer Archetype' beschrieben.

Dependencies:

Productdesigner-Web:

  <dependencies>
        <dependency>
            <groupId>org.faktorips.productdesigner</groupId>
            <artifactId>productdesigner-web</artifactId>
            <version>24.7.0</version>
        </dependency>
  </dependencies>

Gewünschte Modellabhängigkeiten hinzufügen – z. B.:

 <dependencies>
        <dependency>
            <groupId>de.faktorzehn.muster.shu-gewerbe</groupId>
            <artifactId>vm-gewerbe-gruppenunfall-produktmodellerw</artifactId>
            <version>24.7.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>de.faktorzehn.muster.shu-gewerbe</groupId>
            <artifactId>vm-gewerbe-basis-produkte</artifactId>
            <version>24.7.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
 </dependencies>

In der Spring-Boot-Plugin-Configuration wird die im nachfolgenden Schritt erstellte Product Designer-Applikation eingetragen:

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <wait>500</wait>
                    <maxAttempts>240</maxAttempts>
                    <!-- HIER die Product-Designer-Application eintragen (s.u.) -->
                    <mainClass>org.faktorips.productdesigner.demo.SampleProductDesignerApplication</mainClass>
                    <layout>JAR</layout>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

Nachfolgend eine beispielhafte pom.xml eines Produkt Designer-Maven-Projekts:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>de.faktorzehn.commons</groupId>
        <artifactId>f10-suite-starter-spring</artifactId>
        <version>24.7.0</version>
    </parent>
    <groupId>org.faktorips.productdesigner</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>21</java.version>
        <maven.compiler.release>${java.version}</maven.compiler.release>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <faktorips.version>24.7.0</faktorips.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.faktorips.productdesigner</groupId>
            <artifactId>productdesigner-web</artifactId>
            <version>24.7.0</version>
        </dependency>
        <!-- HIER MODELL-Dependencie(s) angeben -->
        <dependency>
            <groupId>de.faktorzehn.muster.shu-gewerbe</groupId>
            <artifactId>vm-gewerbe-gruppenunfall-produktmodellerw</artifactId>
            <version>24.7.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>de.faktorzehn.muster.shu-gewerbe</groupId>
            <artifactId>vm-gewerbe-basis-produkte</artifactId>
            <version>24.7.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
    </dependencies>
    <build>
        <defaultGoal>spring-boot:run</defaultGoal>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <wait>500</wait>
                    <maxAttempts>240</maxAttempts>
                    <!-- HIER die Product-Designer-Application angeben (s.u.) -->
                    <mainClass>org.faktorips.productdesigner.demo.SampleProductDesignerApplication</mainClass>
                    <layout>JAR</layout>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>prepare-frontend</goal>
                        </goals>
                        <phase>compile</phase>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Anlage einer SpringBoot-Application-Klasse

Nun wird eine Application-Klasse angelegt, welche im Anschluss in der pom.xml in der Konfiguration des spring-boot-maven-plugin eingetragen wird. Beispiel: SampleProductDesignerApplication.java:

import com.vaadin.flow.component.page.AppShellConfigurator;
import com.vaadin.flow.server.AppShellSettings;
import com.vaadin.flow.spring.annotation.EnableVaadin
import com.vaadin.flow.theme.Theme;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.faktorips.productdesigner.core.ProductDesigner;
import org.faktorips.productdesigner.core.ProductDesignerConfigurationProperties;

@Theme(value = "productdesigner", variant = "card-section-pages")
@SpringBootApplication(scanBasePackages = ProductDesigner.BASE_PACKAGE)
@EnableConfigurationProperties(ProductDesignerConfigurationProperties.class)
@EnableVaadin(value = ProductDesigner.BASE_PACKAGE)
public class SampleProductDesignerApplication implements AppShellConfigurator {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        SpringApplication.run(SampleProductDesignerApplication.class, args);
    }

    @Override
    public void configurePage(AppShellSettings settings) {
        settings.addFavIcon("icon", "../favicon.ico", "48x48");
    }
}

Anlegen der Config und einbinden zusätzlicher Repositories

Unter src/main/resources/ wird nun eine application.yml angelegt:

logging:
  level:
    org.springframework: WARN

server:
  port: 8080

vaadin:
  urlMapping: '/ui/*'
  launch-browser: true

ips-product-designer:
  ips-project-path: ../../../git/mustercontent/vm/vm.shu.gewerbe/gruppenunfall/produkte/
  additional-repos:
    - de.faktorzehn.versicherungsmodell.gw.produkte.GwProduktClassloaderRuntimeRepository
    - de.faktorzehn.versicherungsmodell.gw.produkte.GwAllgemeinClassloaderRuntimeRepository
  read-only-mode: false

Im Abschnitt additional-repos werden Repositories, von denen das Produktprojekt abhängt, durch ihre Klassenreferenzen eingebunden.

Damit diese zur Laufzeit korrekt geladen werden, sollte je Repository eine Klasse mit einem INSTANCE-Field für ein IRuntimeRepository oder IRuntimeRepositoryLookup enthalten sein.

Am Beispiel des in der .yml referenzierten Repositories sieht die Klasse GwProduktClassloaderRuntimeRepository zur Bereitstellung und Konfiguration des Singleton-Repositories wie folgt aus:

import org.faktorips.runtime.ClassloaderRuntimeRepository;
import org.faktorips.runtime.formula.groovy.GroovyFormulaEvaluatorFactory;

public class GwProduktClassloaderRuntimeRepository {

    public static final ClassloaderRuntimeRepository INSTANCE = ClassloaderRuntimeRepository
            .create("de/faktorzehn/versicherungsmodell/gw/produkte/internal/faktorips-repository-toc.xml");

    static {
        INSTANCE.addDirectlyReferencedRepository(GwAllgemeinClassloaderRuntimeRepository.INSTANCE);
        INSTANCE.setFormulaEvaluatorFactory(new GroovyFormulaEvaluatorFactory());
    }

    private GwProduktClassloaderRuntimeRepository() {
        // Soll nicht instanziiert werden
    }

}

Zunächst wird eine ClassloaderRuntimeRepository INSTANCE, auf Basis der zugehörigen toc.xml initialisiert. Im statischen Initialisierungsblock werden dann notwendige, referenzierte Repositories über ihre jeweiligen Instanzen eingebunden (INSTANCE.addDirectlyReferencedRepository(GwAllgemeinClassloaderRuntimeRepository.INSTANCE);), sowie zusätzlich auch Konfigurationen für die Repository Instanz definiert (INSTANCE.setFormulaEvaluatorFactory(new GroovyFormulaEvaluatorFactory());).

Favicon hinzufügen

Um schließlich im Browser-Tab Icons der Anwendung anzeigen zu lassen, wird optional ein Favicon in src/main/resources/static abgelegt.

Docker-Deployment

Beim Bereitstellen und Deployen der Anwendung in Docker-Containern ist zu berücksichtigen, dass die Anwendung als .jar deployt wird, die Produktdaten jedoch in entpackter Form in den Container kopiert und konfiguriert werden. Hierfür muss zunächst in der pom.xml der vaadin.productionMode auf true gesetzt werden.

<profiles>
    <profile>
        <id>production</id>
        <properties>
            <vaadin.productionMode>true</vaadin.productionMode>
        </properties>
        <build>
            <plugins>
                <plugin>
                    <groupId>com.vaadin</groupId>
                    <artifactId>vaadin-maven-plugin</artifactId>
                    <version>${vaadin.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>prepare-frontend</goal>
                                <goal>build-frontend</goal>
                            </goals>
                            <phase>compile</phase>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

Beispiel Dockerfile:

FROM eclipse-temurin:21-jre-jammy
RUN apt-get update \
    && ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime \
    && dpkg-reconfigure -f noninteractive tzdata
ARG UID=999
ARG GID=999
ENV JAVA_TOOL_OPTIONS "-Xms480m -Xmx1024m"
RUN groupadd --gid $GID spring \
    && useradd -r -m -d /opt/spring -s /sbin/nologin --gid $GID --uid $UID -c "Spring user" spring \
    && chmod 755 /opt/spring \
    && mkdir -p /var/opt/spring \
    && chown spring: /var/opt/spring \
    && chmod 755 /var/opt/spring
WORKDIR /opt/spring
COPY ${PATH_TO_APPLICATION_JAR} application.jar
COPY ${PATH_TO_PRODUCT_FOLDER} /var/opt/spring/produkte
RUN chown -R spring: /var/opt/spring
USER $UID
EXPOSE 8080
CMD ["java", \
    "-Dspring.profiles.active=production", \
    "-jar", \
    "application.jar", \
    "--server.port=8080", \
    "--server.forward-headers-strategy=FRAMEWORK"]

Beispiel docker-compose.yml:

version: '2.4'

services:
  productdesigner-sample:
    container_name: ${CONTAINER_NAME}-sample
    build:
      context: ../
      dockerfile: ./path/to/Dockerfile
      args:
      - PATH_TO_APPLICATION_JAR=${PATH_TO_APPLICATION_JAR}
      - PATH_TO_PRODUCT_FOLDER=${PATH_TO_PRODUCT_FOLDER}
    environment:
      SPRING_PROFILES_ACTIVE: production
      ips-product-designer.ips-project-path: /var/opt/spring/produkte
    labels:
      url: ${CONTAINER_NAME}-sample
      entry-path: ui

networks:
    default:
        name: network-${CONTAINER_NAME}
        labels:
            retention: ${CONTAINER_RETENTION}