Auf Thema antworten

Hallo,

ich versuche aktuell ein Projekt aufzusetzen um Themen wie Clean Architecture, JPA & CDI näher zu behandeln.

Leider habe ich Probleme, die Datenbankverbindung zum Laufen zu bringen. Geplannt ist, mittels JBoss die Verbindung im Container managen zu lassen (Datasource etc. im Jboss zu definieren), damit ich mir über Sachen wie Connection pooling etc. keine Gedanken machen muss.


Das Projekt soll im ersten Schritt nur zwei Funktionen bieten:

  • Create User (Register User)
  • Login User

Zuersteinmal zu meinem Setup (Programmiert wird mit IntelliJ IDEA):

  • web-app: Das ist meine JSF Applikation welche als Frontend agieren soll. Später sollen andere Projekte hinzukommen, um andere "Presentation Layer" zu Verfügung zu stellen (Console Application, API Projekt, ...)
  • usecases: Beinhaltet die BusinessLogic. z.B. "LoginUser.java" (Beispiel unten). Dieses Projekt basiert auf Contracts (z.B. Interfaces für "UserRepository") und domain (Domain beeinhaltet die Entities)
  • domain: Beeinhaltet Entities (z.B. User.java), welche nicht an andere "Frameworks" gebunden sind
  • contracts: Beeinhaltet die Interfaces für z.B. UserRepository, PasswordHasher, ...
  • adapters: Beeinhaltet die Implementierung für Interfaces (z.B. JPAUserRepository, BCryptHasher)

Mit dieser Architektur, wären die "Presentation Layers" in der Verantwortung, die interfaces korrekt zu initialisieren. Dafür habe ich mich für Spring Boot entschieden:


[code=JAVA]@Configuration

@EntityScan("de.test.adapters.hibernate.entity")

public class SpringCoreConfig {

    private final PasswordHasher passwordHasher = new BCryptHasher();

    private final IdGenerator idGenerator = new GuidGenerator();


    @PersistenceContext(name = "entities")

    private EntityManager entityManager;


    @Bean

    public UserService userService(){

        return new UserService();

    }


    @Bean

    public CreateUser createUser() {

        return new CreateUser(getUserRepository(), passwordHasher, idGenerator);

    }


    @Bean

    public LoginUser loginUser() {

        return new LoginUser(getUserRepository(), passwordHasher);

    }


    private UserRepository getUserRepository(){

        return new JpaUserRepository(getEntityManager());

    }


    private EntityManager getEntityManager(){

        return entityManager;

    }

}

[/code]


Sollte ich nun eine neue Presentation Layer einfügen z.B. Console Application, müsste diese die "Interfaces" neu initialisieren. Das ist i.O., da dort z.B. der EntityManager anderst gehandelt werden muss.


Beispiel für JpaUserRepository:

[code=JAVA]

public class JpaUserRepository implements UserRepository {


    private EntityManager entityManager;


    public JpaUserRepository(EntityManager em){

        this.entityManager = em;

    }


    @Override

    public User create(User user) {

        entityManager.persist(UsersEntity.fromUser(user));

        return null;

    }


    @Override

    public Optional<User> findById(String id) {

        return Optional.empty();

    }


    @Override

    public Optional<User> findByEmail(String email) {

        return Optional.empty();

    }

}[/code]


Nun habe ich das Problem, dass der EntityManager in der Configuration nicht ordentlich initialisiert werden kann:

[code]Caused by: java.lang.NullPointerException

   at deployment.web-app-1.0-SNAPSHOT.war//org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:580)

   at deployment.web-app-1.0-SNAPSHOT.war//org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:546)

   at deployment.web-app-1.0-SNAPSHOT.war//org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:707)

   at deployment.web-app-1.0-SNAPSHOT.war//org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:680)

   at deployment.web-app-1.0-SNAPSHOT.war//org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)

   at deployment.web-app-1.0-SNAPSHOT.war//org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)

   at deployment.web-app-1.0-SNAPSHOT.war//org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:354)

   ... 35 more[/code]


Die persistence.xml liegt innerhalb des web-app projektes:

