Jump to content

Hibernate: How to Launch

From Wikiversity

Launching Hibernate Framework can be a tricky task. This page provides you with multiple ways to do it, it can be useful to you if you're trying to run your first application with Hibernate and it just crashes, or if you need Proof-of-Concept or an archetype of project with specific configuration. Every sample application on this page maintains a simple goal - to read something from database, which is a proof of Hibernate up and running.

All projects on this page use H2 database.

Just pick a desired configuration option, create specified files and you're good to go.


H2 Database

[edit | edit source]

Ignore this section if you're going to use Maven. Otherwise, download H2 zip, find \h2\bin\h2-$version.jar file in it and proceed to one of the Standalone non-Maven sections on this page.

If you want to know how to use H2 database without writing an application, this section shows how to do it.

Installation

[edit | edit source]
  1. Download H2 zip here: https://www.h2database.com/html/download.html
  2. Extract it to ~\AppData\Local\Programs
  3. Create a shortcut for \h2\bin\h2.bat
  4. Place it to ~\AppData\Roaming\Microsoft\Windows\Start Menu. Now you can easily start H2 from Start menu.

Usage

[edit | edit source]
  1. Start H2 .bat or shortcut, web page will open with Generic H2 (Embedded) preset active;
  2. Use JDBC url jdbc:h2:mem:test for in-memory or jdbc:h2:~/test for local storage based db;
    • If local storage is used, ~/test.mv.db file will be created and will stay there until you’ll delete it;
    • ~/.h2.server.properties file will be created either way;
  3. Press Connect to start server and use database;
  4. In CMD window press CTRL+C several times to stop server.
    • You don't have to run/stop H2 server manually if it's library is in classpath of your application.

Standalone

[edit | edit source]

You can launch Hibernate in offline desktop application. Maybe it is a CLI app, or maybe it uses GUI frameworks like Swing or JavaFX, it doesn't matter - you can bootstrap Hibernate into it. This section shows how to do it.

Also Hibernate itself can be configured with persistence.xml, hibernate.properties or hibernate.cfg.xml file. So, we will cover every of this configuration options.

Without Maven

[edit | edit source]

persistence.xml

[edit | edit source]

This a proof of concept, it is recommended to use Maven.

  1. Choose a 6.0.0.CR2 version here: https://sourceforge.net/projects/hibernate/files/hibernate-orm/; - Since then Hibernate release bundle download is no longer provided, so this is the latest Hibernate version you can download as a bundle;
  2. Download hibernate-release-6.0.0.CR2.zip
  3. Extract it’s .\required internal directory.
  4. Into .\required\ directory copy a h2-2.2.220.jar file as well, it is in the same directory as h2.bat file from above section. It contains H2 JDBC driver.
  1. Create .\META-INF\persistence.xml file:
  2. <persistence xmlns="https://jakarta.ee/xml/ns/persistence" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" 
        version="3.0">
        
        <persistence-unit name="only-unit" >
            <properties>
                <property name="jakarta.persistence.jdbc.driver" value="org.h2.Driver" />
                <property name="jakarta.persistence.jdbc.url" value="jdbc:h2:mem:test" />
                <property name="jakarta.persistence.jdbc.user" value="sa" />
                <property name="jakarta.persistence.jdbc.password" value="" />
                
                <property name="hibernate.hbm2ddl.auto" value="create" />
            </properties>
        </persistence-unit>
    </persistence>
    
  3. Create .\example\entity\Person.java class:
  4. package example.entity;
    
    import jakarta.persistence.*;
    // import lombok.Data;
    
    @Entity
    //@Data 
    public class Person {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private String name;
        // add Lombok to classpath, uncomment annotation and you can remove all this:
        public Person() {}
        
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return String.format("Person[%s %s]", id, name);
        }
    }
    
  5. Create .\example\Start.java class:
  6. package example;
    
    import jakarta.persistence.*;
    import example.entity.*;
    
    public class Start {
        
        public static void main(String[] args) {
            var emf = Persistence.createEntityManagerFactory("only-unit");
            var em = emf.createEntityManager();
            
            em.getTransaction().begin();
            var person = new Person();
            person.setName("Вася Петечкин");
            em.persist(person);
            em.getTransaction().commit();
            
            listAll(em, Person.class);
            
            var pupkin = em.find(Person.class, 1);
            pupkin.setName("Петя Васечкин");
            
            listAll(em, Person.class);
            
            em.close();
            emf.close();
        }
        
        
    
        public static void listAll(EntityManager em, Class entity) {
            String entityName = entity.getSimpleName();
            String queryString = String.format("SELECT e FROM %s e", entityName);
    
            Query query = em.createQuery(queryString);
            var resultList = query.getResultList();
            System.out.printf("All records(%s):%n", resultList.size());
            for (Object obj : resultList) {
                System.out.println(obj);
            }
        }
    }
    
  7. Examine file structure of a project:
  8. .\example\Start.java
    .\example\entity\Person.java
    .\META-INF\persistence.xml
    .\required\antlr4-runtime-4.9.1.jar
    .\required\byte-buddy-1.12.7.jar
    .\required\classmate-1.5.1.jar
    .\required\h2-2.2.220.jar
    .\required\hibernate-commons-annotations-6.0.0.CR1.jar
    .\required\hibernate-core-6.0.0.CR2.jar
    .\required\istack-commons-runtime-4.0.1.jar
    .\required\jakarta.activation-2.0.1.jar
    .\required\jakarta.activation-api-2.0.1.jar
    .\required\jakarta.inject-api-2.0.0.jar
    .\required\jakarta.persistence-api-3.0.0.jar
    .\required\jakarta.transaction-api-2.0.0.jar
    .\required\jakarta.xml.bind-api-3.0.1.jar
    .\required\jandex-2.4.2.Final.jar
    .\required\jaxb-core-3.0.2.jar
    .\required\jaxb-runtime-3.0.2.jar
    .\required\jboss-logging-3.4.3.Final.jar
    .\required\txw2-3.0.2.jar
    
  9. Compile and run it from Powershell:
  10. javac --% -cp .;required\*;.\classes -d classes example\entity\*.java example\*.java
    java --% -cp .;required\*;.\classes example.Start
    • --% is needed to prevent Powershell from interpreting arguments to java and javac executables.

hibernate.properties

[edit | edit source]
  1. Create Person and Start classes as in the previous section;
  2. Create .\hibernate.properties:
hibernate.connection.driver_class org.h2.Driver
hibernate.connection.username sa
hibernate.connection.password
hibernate.connection.url jdbc:h2:mem:test
hibernate.hbm2ddl.auto create
  1. Replace main() method with this:
import org.hibernate.cfg.Configuration;
public static void main(String[] args) {
    var configuration = new Configuration().addAnnotatedClass(Person.class);
    var sessionFactory = configuration.buildSessionFactory();
    var em = sessionFactory.openSession();
   
    em.getTransaction().begin();
    var person = new Person();
    person.setName("Вася Петечкин");
    em.persist(person);
    em.getTransaction().commit();
    
    listAll(em, Person.class);
    
    var pupkin = em.find(Person.class, 1);
    pupkin.setName("Петя Васечкин");
    
    listAll(em, Person.class);
    
    em.close();
}
  1. Compile and run it as in previous section.

hibernate.properties is more concise than persistence.xml, but now you must manually list all your annotated classes while creating Configuration.

hibernate.cfg.xml

[edit | edit source]
  1. Create Person and Start classes as in the previous section;
  2. Create .\hibernate.cfg.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC 
  "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
  "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="connection.driver_class">org.h2.Driver</property>
    <property name="connection.url">jdbc:h2:mem:test</property>
    <property name="connection.username">sa</property>
    <property name="connection.password"></property>
    <property name="hbm2ddl.auto">create</property>
    
    <!-- use <mapping> or new Configuration().addAnnotatedClass(Person.class) -->
    <mapping class="example.entity.Person" />
  </session-factory>
</hibernate-configuration>
  1. Use this main() method:
public static void main(String[] args) {
    // var configuration = new Configuration().addAnnotatedClass(Person.class).configure();
    var configuration = new Configuration().configure();
    var sessionFactory = configuration.buildSessionFactory();
    var em = sessionFactory.openSession();
    
    em.getTransaction().begin();
    var person = new Person();
    person.setName("Вася Петечкин");
    em.persist(person);
    em.getTransaction().commit();
    
    listAll(em, Person.class);
    
    var pupkin = em.find(Person.class, 1);
    pupkin.setName("Петя Васечкин");
    
    listAll(em, Person.class);
    
    em.close();
}
  1. Compile and run it as in previous section. Usage of hibernate.cfg.xml is considered to be legacy and is not recommended for new projects.

Open in VSCode

[edit | edit source]

It's simple to run a maven project in IDE, but if you'll want to run one of above combinations, here is what you need to do:

  1. Open project directory through File -> Open Folder...;
  2. In Explorer -> Java Projects -> Referenced Libraries press + sign and choose all .jar files from .\required\ directory;
  3. Now you can run this project through Ctrl+F5. In Run -> Open Configurations you will find new run configuration:
{
    "type": "java",
    "name": "Start",
    "request": "launch",
    "mainClass": "example.Start",
    "projectName": "example2023_44420544",
    "classPaths": [
        "required/*.jar",
        "classes"
    ]
}

With Maven

[edit | edit source]

Add Maven to existing project

[edit | edit source]

Use any of the above non-maven combinations of java classes and configuration files, but also:

  1. Instead of placing .jar files into .\required directory, create this .\pom.xml:
  2. <?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>example</groupId>
      <artifactId>hibertinymav</artifactId>
      <version>0.1</version>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>18</maven.compiler.source>
        <maven.compiler.target>18</maven.compiler.target>
        <exec.mainClass>example.Start</exec.mainClass>
      </properties>
    
      <dependencies>
    
        <!-- https://mvnrepository.com/artifact/org.hibernate.orm/hibernate-core -->
        <dependency>
          <groupId>org.hibernate.orm</groupId>
          <artifactId>hibernate-core</artifactId>
          <version>6.2.6.Final</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
        <dependency>
          <groupId>com.h2database</groupId>
          <artifactId>h2</artifactId>
          <version>2.1.214</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <version>1.18.28</version>
          <scope>provided</scope>
        </dependency>
    
    
      </dependencies>
    </project>
    
  3. Place all your .java files with package-defined directories into .\src\main\java\.
  4. If there is a configuration .xml or .properties file in your project, move it into .\src\main\resources\. If this file by convention should itself be located in some kind of a directory, like /META-INF/, move it with it's parent directory, so new location will be: .\src\main\resources\META-INF\persistence.xml.
  5. Examine project file structure:
    .\pom.xml
    .\src\main\java\example\Start.java
    .\src\main\java\example\entity\Person.java
    .\src\main\resources\META-INF\persistence.xml
  6. Run your application with mvn clean compile exec:java command.
    • If you will need to run this goal in VSCode, add following plugin section after <dependency> tag, otherwise you may be not able to choose exec:java goal:
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
    


Maven Encoding Issue

[edit | edit source]

You may encounter your application fails to output some unicode characters to console under Windows platform when you run it with Maven, even though when you execute your app with VSCode internal functionality or manually with java in CMD, characters are displayed properly. To fix this issue add this method to your main class and call it from main():

public static void changeConsoleEncodingIfNeeded() {
    var utf8 = java.nio.charset.Charset.forName("UTF-8");
    var ibm866 = java.nio.charset.Charset.forName("IBM866");
    if (System.console().charset().equals(ibm866) && 
        System.out.charset().equals(utf8)) {
            
        System.out.println("System.out encoding is going to change. Before: АБВ");
        System.setOut(new java.io.PrintStream(new java.io.FileOutputStream(java.io.FileDescriptor.out), true, ibm866));
        System.out.println("After: АБВ");
    }
}

Spring Standalone

[edit | edit source]

