Setup

Manuelles Einrichten des Faktor-IPS Product Designers mit eigenen Produktprojekten

Im Folgenden wird beschrieben, was notwendig ist, um den Produkt Designer manuell einzurichten. Es wird jedoch empfohlen, den Product Designer über den Archetype, wie im Kapitel 'Product Designer Archetype' beschrieben, zu erstellen. Das erspart viele der folgenden beschriebenen Schritte.

Voraussetzungen:

Der Product Designer setzt die neueste Faktor-IPS-Version (25.1) sowie Java 21 voraus. Im ersten Schritt müssen daher zunächst die Faktor-IPS-Dependencies im Eclipse aktualisiert werden (Updatesite) und 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.

Dependencies:

Productdesigner-Web:

  <dependencies>
        <dependency>
            <groupId>org.faktorips.productdesigner</groupId>
            <artifactId>productdesigner-web</artifactId>
            <version>25.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>25.7.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>de.faktorzehn.muster.shu-gewerbe</groupId>
            <artifactId>vm-gewerbe-basis-produkte</artifactId>
            <version>25.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 eine Main-Klasse benötigt. Im nächsten Schritt wird diese angelegt. Die notwendige Konfiguration kann im pom.xml bereits eingetragen werden:

            <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 Product 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>25.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>25.7.0.release</faktorips.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.faktorips.productdesigner</groupId>
            <artifactId>productdesigner-web</artifactId>
            <version>25.7.0</version>
        </dependency>
        <!-- HIER MODELL-Dependencie(s) angeben -->
        <dependency>
            <groupId>de.faktorzehn.muster.shu-gewerbe</groupId>
            <artifactId>vm-gewerbe-gruppenunfall-produktmodellerw</artifactId>
            <version>25.7.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>de.faktorzehn.muster.shu-gewerbe</groupId>
            <artifactId>vm-gewerbe-basis-produkte</artifactId>
            <version>25.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 und Konfiguration

Wie zuvor beschrieben – wird eine Main-Klasse benötigt. Die Einstellung im pom.xml wurde im vorherigen Schritt bereits durchgeführt. Nun wird eine Application-Klasse angelegt. 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, <<Package von SampleProductDesignerApplication eintragen>>})
@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");
    }
}

Hinweis: Falls die Application in einem anderen (Sub-)Package als ProductDesigner.BASE_PACKAGE liegt, ist es notwendig, dieses Package neben dem ProductDesigner.BASE_PACKAGE einzutragen. Durch das Überschreiben wird ansonsten dieses Package nicht berücksichtigt. Es wird im nächsten Schritt eine SampleProductDesignerConfig.java angelegt und diese soll automatisch eingebunden werden – daher ist es erforderlich dieses Package anzugeben.

Zusätzlich braucht es eine Bean des ProductDesignerPermissionService. Mit dieser Klasse werden anhand unterschiedlicher Faktoren die Berechtigungen des Benutzers bestimmt. Dieser Service ist auch notwendig, wenn kein Single-Sign-On verwendet wird. Im bereitgestellten DefaultProductDesignerPermissionService werden die Schreibberechtigungen anhand des RuntimeRepositories, der Konfiguration im application.yml und der Rolle durch den RoleMapper ermittelt. Die SampleProductDesignerConfig.java wird neben der SampleProductDesignerApplication.java erstellt:

@Primary
@Component
public class SampleProductDesignerConfig {

    @SessionScope
    @Bean
    public ProductDesignerPermissionService permissionService(Optional<User> user,
            IModifiableRuntimeRepository repository,
            ProductDesignerConfigurationProperties properties) {
        return new DefaultProductDesignerPermissionService(user.orElse(new LocalUser()), repository,
                properties.readOnlyMode() ? ProductDesignerMode.READ_ONLY_MODE : ProductDesignerMode.EDIT_MODE);
    }
}

Anlegen der Config

Unter src/main/resources/ wird nun eine application.yml angelegt. Ein Beispiel hierfür:

logging:
  level:
    org.springframework: WARN

server:
  port: 8080

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

ips-product-designer:
  local:
    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
Parameter

Die folgenden Parameter müssen am Product Designer unter ips-product-designer gesetzt werden.

additional-repos

string[]

Liste von zusätzliche Repositories (Klassenreferenz, fully qualified name), von denen das Produktprojekt abhängt.

read-only-mode

boolean

Wenn true: der Product Desinger wird im Read-Only Modus gestartet (egal welcher Benutzer mit welcher Rolle sich anmeldet)

Version Control Mode

Der Product Designer unterstützt derzeit zwei Modi:

  • local: Der Product Designer nutzt einen lokalen Ordner, um das Repository und alle Bausteine zu laden. Alle Benutzer nutzen hier denselben Ordner. Sollte es sich trotzdem um ein GIT Repository handeln, kann auch hier ein Commit (auf den aktuellen Branch) erstellt werden.

  • git: Der Product Designer klont beim Log-In das Repository in ein Userverzeichnis. Bei einem "Commit" wird ein Commit auf einem neuen Branch erstellt (der Name setzt sich aus dem Usernamen, dem aktuellen Datum und einer fortlaufenden Nummer zusammen) und dann gepusht.

Es muss einer der Modus ausgewählt werden. Dazu muss entweder ips-product-designer.local oder ips-product-designer.git und dann die dafür notwendigen Paramter gesetzt werden.

Local

Parameter für den lokalen Modus:

ipsProjectPath

string

Relativer oder absoluter Pfad zum IPS Projekt

Git

Parameter für den Modus mit git Integration:

relativeIpsProjectPath

string

Relativer Pfad zum IPS Projekt. (Der Pfad muss relativ sein, da das Git Repository im jeweiligen User Verzeichnis ausgecheckt wird)

userFolderPath

string

Relativer oder absoluter Pfad zum Ordner in dem pro User ein Ordner angelegt wird und das Repository geklont wird

repositoryUrl

string

Git Repository Url um das Projekt zu clonen

branch

string

Name des Branches der standardmäßig beim clonen ausgecheckt werden soll

keyPath

string

Pfad zum private SSH Key für den technischen User

Für den Git-Modus wird ein technischer Benutzer benötigt, um das Repository zu klonen, pullen, pushen etc. Änderungen werden dann in dessen Namen durchgeführt. Derzeit unterstützt der Product Designer nur die Authentifizierung via SSH und mit einem passwortlosen private Key (alle gängigen Verschlüsselungen). Um das System so sicher wie möglich zu gestalten soll der Key nicht in fremde Hände gelangen und nur die allernotwendigsten Berechtigungen erhalten.

Einbinden zusätzlicher Repositories

Unter additional-repos können, wie zuvor beschrieben, zusätzliche Repositories eingebunden werden. In den Java Klassen müssen nicht nur Produkt-Repositories sondern auch die Modell-Repositories, auf denen sie basieren via addDirectlyReferencedRepository verknüpft werden, damit der Product Designer auch Modellklassen finden kann, die derzeit im Produktrepository nicht genutzt werden.

In anderen Konstellationen bei Verwendung mit Faktor-IPS war es bisher nicht notwendig die Modell-Repositories anzugeben. Der Product Designer braucht für die Analyse der Bausteine jedoch dies Informationen.

Damit die Repositories 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.