[code=XML]<?xml version="1.0" encoding="UTF-8"?>

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">

    <persistence-unit name="entities" transaction-type="RESOURCE_LOCAL">

        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <jta-data-source>java:jboss/datasources/testDS</jta-data-source>

        <properties>

            <property name="hibernate.archive.autodetection" value="class, hbm"/>

            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />

            <property name="jboss.entity.manager.factory.jndi.name" value="java:/EntityManagerFactory" />

            <property name="jboss.entity.manager.jndi.name" value="java:/EntityManager" />

        </properties>

    </persistence-unit>

</persistence>

[/code]


Meine POM.xml von der web-app:

[code=XML]<?xml version="1.0" encoding="UTF-8"?>

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <parent>

        <groupId>de.test</groupId>

        <artifactId>test</artifactId>

        <version>1.0-SNAPSHOT</version>

    </parent>

    <modelVersion>4.0.0</modelVersion>

    <artifactId>web-app</artifactId>

    <packaging>war</packaging>



    <properties>

        <com.sun.faces.version>2.2.14</com.sun.faces.version>

        <javax.el.version>3.0.0</javax.el.version>

        <maven-war-plugin.version>3.0.0</maven-war-plugin.version>

        <javax.servlet-api.version>3.1.0</javax.servlet-api.version>

        <jsf.omnifaces.version>3.4</jsf.omnifaces.version>

    </properties>


    <dependencies>

        <dependency>

            <groupId>org.omnifaces</groupId>

            <artifactId>omnifaces</artifactId>

            <version>${jsf.omnifaces.version}</version>

        </dependency>


        <dependency>

            <groupId>javax.annotation</groupId>

            <artifactId>javax.annotation-api</artifactId>

            <version>1.3.2</version>

        </dependency>


        <!-- logging -->

        <dependency>

            <groupId>org.slf4j</groupId>

            <artifactId>slf4j-api</artifactId>

            <version>${org.slf4j.version}</version>

        </dependency>

        <dependency>

            <groupId>ch.qos.logback</groupId>

            <artifactId>logback-classic</artifactId>

            <version>${logback.version}</version>

        </dependency>

        <dependency>

            <groupId>ch.qos.logback</groupId>

            <artifactId>logback-core</artifactId>

            <version>${logback.version}</version>

        </dependency>

        <dependency>

            <groupId>org.slf4j</groupId>

            <artifactId>jcl-over-slf4j</artifactId>

            <version>${org.slf4j.version}</version>

        </dependency>

        <!-- JSF -->

        <dependency>

            <groupId>com.sun.faces</groupId>

            <artifactId>jsf-api</artifactId>

            <version>${com.sun.faces.version}</version>

        </dependency>

        <dependency>

            <groupId>com.sun.faces</groupId>

            <artifactId>jsf-impl</artifactId>

            <version>${com.sun.faces.version}</version>

        </dependency>

        <dependency>

            <groupId>javax.el</groupId>

            <artifactId>javax.el-api</artifactId>

            <version>${javax.el.version}</version>

        </dependency>

        <!-- Spring -->

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-web</artifactId>

            <version>${org.springframework.version}</version>

            <exclusions>

                <exclusion>

                    <artifactId>commons-logging</artifactId>

                    <groupId>commons-logging</groupId>

                </exclusion>

            </exclusions>

        </dependency>

        <dependency>

            <groupId>javax.servlet</groupId>

            <artifactId>javax.servlet-api</artifactId>

            <scope>provided</scope>

            <version>${javax.servlet-api.version}</version>

        </dependency>

        <dependency>

            <groupId>de.test</groupId>

            <artifactId>usecases</artifactId>

        </dependency>

        <dependency>

            <groupId>de.test</groupId>

            <artifactId>domain</artifactId>

        </dependency>

        <dependency>

            <groupId>de.test</groupId>

            <artifactId>adapters</artifactId>

            <version>1.0-SNAPSHOT</version>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-autoconfigure</artifactId>

            <version>2.2.1.RELEASE</version>

            <scope>compile</scope>

        </dependency>

    </dependencies>


    <build>

        <plugins>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-war-plugin</artifactId>

                <version>${maven-war-plugin.version}</version>

                <configuration>

                    <failOnMissingWebXml>false</failOnMissingWebXml>

                </configuration>

            </plugin>

        </plugins>

    </build>

</project>[/code]


Ich gehe davon aus, dass ich einen Fehler gemacht habe bzgl JPA. Leider komme ich auch mit meiner Recherche nicht weiter, weswegen ich nun hier um Hilfe bitte.



Oben