You can write a standalone application which uses Spring's Inversion of Control and Dependency Injection capabilities but doesn't use MVC web module.

  1. Create .\pom.xml:
  2. <project>
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>example</groupId>
      <artifactId>hiberspringtiny</artifactId>
      <version>0.1</version>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>18</maven.compiler.source>
        <maven.compiler.target>18</maven.compiler.target>
        <exec.mainClass>myapp.App</exec.mainClass>
      </properties>
    
      <dependencies>
    
        <!-- https://mvnrepository.com/artifact/org.hibernate.orm/hibernate-core -->
        <dependency>
          <groupId>org.hibernate.orm</groupId>
          <artifactId>hibernate-core</artifactId>
          <version>6.2.6.Final</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
        <dependency>
          <groupId>com.h2database</groupId>
          <artifactId>h2</artifactId>
          <version>2.1.214</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.10</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>6.0.10</version>
        </dependency>
    
    
      </dependencies>
    </project>
    
  3. Create .\src\main\java\myapp\App.java:
  4. package myapp;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class App {
    
        public static void main(String[] args) {
            changeConsoleEncodingIfNeeded();
            System.out.println("Hello Привет");
            var ctx = new AnnotationConfigApplicationContext(ApplicationConfig.class);
            // var emf = ctx.getBean(EntityManagerFactory.class);
            // System.out.println(emf);
            ctx.getBean(Printer.class).doPrint();
            ctx.close();
        }
        public static void changeConsoleEncodingIfNeeded() { // you can remove this method
            var utf8 = java.nio.charset.Charset.forName("UTF-8");
            var ibm866 = java.nio.charset.Charset.forName("IBM866");
            if (System.console().charset().equals(ibm866) && 
                System.out.charset().equals(utf8)) {
                    
                System.out.println("System.out encoding is going to change. Before: АБВ");
                System.setOut(new java.io.PrintStream(new java.io.FileOutputStream(java.io.FileDescriptor.out), true, ibm866));
                System.out.println("After: АБВ");
            }
        }
    }
    
  5. Create .\src\main\java\myapp\model\Person.java:
  6. package myapp.model;
    
    import jakarta.persistence.*;
    // import lombok.Data;
    
    @Entity
    //@Data 
    public class Person {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private String name;
        // add Lombok to classpath, uncomment annotation and you can remove all this:
        public Person() {}
        
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return String.format("Person[%s %s]", id, name);
        }
    }
    
  7. Create .\src\main\resources\META-INF\persistence.xml:
  8. <persistence xmlns="https://jakarta.ee/xml/ns/persistence" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    	xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" 
    	version="3.0">
    	
    	<persistence-unit name="only-unit" >
    		<properties>
    			<property name="jakarta.persistence.jdbc.driver" value="org.h2.Driver" />
    			<property name="jakarta.persistence.jdbc.url" value="jdbc:h2:mem:test" />
    			<property name="jakarta.persistence.jdbc.user" value="sa" />
    			<property name="jakarta.persistence.jdbc.password" value="" />
    			
    			<property name="hibernate.hbm2ddl.auto" value="create" />
    		</properties>
    	</persistence-unit>
    </persistence>
    
  9. Create .\src\main\java\myapp\ApplicationConfig.java:
  10. package myapp;
    
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.orm.jpa.JpaTransactionManager;
    import org.springframework.orm.jpa.LocalEntityManagerFactoryBean;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    import jakarta.persistence.EntityManagerFactory;
    
    @Configuration
    @ComponentScan
    @EnableTransactionManagement
    public class ApplicationConfig {
    
    	@Bean
        public LocalEntityManagerFactoryBean myEmf() {
            LocalEntityManagerFactoryBean emf = new LocalEntityManagerFactoryBean();
            emf.setPersistenceUnitName("only-unit");
            return emf;
        }
        @Bean
        public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
            return new JpaTransactionManager(emf);
        }
    }
    
  11. Create .\src\main\java\myapp\Printer.java:
  12. package myapp;
    
    import org.springframework.stereotype.Component;
    
    import jakarta.persistence.EntityManager;
    import jakarta.persistence.PersistenceContext;
    import jakarta.persistence.Query;
    import jakarta.transaction.Transactional;
    import myapp.model.Person;
    
    @Component
    @Transactional
    public class Printer {
    
        @PersistenceContext
        private EntityManager em;
    
        public void doPrint() {
            System.out.println("EntityManager: "+em);
            listAll(em,Person.class);
            createNewPerson(em);
            listAll(em,Person.class);
    
        }
        
        @Transactional
        public void createNewPerson(EntityManager em) {
            var person = new Person();
            person.setName("Вася Петечкин");
            em.persist(person);
        }
    
        public static void listAll(EntityManager em, Class entity) {
            String entityName = entity.getSimpleName();
            String queryString = String.format("SELECT e FROM %s e", entityName);
    
            Query query = em.createQuery(queryString);
            var resultList = query.getResultList();
            System.out.printf("All records(%s):%n", resultList.size());
            for (Object obj : resultList) {
                System.out.println(obj);
            }
        }
        
    }
    
  13. Run your app with mvn clean compile exec:java. Basic read/write operations will be performed.

Spring Boot Standalone

[edit | edit source]

You can write a standalone application with Spring Boot. It provides you Inversion of Control and Dependency Injection capabilities but doesn't use MVC web module.

  1. Create .\pom.xml:
  2. <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>3.2.0-SNAPSHOT</version>
    		<relativePath /> <!-- lookup parent from repository -->
    	</parent>
    	<groupId>com.example</groupId>
    	<artifactId>demo</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    
    	<properties>
    		<java.version>17</java.version>
    	</properties>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-jpa</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>com.h2database</groupId>
    			<artifactId>h2</artifactId>
    			<scope>runtime</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.projectlombok</groupId>
    			<artifactId>lombok</artifactId>
    			<version>1.18.28</version>
    			<scope>provided</scope>
    		</dependency>
    
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>
    	<repositories>
    		<repository>
    			<id>spring-milestones</id>
    			<name>Spring Milestones</name>
    			<url>https://repo.spring.io/milestone</url>
    			<snapshots>
    				<enabled>false</enabled>
    			</snapshots>
    		</repository>
    		<repository>
    			<id>spring-snapshots</id>
    			<name>Spring Snapshots</name>
    			<url>https://repo.spring.io/snapshot</url>
    			<releases>
    				<enabled>false</enabled>
    			</releases>
    		</repository>
    	</repositories>
    	<pluginRepositories>
    		<pluginRepository>
    			<id>spring-milestones</id>
    			<name>Spring Milestones</name>
    			<url>https://repo.spring.io/milestone</url>
    			<snapshots>
    				<enabled>false</enabled>
    			</snapshots>
    		</pluginRepository>
    		<pluginRepository>
    			<id>spring-snapshots</id>
    			<name>Spring Snapshots</name>
    			<url>https://repo.spring.io/snapshot</url>
    			<releases>
    				<enabled>false</enabled>
    			</releases>
    		</pluginRepository>
    	</pluginRepositories>
    
    </project>
    


  3. Create .\src\main\resources\application.properties:
  4. spring.datasource.url=jdbc:h2:mem:testdb
    spring.datasource.driverClassName=org.h2.Driver
    spring.datasource.username=sa
    spring.datasource.password=
    
  5. Create .\src\main\java\myapp\DemoApplication.java:
  6. package myapp;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class DemoApplication implements CommandLineRunner {
    	@Autowired
    	Printer printer;
    
    	public static void main(String[] args) {
    		SpringApplication.run(DemoApplication.class, args);
    
    	}
    
    	@Override
    	public void run(String... args) throws Exception {
    		printer.doPrint();
    	}
    
    }
    
  7. Create .\src\main\java\myapp\model\Person.java:
  8. package myapp.model;
    
    import jakarta.persistence.*;
    import lombok.Data;
    
    @Entity
    @Data 
    public class Person {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private String name;
        
    }
    
  9. Create .\src\main\java\myapp\Printer.java:
  10. package myapp;
    
    import org.springframework.stereotype.Component;
    
    import jakarta.persistence.EntityManager;
    import jakarta.persistence.PersistenceContext;
    import jakarta.persistence.Query;
    import jakarta.transaction.Transactional;
    import myapp.model.Person;
    
    @Component
    @Transactional
    public class Printer {
    
        @PersistenceContext
        private EntityManager em;
    
        public void doPrint() {
            System.out.println("EntityManager: "+em);
            listAll(em,Person.class);
            createNewPerson(em);
            listAll(em,Person.class);
    
        }
        
        @Transactional
        public void createNewPerson(EntityManager em) {
            var person = new Person();
            person.setName("Вася Петечкин");
            em.persist(person);
        }
    
        public static void listAll(EntityManager em, Class entity) {
            String entityName = entity.getSimpleName();
            String queryString = String.format("SELECT e FROM %s e", entityName);
    
            Query query = em.createQuery(queryString);
            var resultList = query.getResultList();
            System.out.printf("All records(%s):%n", resultList.size());
            for (Object obj : resultList) {
                System.out.println(obj);
            }
        }
        
    }
    
  11. Run your app with mvn clean compile spring-boot:run. Basic read/write operations will be performed.

