Home > Blockchain >  Trying to use my first DB connection in Java - I'm getting loads of errors and I don't kno
Trying to use my first DB connection in Java - I'm getting loads of errors and I don't kno

Time:12-27

So I have to do a small app in Java - I have no background in it so I don't really know many things (syntactically) about it. I'm using the internet and intellij for generating some code. (like the models)

The program builds successfully, but then I get these runtime errors:

Error at initialing DatabaseManager: Exception [EclipseLink-7107] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Error encountered during string decryption.
Internal Exception: java.io.StreamCorruptedException: invalid stream header: BEAD66C6
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "javax.persistence.EntityManager.getTransaction()" because "this.entityManager" is null
    at database.DatabaseConnection.executeTransaction(DatabaseConnection.java:23)
    at database.daos.EchipaDao.create(EchipaDao.java:23)
    at Main.main(Main.java:11)

Here's my code:

DatabaseConnection.Java

package database;

import java.util.function.Consumer;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class DatabaseConnection {
    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;

    public DatabaseConnection() {
        this.initTransaction();
    }

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public boolean executeTransaction(Consumer<EntityManager> action) {
        EntityTransaction entityTransaction = entityManager.getTransaction();
        try {
            entityTransaction.begin();
            action.accept(entityManager);
            entityTransaction.commit();
        } catch (RuntimeException e) {
            System.err.println("Transaction error: "   e.getLocalizedMessage());
            entityTransaction.rollback();
            return false;
        }
        return true;
    }

    private boolean initTransaction() {
        try {
            entityManagerFactory = Persistence.createEntityManagerFactory("ProiectMipPersistence");
            entityManager = entityManagerFactory.createEntityManager();
        } catch (Exception e) {
            System.err.println("Error at initialing DatabaseManager: "   e.getMessage().toString());
            return false;
        }
        return true;
    }
}

IDao.java

package database.daos;

import java.util.List;

public interface IDao<T> {
    T get(Long id);
    List<T> getAll ();
    void create (T t);
}

EchipaDao.java

package database.daos;

import database.DatabaseConnection;
import database.models.EchipaEntity;

import javax.persistence.TypedQuery;
import java.util.List;

public class EchipaDao implements IDao<EchipaEntity>{
    DatabaseConnection connection = new DatabaseConnection();

    public EchipaEntity get(Long id) {
        return connection.getEntityManager().find(EchipaEntity.class, Long.valueOf(id));
    }

    @Override
    public List<EchipaEntity> getAll() {
        TypedQuery<EchipaEntity> query = connection.getEntityManager().createQuery("SELECT a FROM EchipaEntity a", EchipaEntity.class);
        return query.getResultList();
    }

    public void create(EchipaEntity echipa) {
        connection.executeTransaction(entityManager -> entityManager.persist(echipa));
    }
}

EchipaEntity.java

package database.models;

import javax.persistence.*;
import java.util.Objects;

@Entity
@Table(name = "echipa", schema = "public", catalog = "dbfdlur9ijidho")
public class EchipaEntity {
    @Basic
    @Column(name = "nume_echipa", nullable = false, length = -1)
    private String numeEchipa;
    @Id
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    public String getNumeEchipa() {
        return numeEchipa;
    }

    public void setNumeEchipa(String numeEchipa) {
        this.numeEchipa = numeEchipa;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        EchipaEntity that = (EchipaEntity) o;
        return id == that.id && Objects.equals(numeEchipa, that.numeEchipa);
    }

    @Override
    public int hashCode() {
        return Objects.hash(numeEchipa, id);
    }
}

Main.java

import database.daos.EchipaDao;
import database.models.EchipaEntity;

public class Main {
    public static void main(String[] args) {
        EchipaDao echipaDao = new EchipaDao();
        EchipaEntity echipaEntity = new EchipaEntity();

        echipaEntity.setNumeEchipa("test");

        echipaDao.create(echipaEntity);

        System.out.println("Hello world");
    }
}

I tried searching online (honestly, just for the first one, because I feel like if I get rid of that the rest will disappear too) - I couldn't find anything meaningful to my case.

So, why are those errors happening and how can I fix them?

//Edit:

Added pom.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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>server</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>16</source>
                    <target>16</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
    <!-- ECLIPSELINK -->
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>eclipselink</artifactId>
        <version>2.7.7</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>javax.persistence</artifactId>
        <version>2.0.0</version>
    </dependency>
    <!-- POSTGRES -->
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>9.3-1102-jdbc41</version>
    </dependency>
</dependencies>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

</project>

CodePudding user response:

At the end of the stacktrace you can see the root of the problem:

java.io.StreamCorruptedException: invalid stream header: 2666A3B3

Although a bit cryptic, this usally means an incompatibility of libraries.

Looking closer at your dependencies, you are using a fairly new version of eclipselink (2.7.7 from year 2020), and quite old versions of the other dependencies (javax.persistence 2.0.0 from 2010, and postgres 9.3 from 2014).

If you go to the eclipselink 2.7.7 maven page (https://mvnrepository.com/artifact/org.eclipse.persistence/eclipselink/2.7.7) you can see that the dependency used to compile it was jakarta.persistence (the new denomination for javax.persistence) 2.2.3, from 2019, which would make a lot more sense.

In the case of Postgress driver, you can see in its documentation (https://jdbc.postgresql.org/download.html) :

Current Version 42.3.1

This is the current version of the driver. Unless you have unusual requirements (running old applications or JVMs), this is the driver you should be using. It supports PostgreSQL 8.2 or newer and requires Java 8 or newer. It contains support for SSL and the javax.sql package.

So, to tidy up your dependencies do the following changes in your pom.xml

<dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>eclipselink</artifactId>
        <version>2.7.7</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>jakarta.persistence</artifactId>
        <version>2.2.3</version>
    </dependency>
    <!-- POSTGRES -->
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.3.1</version>
    </dependency>
</dependencies>

Also, you are defining the maven compiler plugin to use java version 16, but in the properties maven.compiler.xxx point to java 17. Those are exactly the same, so either you specify the properties ornthe plugin configuration. If you are not using additional plugin configuration I would always go for the properties. And make it 16 or 17 depending on your jdk version (I would use 17, as it is the last LTS jdk version)

Following this eclipselink github project thread (https://github.com/eclipse-ee4j/eclipselink/issues/269) jdk 11 support was supposedly added in 3.0.0.

Update after local testing

That means that, theoretically, using 2.7.7 you are tied to use jdk 8. But I have just run your code samples correctly with jdk 11. (16 and 17 failed with the Unsupported class file major version 60 and 61.

Even only changing the JDK to 11 in your original question wouldn't have been enough, you would have gotten org.postgresql.util.PSQLException: The authentication type 10 is not supported because of incompatibility issues between libraries as mentioned at the beginning of the answer.

  • Related