skip to Main Content

I was assigned a case study project for recruitment process. I have developed a Java Spring project and used H2 in memory database.

I have to place a docker-compose.yml to root folder to dockerize that.

Even if my application runs correctly on intellij, it doesnt run on docker container.

They will run the following scenerio to run my application.

This scenario will be run by our reviewers during the review process. Make sure that these steps work as exactly same without any additional steps !

 1. Clone project  
git clone {repository-git-url}

 2. Run docker compose file (docker-compose.yml) and expose your service on port 8080  
docker-compose up -d

 3. Send a health check request and receive HttpStatus 200   
curl -L -X GET 'http://localhost:8080/health' 

To dockerize my spring project, i created a Dockerfile file. You can see my dockerfile below:

FROM adoptopenjdk/openjdk8
EXPOSE 8080
ARG JAR_FILE=target/fleet-management-0.0.1-SNAPSHOT.jar
ADD ${JAR_FILE} myapp.jar
ENTRYPOINT ["java","-jar","/myapp.jar"]

ENV SPRING_DATASOURCE_URL=jdbc:h2:mem:testdb
ENV SPRING_DATASOURCE_USERNAME=sa
ENV SPRING_DATASOURCE_PASSWORD=""

I also created a docker-compose.yml file. You can see below:

version: '3'
services:
  myapp:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 8080:8080
    environment:
      - SPRING_DATASOURCE_URL=jdbc:h2:mem:testdb
      - SPRING_DATASOURCE_USERNAME=sa
      - SPRING_DATASOURCE_PASSWORD=

I am using Java 8 and Spring Boot 2.7.1. Also, you can see my application.properties file below:

spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
spring.datasource.driverClassName=org.h2.Driver
spring.jpa.defer-datasource-initialization=true
spring.jpa.hibernate.ddl-auto=create

I can start a container with command "docker-compose up -d" but i cant run the application with command "docker run -p8080:8080 {ID}". It gives me error about H2 database.

 Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependen
cyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.f
actory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed
; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException
: Cannot load driver class: org.h2.Driver

How can i fix the issue?

2

Answers


  1. Chosen as BEST ANSWER

    I have solved the issue. I will share my files.

    application.properties:

    spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
    spring.jpa.defer-datasource-initialization=true
    spring.jpa.hibernate.ddl-auto=create
    spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
    

    Dockerfile

    FROM openjdk:8-jdk-alpine
    RUN mkdir /app
    COPY target/fleet-management-0.0.1-SNAPSHOT.jar /app/myapp.jar
    RUN mkdir /h2-data
    COPY h2-data/ /h2-data/
    ENTRYPOINT ["java","-jar","/app/myapp.jar"]
    CMD java -jar myapp.jar --spring.config.additional-location=file:/src/main/resources/application.properties
    

    docker-compose.yml

    version: "3"
    services:
      myapp:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
          - 8080:8080
        depends_on:
          - database
    
      database:
        image: oscarfonts/h2:latest
        ports:
          - 1521:1521
          - 81:81
        volumes:
          - ./h2-data:/h2-data
          - ./scripts:/docker-entrypoint-initdb.d
    

    and h2 dependency in pom.xml:

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>compile</scope>
        </dependency>
    

  2. This is a common scenario when the program is not able to find the relevant jar.
    The first thing I will do is look into the project dependency file over here and what it says regarding import configs for h2 drivers jar.

    If in case it is set to provided or test then you to change those accordingly.

    You can go with the route above or h2 jar can be imported and added to classpath manually as well. steps you need do is copy h2 jar to your docker and your run program command will be:

    ENTRYPOINT ["java","-cp","myapp.jar:h2-1.4.200.jar","EntryClass"]

    Although this is not recommended practice I just mentioned as an alternative, you can go with shade plugin.

    More read: What is the maven-shade-plugin used for, and why would you want to relocate Java packages?

    Hope this helps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search