Spring Web

[edit | edit source]

Projects in this category are web applications built with Spring Framework.

Spring Boot Rest

[edit | edit source]
  1. Create .\pom.xml:
  2. <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>mygroup</groupId>
    	<artifactId>springboot-tiny</artifactId>
    	<version>0.0.1</version>
    	<name>First Spring Boot Example</name>
    	<packaging>war</packaging>
    
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>3.1.1</version>
    	</parent>
    	<properties>
    	</properties>	
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-tomcat</artifactId>
    			<scope>provided</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-jpa</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>com.h2database</groupId>
    			<artifactId>h2</artifactId>
    			<scope>runtime</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.projectlombok</groupId>
    			<artifactId>lombok</artifactId>
    			<version>1.18.28</version>
    			<scope>provided</scope>
    		</dependency>
    	</dependencies>
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>	
    </project>
    
  3. Create .\src\main\java\myapp\Application.java:
  4. package myapp;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ApplicationContext;
    
    @SpringBootApplication 
    public class Application {
    	public static void main(String[] args) {
    		ApplicationContext ctx = SpringApplication.run(Application.class,args);
    	}
    }
    
  5. Create .\src\main\resources\application.properties:
  6. spring.datasource.url=jdbc:h2:mem:testdb
    spring.datasource.driverClassName=org.h2.Driver
    spring.datasource.username=sa
    spring.datasource.password=
    
  7. Create .\src\main\java\myapp\model\Person.java:
  8. package myapp.model;
    
    import jakarta.persistence.*;
    import lombok.Data;
    
    @Entity
    @Data 
    public class Person {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private String name;
        
    }
    
  9. Create .\src\main\java\myapp\rest\PersonController.java:
  10. package myapp.rest;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import myapp.dao.PersonDao;
    import myapp.model.Person;
    
    @RestController
    @RequestMapping("/person")
    public class PersonController {
    
    	@Autowired
    	PersonDao personDao;
    
    	@PostMapping("/new")
    	public Person create(@RequestBody Person person) {
    		person.setId(null);
    		return personDao.create(person);
    	}
    
    	@GetMapping("/all")
    	public List<Person> findAll() {
    		return personDao.findAll();
    	}
    }
    
  11. Create .\src\main\java\myapp\dao\PersonDao.java:
  12. package myapp.dao;
    
    import java.util.List;
    
    import org.springframework.stereotype.Repository;
    
    import jakarta.persistence.EntityManager;
    import jakarta.persistence.PersistenceContext;
    import jakarta.transaction.Transactional;
    import myapp.model.Person;
    
    @Repository
    public class PersonDao {
    
        @PersistenceContext
        private EntityManager em;
    
        @Transactional
        public Person create(Person person) {
            em.persist(person);
            return person;
        }
    
        public List<Person> findAll() {
            String queryString = "SELECT p FROM Person p";
            var query = em.createQuery(queryString, Person.class);
            var resultList = query.getResultList();
            return resultList;
        }
    
    }
    
  13. Run your application: mvn clean spring-boot:run
  14. Create new person by accessing REST endpoint with CURL or Powershell:
  15. curl.exe -X POST -H "Content-Type: application/json" -d '{"name":"Вася Петечкин"}' http://localhost:8080/person/new
    Invoke-WebRequest -Uri "http://localhost:8080/person/new" -Method POST -Body '{"name":"Вася Петечкин"}' -ContentType "application/json; charset=UTF-8"
    
    • Note how you'll need to explicitly state encoding if using Powershell.
  16. Get a list of all persons by accessing REST endpoint with CURL or Powershell (or open this link in a browser):
  17. curl.exe -X GET http://localhost:8080/person/all
    Invoke-WebRequest -Uri "http://localhost:8080/person/all" -Method GET | select -Expand Content
    
  18. You will see output:
  19. [{"id":1,"name":"Вася Петечкин"},{"id":2,"name":"Петя Васечкин"}]
    

Spring MVC XML-config Rest

[edit | edit source]

Spring Framework can be used without Spring Boot and with XML-configuration. This project uses REST endpoint to read/write data with Hibernate.

  1. Create .\pom.xml:
  2. <project>
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>mygroup</groupId>
    	<artifactId>SpringTinyWeb</artifactId>
    	<version>0.1</version>
    	<packaging>war</packaging>
    	
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<maven.compiler.source>18</maven.compiler.source>
    		<maven.compiler.target>18</maven.compiler.target>
    
    		<spring.version>6.0.11</spring.version>
    		<jetty-maven-plugin.version>11.0.12</jetty-maven-plugin.version>
    		<hibernate-core.version>6.1.5.Final</hibernate-core.version>
    	</properties>
    	
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-webmvc</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-orm</artifactId>
    			<version>6.0.11</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.commons</groupId>
    			<artifactId>commons-dbcp2</artifactId>
    			<version>2.9.0</version>
    		</dependency>
    		<dependency>
    			<groupId>com.h2database</groupId>
    			<artifactId>h2</artifactId>
    			<version>2.1.214</version>
    		</dependency>
    		<dependency>
    			<groupId>org.hibernate</groupId>
    			<artifactId>hibernate-core</artifactId>
    			<version>${hibernate-core.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>com.fasterxml.jackson.core</groupId>
    			<artifactId>jackson-databind</artifactId>
    			<version>2.14.1</version>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<pluginManagement>
    			<plugins>
    				<plugin>
    					<groupId>org.eclipse.jetty</groupId>
    					<artifactId>jetty-maven-plugin</artifactId>
    					<version>${jetty-maven-plugin.version}</version>
    				</plugin>
    			</plugins>
    		</pluginManagement>
    	</build>
    	
    </project>
    
  3. Create .\src\main\webapp\WEB-INF\web.xml:
  4. <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
            https://jakarta.ee/xml/ns/jakartaee
            https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
        version="5.0">
    	<servlet>
    		<servlet-name>dispatcher</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>dispatcher</servlet-name>
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
    </web-app>
    
  5. Create .\src\main\webapp\WEB-INF\dispatcher-servlet.xml:
  6. <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
    	xmlns:context="http://www.springframework.org/schema/context"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc
            https://www.springframework.org/schema/mvc/spring-mvc.xsd
    		http://www.springframework.org/schema/context
        	http://www.springframework.org/schema/context/spring-context.xsd
    		http://www.springframework.org/schema/tx
    		http://www.springframework.org/schema/tx/spring-tx.xsd
    		">
    	<context:component-scan base-package="myapp" />
    	
    	<mvc:annotation-driven>
    		<mvc:message-converters>
    			<bean id="jacksonHttpMessageConverter" 
    				class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    				<!--<property name="prettyPrint" value="true" />-->
    			</bean>
    		</mvc:message-converters>
    	</mvc:annotation-driven>
    
    	<!-- src: https://stackoverflow.com/questions/36420880/what-is-enabletransactionmanagement-xml-equivalent-in-spring-4 -->
    	<tx:annotation-driven transaction-manager="txManager" />
    	
    	<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    		<property name="driverClassName" value="org.h2.Driver" />
    		<property name="url" value="jdbc:h2:mem:dataSource;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false" />
    		<property name="username" value="user" />
    		<property name="password" value="1234" />
    		<!-- <property name="connectionInitSqls" value="#{T(java.nio.file.Files).readString(T(org.springframework.util.ResourceUtils).getFile('classpath:schema.sql'))}"/> -->
    	</bean>
    	<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    		<property name="dataSource" ref="dataSource"/>
    		<property name="packagesToScan" value="myapp"/>
    		<property name="hibernateProperties">
    			<value>
    				hibernate.dialect=org.hibernate.dialect.H2Dialect
    				hibernate.hbm2ddl.auto=create-drop
    				hibernate.hbm2ddl.import_files=data.sql
    			</value>
    		</property>
    	</bean>
    
    	<bean id="txManager"
    			class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    		<property name="sessionFactory" ref="sessionFactory"/>
    		<property name="dataSource" ref="dataSource"/>
    	</bean>
    </beans>
    
  7. Create .\src\main\java\myapp\model\Person.java:
  8. package myapp.model;
    
    import jakarta.persistence.*;
    // import lombok.Data;
    
    @Entity
    // @Data 
    public class Person {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private String name;
        // add Lombok to classpath, uncomment annotation and you can remove all this:
        public Person() {}
        
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return String.format("Person[%s %s]", id, name);
        }
    }
    
  9. Create .\src\main\java\myapp\rest\PersonResource.java:
  10. package myapp.rest;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import myapp.dao.PersonDao;
    import myapp.model.Person;
    
    @RestController
    @RequestMapping("/person")
    public class PersonResource {
    
    	@Autowired
    	PersonDao personDao;
    
    	@PostMapping("/new")
    	public Person create(@RequestBody Person person) {
    		person.setId(null);
    		return personDao.create(person);
    	}
    
    	@GetMapping("/all")
    	public List<Person> findAll() {
    		return personDao.findAll();
    	}
    }
    
  11. Create .\src\main\java\myapp\dao\PersonDao.java:
  12. package myapp.dao;
    
    import java.util.List;
    
    import org.springframework.stereotype.Repository;
    
    import jakarta.persistence.EntityManager;
    import jakarta.persistence.PersistenceContext;
    import jakarta.transaction.Transactional;
    import myapp.model.Person;
    
    @Repository
    public class PersonDao {
    
        @PersistenceContext
        private EntityManager em;
    
        @Transactional
        public Person create(Person person) {
            em.persist(person);
            return person;
        }
    
        public List<Person> findAll() {
            String queryString = "SELECT p FROM Person p";
            var query = em.createQuery(queryString, Person.class);
            var resultList = query.getResultList();
            return resultList;
        }
    
    }
    
  13. Launch server: mvn clean jetty:run:
  14. Get all people from database, add new one and get all once again:
  15. curl.exe -X GET http://localhost:8080/person/all
    curl.exe -X POST -H "Content-Type: application/json" -d '{"name":"Вася Петечкин"}' http://localhost:8080/person/new
    curl.exe -X GET http://localhost:8080/person/all

    You will see read/write operations work as expected.

Spring Java-config Rest

[edit | edit source]
  1. Create .\pom.xml:
  2. <project>
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>mygroup</groupId>
    	<artifactId>SpringMvcJavaConfig</artifactId>
    	<version>0.1</version>
    	<packaging>war</packaging>
    	
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<maven.compiler.source>18</maven.compiler.source>
    		<maven.compiler.target>18</maven.compiler.target>
    
    		<spring.version>6.0.3</spring.version>
    		<jetty-maven-plugin.version>11.0.12</jetty-maven-plugin.version>
    	</properties>
    	
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-webmvc</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-orm</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>jakarta.servlet</groupId>
    			<artifactId>jakarta.servlet-api</artifactId>
    			<version>6.0.0</version>
    			<scope>provided</scope>
    		</dependency>
    		<dependency>
    			<groupId>com.fasterxml.jackson.core</groupId>
    			<artifactId>jackson-databind</artifactId>
    			<version>2.15.2</version>
    		</dependency>
    		<dependency>
    			<groupId>org.hibernate.orm</groupId>
    			 <artifactId>hibernate-core</artifactId>
    			<version>6.2.6.Final</version>
    		</dependency>
    		<dependency>
    			<groupId>com.h2database</groupId>
    			<artifactId>h2</artifactId>
    			<version>2.1.214</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.commons</groupId>
    			<artifactId>commons-dbcp2</artifactId>
    			<version>2.9.0</version>
    		</dependency>
    		<dependency>
    			<groupId>org.projectlombok</groupId>
    			<artifactId>lombok</artifactId>
    			<version>1.18.28</version>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<finalName>myapp</finalName>
    		<pluginManagement>
    			<plugins>
    				<plugin>
    					<groupId>org.eclipse.jetty</groupId>
    					<artifactId>jetty-maven-plugin</artifactId>
    					<version>${jetty-maven-plugin.version}</version>
    				</plugin>
    			</plugins>
    		</pluginManagement>
    	</build>
    	
    </project>
    
  3. Create .\src\main\java\myapp\config\WebInit.java:
  4. package myapp.config;
    
    import org.springframework.web.WebApplicationInitializer;
    import org.springframework.web.context.ContextLoaderListener;
    import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
    import org.springframework.web.servlet.DispatcherServlet;
    
    import jakarta.servlet.ServletContext;
    import jakarta.servlet.ServletRegistration;
    
    public class WebInit implements WebApplicationInitializer {
        @Override
        public void onStartup(ServletContext container) {
            var context = new AnnotationConfigWebApplicationContext();
            context.setConfigLocation("myapp.config");
    
            container.addListener(new ContextLoaderListener(context));
    
            ServletRegistration.Dynamic dispatcher = container
              .addServlet("dispatcher", new DispatcherServlet(context));
            
            dispatcher.setLoadOnStartup(1);
            dispatcher.addMapping("/");
        }
        
    }
    
  5. Create .\src\main\java\myapp\config\WebConfig.java:
  6. package myapp.config;
    
    import java.util.List;
    import java.util.Properties;
    
    import javax.sql.DataSource;
    
    import org.hibernate.SessionFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
    import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
    import org.springframework.orm.hibernate5.HibernateTransactionManager;
    import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = {"myapp"})
    @EnableTransactionManagement
    public class WebConfig implements WebMvcConfigurer {
        
    
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
            var messageConverter = new MappingJackson2HttpMessageConverter();
            // messageConverter.setDefaultCharset(Charset.forName("UTF-8")); //doesn't help anyway
            messageConverters.add(messageConverter);
        }
    
        @Bean
        public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
            var sessionFactory = new LocalSessionFactoryBean();
            sessionFactory.setDataSource(dataSource);
            sessionFactory.setPackagesToScan("myapp.model");
            sessionFactory.setHibernateProperties(hibernateProperties());
            return sessionFactory;
        }
        @Bean
        public PlatformTransactionManager hibernateTransactionManager(SessionFactory sessionFactory) {
            var transactionManager = new HibernateTransactionManager();
            transactionManager.setSessionFactory(sessionFactory);
            return transactionManager;
        }
        @Bean
        public DataSource dataSource() {
            return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                // .addScript("classpath:schema.sql")
                // .addScript("classpath:data.sql")
                .build();
        }
        private Properties hibernateProperties() {
    
            // set hibernate properties
            Properties props = new Properties();
    
            props.setProperty("hibernate.hbm2ddl.auto", "create");
            // props.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
    
            return props;
        }
    }
    
  7. Create .\src\main\java\myapp\model\Person.java:
  8. package myapp.model;
    
    import jakarta.persistence.Entity;
    import jakarta.persistence.GeneratedValue;
    import jakarta.persistence.GenerationType;
    import jakarta.persistence.Id;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Entity
    public class Person {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private String name;
        
    }
    
  9. Create .\src\main\java\myapp\rest\PersonResource.java:
  10. package myapp.rest;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import myapp.dao.PersonDao;
    import myapp.model.Person;
    
    @RestController
    @RequestMapping("/person")
    public class PersonResource {
    
    	@Autowired
    	PersonDao personDao;
    
    	@PostMapping("/new")
    	public Person create(@RequestBody Person person) {
    		person.setId(null);
    		return personDao.create(person);
    	}
    
    	@GetMapping("/all")
    	public List<Person> findAll() {
    		return personDao.findAll();
    	}
    }
    
  11. Create .\src\main\java\myapp\dao\PersonDao.java:
  12. package myapp.dao;
    
    import java.util.List;
    
    import org.springframework.stereotype.Repository;
    
    import jakarta.persistence.EntityManager;
    import jakarta.persistence.PersistenceContext;
    import jakarta.transaction.Transactional;
    import myapp.model.Person;
    
    @Repository
    public class PersonDao {
    
        @PersistenceContext
        private EntityManager em;
    
        @Transactional
        public Person create(Person person) {
            em.persist(person);
            return person;
        }
    
        public List<Person> findAll() {
            String queryString = "SELECT p FROM Person p";
            var query = em.createQuery(queryString, Person.class);
            var resultList = query.getResultList();
            return resultList;
        }
    
    }
    
  13. Launch web application and perform read/write operations through Rest endpoint:
  14. mvn clean jetty:run
    curl.exe -X GET http://localhost:8080/person/all
    curl.exe -X POST -H "Content-Type: application/json" -d '{"name":"Вася Петечкин"}' http://localhost:8080/person/new


Jakarta EE

[edit | edit source]

Glassfish MySQL Rest

[edit | edit source]

Prerequisites: standalone MySQL server.

This project differs from other sample applications on this page: instead of using embedded database, it needs separate MySQL server instance up and running. If you don't have standalone MySQL server installed, you wouldn't be able to launch this application, otherwise follow these instructions:

  1. Create .\pom.xml:
  2. <?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>example</groupId>
    	<artifactId>jakartaee-hello-world</artifactId>
    	<version>0.1-SNAPSHOT</version>
    	<packaging>war</packaging>
    
    	<name>jakartaee-hello-world</name>
    	<description>
    		asadmin start-domain --verbose
    		mysqld --console
    		mvn clean package
    		asadmin deploy --force target\myapp.war
    		curl.exe -X GET http://localhost:8080/myapp/rest/person/all/
    		curl.exe -X POST -H "Content-Type: application/json" -d '{"name":"Вася Петечкин"}' http://localhost:8080/myapp/rest/person/new
    		
    	</description>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<project.report.sourceEncoding>UTF-8</project.report.sourceEncoding>
    		<maven.compiler.release>17</maven.compiler.release>
    		<jakartaee-api.version>10.0.0</jakartaee-api.version>
    		<compiler-plugin.version>3.11.0</compiler-plugin.version>
    		<war-plugin.version>3.3.2</war-plugin.version>
    	</properties>
    
    	<dependencies>
    
    		<dependency>
    			<groupId>org.projectlombok</groupId>
    			<artifactId>lombok</artifactId>
    			<version>1.18.28</version>
    		</dependency>
    
    		<dependency>
    			<groupId>jakarta.platform</groupId>
    			<artifactId>jakarta.jakartaee-api</artifactId>
    			<version>${jakartaee-api.version}</version>
    			<scope>provided</scope>
    		</dependency>
    		<!-- https://mvnrepository.com/artifact/org.hibernate.orm/hibernate-core -->
    		<dependency>
    			<groupId>org.hibernate.orm</groupId>
    			 <artifactId>hibernate-core</artifactId>
    			<version>6.2.6.Final</version>
    		</dependency>
    		<dependency>
    			<groupId>com.mysql</groupId>
    			<artifactId>mysql-connector-j</artifactId>
    			<version>8.0.33</version>
    		</dependency>
    		
    
    	</dependencies>
    
    	<build>
    		<!-- This bad boi becomes a parl of url and .war filename: -->
    		<finalName>myapp</finalName>
    		<plugins>
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-compiler-plugin</artifactId>
    				<version>${compiler-plugin.version}</version>
    			</plugin>
    			<plugin>
    				<artifactId>maven-war-plugin</artifactId>
    				<version>${war-plugin.version}</version>
    				<configuration>
    					<failOnMissingWebXml>false</failOnMissingWebXml>
    				</configuration>
    			</plugin>
    
    		</plugins>
    	</build>
    </project>
    
  3. Create .\src\main\java\myapp\model\Person.java:
  4. package myapp.model;
    
    import jakarta.persistence.Entity;
    import jakarta.persistence.GeneratedValue;
    import jakarta.persistence.GenerationType;
    import jakarta.persistence.Id;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Entity
    public class Person {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private String name;
        
    }
    
  5. Create .\src\main\java\myapp\rest\DemoApplication.java:
  6. package myapp.rest;
    
    import jakarta.ws.rs.ApplicationPath;
    import jakarta.ws.rs.core.Application;
    
    @ApplicationPath("/rest/*")
    public class DemoApplication extends Application {
    }
    
  7. Create .\src\main\java\myapp\rest\PersonResource.java:
  8. package myapp.rest;
    
    import java.util.List;
    
    import jakarta.inject.Inject;
    import jakarta.ws.rs.Consumes;
    import jakarta.ws.rs.GET;
    import jakarta.ws.rs.POST;
    import jakarta.ws.rs.Path;
    import jakarta.ws.rs.Produces;
    import jakarta.ws.rs.core.MediaType;
    import myapp.dao.PersonDao;
    import myapp.model.Person;
    
    @Path("person")
    public class PersonResource {
    
    	@Inject
    	PersonDao personDao;
    
    	@GET
    	@Path("all")
    	@Produces({ MediaType.APPLICATION_JSON })
    	public List<Person> findAll() {
    		var list = personDao.findAll();
    		return list;
    	}
    	@POST
    	@Path("new")
    	@Produces({ MediaType.APPLICATION_JSON })
    	@Consumes(MediaType.APPLICATION_JSON)
    	public Person create(Person person) {
    		person.setId(null);
    		System.out.println(person);
    		personDao.create(person);
    		return person;
    	}
    }
    
  9. Create .\src\main\resources\META-INF\persistence.xml:
  10. <persistence xmlns="https://jakarta.ee/xml/ns/persistence" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    	xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" 
    	version="3.0">
    	
    	<persistence-unit 	name="only-unit"
    						transaction-type="JTA" >
            
            <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
            <jta-data-source>java:app/jdbc/embeddedDS</jta-data-source>
    		
    		<properties>
    			<property name="jakarta.persistence.schema-generation.database.action" value="drop-and-create"/>
    			<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" />
    		</properties>
    	</persistence-unit>
    	
    </persistence>
    
  11. Create .\src\main\java\myapp\dao\PersonDao.java:
  12. package myapp.dao;
    
    import java.util.List;
    
    import jakarta.enterprise.context.ApplicationScoped;
    import jakarta.persistence.EntityManager;
    import jakarta.persistence.PersistenceContext;
    import jakarta.transaction.Transactional;
    import myapp.model.Person;
    
    @ApplicationScoped
    public class PersonDao {
    
    	@PersistenceContext(unitName = "only-unit")
    	private EntityManager em;
    
    	@Transactional
    	public Person create(Person person) {
    		em.persist(person);
    		return person;
    	}
    
    	public List<Person> findAll() {
    		String queryString = "SELECT p FROM Person p";
    		var query = em.createQuery(queryString, Person.class);
    		var resultList = query.getResultList();
    		return resultList;
    	}
    
    }
    
  13. Create .\src\main\webapp\WEB-INF\glassfish-resources.xml:
  14. <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
    <resources>
        <jdbc-connection-pool 
                    datasource-classname="com.mysql.cj.jdbc.MysqlDataSource"
                    name="embeddedConnPool"
                    res-type="javax.sql.DataSource">
    
            <property name="URL" value="jdbc:mysql://localhost:3306/mydb?createDatabaseIfNotExist=true&amp;autoReconnect=true&amp;useSSL=false&amp;allowPublicKeyRetrieval=true" />
            <property name="User" value="root" />
            <property name="Password" value="qwerty" />
    
        </jdbc-connection-pool>
    
        <jdbc-resource jndi-name="java:app/jdbc/embeddedDS" pool-name="embeddedConnPool" enabled="true" />
    </resources>
    
  15. Start MySQL server, start embedded Glassfish with your webapp deployed:
  16. mysqld --console
    mvn clean package org.codehaus.cargo:cargo-maven3-plugin:run -Dcargo.maven.containerId=glassfish7x
  17. Access REST endpoint to perform read/write operations:
  18. curl.exe -X GET http://localhost:8080/myapp/rest/person/all/
    curl.exe -X POST -H "Content-Type: application/json" -d '{"name":"Вася Петечкин"}' http://localhost:8080/myapp/rest/person/new
  19. To stop Glassfish, send stop-domain command via web-request, after that press Ctrl+C in appropriate terminal window.
  20. curl.exe -X GET http://localhost:4848/__asadmin/stop-domain -u admin:adminadmin


Glassfish H2-Embedded Rest

[edit | edit source]
  1. Create .\pom.xml:
  2. <?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>example</groupId>
    	<artifactId>jakartaee-hello-world</artifactId>
    	<version>0.1-SNAPSHOT</version>
    	<packaging>war</packaging>
    
    	<name>jakartaee-hello-world</name>
    	<description>
    	</description>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<project.report.sourceEncoding>UTF-8</project.report.sourceEncoding>
    		<maven.compiler.release>17</maven.compiler.release>
    		<jakartaee-api.version>10.0.0</jakartaee-api.version>
    		<compiler-plugin.version>3.11.0</compiler-plugin.version>
    		<war-plugin.version>3.3.2</war-plugin.version>
    	</properties>
    
    	<dependencies>
    
    		<dependency>
    			<groupId>org.projectlombok</groupId>
    			<artifactId>lombok</artifactId>
    			<version>1.18.28</version>
    		</dependency>
    
    		<dependency>
    			<groupId>jakarta.platform</groupId>
    			<artifactId>jakarta.jakartaee-api</artifactId>
    			<version>${jakartaee-api.version}</version>
    			<scope>provided</scope>
    		</dependency>
    		<!-- https://mvnrepository.com/artifact/org.hibernate.orm/hibernate-core -->
    		<dependency>
    			<groupId>org.hibernate.orm</groupId>
    			 <artifactId>hibernate-core</artifactId>
    			<version>6.2.6.Final</version>
    		</dependency>
    		<dependency>
    			<groupId>com.h2database</groupId>
    			<artifactId>h2</artifactId>
    			<version>2.1.214</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.commons</groupId>
    			<artifactId>commons-dbcp2</artifactId>
    			<version>2.9.0</version>
    		</dependency>
    		
    
    	</dependencies>
    
    	<build>
    		<!-- This bad boi becomes a parl of url and .war filename: -->
    		<finalName>myapp</finalName>
    		<plugins>
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-compiler-plugin</artifactId>
    				<version>${compiler-plugin.version}</version>
    			</plugin>
    			<plugin>
    				<artifactId>maven-war-plugin</artifactId>
    				<version>${war-plugin.version}</version>
    				<configuration>
    					<failOnMissingWebXml>false</failOnMissingWebXml>
    				</configuration>
    			</plugin>
    
    		</plugins>
    	</build>
    </project>
    
  3. Create .\src\main\java\myapp\dao\PersonDao.java:
  4. package myapp.dao;
    
    import java.util.List;
    
    import jakarta.enterprise.context.ApplicationScoped;
    import jakarta.persistence.EntityManager;
    import jakarta.persistence.PersistenceContext;
    import jakarta.transaction.Transactional;
    import myapp.model.Person;
    
    @ApplicationScoped
    public class PersonDao {
    
    	@PersistenceContext(unitName = "only-unit")
    	private EntityManager em;
    
    	@Transactional
    	public Person create(Person person) {
    		em.persist(person);
    		return person;
    	}
    
    	public List<Person> findAll() {
    		String queryString = "SELECT p FROM Person p";
    		var query = em.createQuery(queryString, Person.class);
    		var resultList = query.getResultList();
    		return resultList;
    	}
    
    }
    
  5. Create .\src\main\java\myapp\model\Person.java:
  6. package myapp.model;
    
    import jakarta.persistence.Entity;
    import jakarta.persistence.GeneratedValue;
    import jakarta.persistence.GenerationType;
    import jakarta.persistence.Id;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Entity
    public class Person {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private String name;
        
    }
    
  7. Create .\src\main\java\myapp\rest\DemoApplication.java:
  8. package myapp.rest;
    
    import jakarta.ws.rs.ApplicationPath;
    import jakarta.ws.rs.core.Application;
    
    @ApplicationPath("/rest/*")
    public class DemoApplication extends Application {
    }
    
  9. Create .\src\main\java\myapp\rest\PersonResource.java:
  10. package myapp.rest;
    
    import java.util.List;
    
    import jakarta.inject.Inject;
    import jakarta.ws.rs.Consumes;
    import jakarta.ws.rs.GET;
    import jakarta.ws.rs.POST;
    import jakarta.ws.rs.Path;
    import jakarta.ws.rs.Produces;
    import jakarta.ws.rs.core.MediaType;
    import myapp.dao.PersonDao;
    import myapp.model.Person;
    
    @Path("person")
    public class PersonResource {
    
    	@Inject
    	PersonDao personDao;
    
    	@GET
    	@Path("all")
    	@Produces({ MediaType.APPLICATION_JSON })
    	public List<Person> findAll() {
    		var list = personDao.findAll();
    		return list;
    	}
    	@POST
    	@Path("new")
    	@Produces({ MediaType.APPLICATION_JSON })
    	@Consumes(MediaType.APPLICATION_JSON)
    	public Person create(Person person) {
    		person.setId(null);
    		System.out.println(person);
    		personDao.create(person);
    		return person;
    	}
    }
    
  11. Create .\src\main\resources\META-INF\persistence.xml:
  12. <persistence xmlns="https://jakarta.ee/xml/ns/persistence" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    	xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" 
    	version="3.0">
    	
    	<persistence-unit 	name="only-unit"
    						transaction-type="JTA" >
            
            <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
            <jta-data-source>java:app/jdbc/embeddedDS</jta-data-source>
    		
    		<properties>
    			<property name="jakarta.persistence.schema-generation.database.action" value="drop-and-create"/>
    			<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" />
    		</properties>
    	</persistence-unit>
    	
    </persistence>
    
  13. Create .\src\main\webapp\WEB-INF\glassfish-resources.xml:
  14. <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
    <resources>
        <jdbc-connection-pool 
                    datasource-classname="org.apache.commons.dbcp2.BasicDataSource"
                    name="embeddedConnPool"
                    res-type="javax.sql.DataSource">
    
            <property name="URL" value="jdbc:h2:mem:dataSource;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false" />
            <property name="User" value="root" />
            <property name="Password" value="qwerty" />
    
        </jdbc-connection-pool>
    
        <jdbc-resource jndi-name="java:app/jdbc/embeddedDS" pool-name="embeddedConnPool" enabled="true" />
    </resources>
    
  15. Start webapp in embedded Glassfish server:
  16. mvn clean package org.codehaus.cargo:cargo-maven3-plugin:run -Dcargo.maven.containerId=glassfish7x
  17. Access REST endpoint to perform read/write operations:
  18. curl.exe -X GET http://localhost:8080/myapp/rest/person/all/
    curl.exe -X POST -H "Content-Type: application/json" -d '{"name":"Вася Петечкин"}' http://localhost:8080/myapp/rest/person/new
  19. To stop server, send stop-domain command via web-request, after that press Ctrl+C in appropriate terminal window.
  20. curl.exe -X GET http://localhost:4848/__asadmin/stop-domain -u admin:adminadmin