Skip to content

Instantly share code, notes, and snippets.

@martialboniou
Last active March 21, 2021 20:19
Show Gist options
  • Save martialboniou/59fdad87a069316af678cb760934cbbb to your computer and use it in GitHub Desktop.
Save martialboniou/59fdad87a069316af678cb760934cbbb to your computer and use it in GitHub Desktop.
Java Snippets

Here's some random snippets for a better understanding of Java.

Table of Contents

New in 11

var

Inside a method body, the new keyword var replaces the type. It's not allowed when the compiler is incapable of infering the correct type of the variable.

// doesn't compile
var text = "Yo!";
text = 23; // Incompatible types

HTTP client

GET

var request = HttpRequest.newBuilder()
  .uri(URI.create("https//www.google.com"))
  .GET() // optional because default request method
  .build();
var client = HttpClient.newHttpClient();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) // use send() for the synchronous solution
  .thenApply(HttpResponse::body)
  .thenAccept(System.out::println);

POST

var request = HttpRequest.newBuilder()
  .uri(URI.create("https://postman-echo.com/post"))
  .header("Content-Type", "text/plain")
  .POST(HttpRequest.BodyPublishers.ofString("Hi there!"))
  .build();
var client = HttpClient.newHttpClient();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode()); // 200

BASIC-AUTH

var request = HttpRequest.newBuild()
  .uri(URI.create("https://postman-echo.com/basic-auth"))
  .build();
var client = HttpClient.newBuilder()
  .authenticator(new Authenticator() {
      @Override
      protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("postman", "password".toCharArray());
      }
    })
  .build();
var response = client.send(request, HttpResponse::BodyHandlers.ofString());
System.out.println(response.statusCode()); // 200

Zulu builds

On macOS & other BSD/Linux systems, use /usr/libexec/java_home -v 1.8to generate your$PATHas JavaEE is not for Java 9 and beyond (I had some issues w/ Java 15 Tomcat programs running well but maven/Hibernate standalone JAR/WAR or log4j2 failed; worked well with Glassfish 5.x by the way, because of the hardcoded path inasenv.conf`).

Inner classes

Shadowing

public class ShadowTest {

  public int x = 0;

  class FirstLevel {

    public int x = 1;

    void methodInFirstLevel(int x) { // instance method
      System.out.println("x = " + x); // 23
      System.out.println("this.x = " + this.x); // Should be 1
      System.out.println("ShadowTest.this.x = " + ShadowTest.this.x); // should be 0
    }
  }

  public static void main(String... args){
    ShadowTest st = new ShadowTest();
    ShadowTest.FirstLevel fl =  st.new FirstLevel(); // instance method so you must create an instance st of Shadowtest
    fl.methodInFirstLevel(23);
  }
}

Another example with a locally created Iterator

public class DataStructure {

    // Create an array
    private final static int SIZE = 15;
    private int[] arrayOfInts = new int[SIZE];

    public DataStructure() {
        // fill the array with ascending integer values
        for (int i = 0; i < SIZE; i++) {
            arrayOfInts[i] = i;
        }
    }

    public void printEven() {

        // Print out values of even indices of the array
        DataStructureIterator iterator = this.new EvenIterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();
    }

    interface DataStructureIterator extends java.util.Iterator<Integer> { }

    // Inner class implements the DataStructureIterator interface,
    // which extends the Iterator<Integer> interface

    private class EvenIterator implements DataStructureIterator {

        // Start stepping through the array from the beginning
        private int nextIndex = 0;

        public boolean hasNext() {

            // Check if the current element is the last in the array
            return (nextIndex <= SIZE - 1);
        }

        public Integer next() {

            // Record a value of an even index of the array
            Integer retValue = Integer.valueOf(arrayOfInts[nextIndex]);

            // Get the next even element
            nextIndex += 2;
            return retValue;
        }
    }

    public static void main(String s[]) {

        // Fill the array with integer values and print out only
        // values of even indices
        DataStructure ds = new DataStructure();
        ds.printEven();
    }
}

Anonymous classes

HelloWorld frenchGreeting = new HelloWorld() {
            String name = "tout le monde";
            public void greet() {
                greetSomeone("tout le monde");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Salut " + name);
            }
        };

Passing Reference Data Type Arguments

public class TestCircle{

  public static void main(String[] args){
    Circle circle = new Circle(); // constructor set (0,0)
    TestCircle tester = new TestCircle();

    System.out.println(circle.getX() + " . " + circle.getY()); // 0,0
    tester.moveCircle(circle,1,1);
    System.out.println(circle.getX() + " . " + circle.getY()); // 1,1 ie side effect on the fields
  }

  public void moveCircle(Circle circle, int deltaX, int deltaY){
    // reference data type parameters are also passed by value;
    // however, the values of the object's fields can be changed
    circle.setX(circle.getX() + deltaX);
    circle.setY(circle.getY() + deltaY);

    // assign a new reference to circle (no permanence)
    circle = new Circle(0,0);
  }
}

As a collection, you can use Collections.emptyList() or since Java 9, List.of() like in Lisp. Otherwise, Brian Goetz, Java Language Architect at Oracle, has introduced in Java 8 a monad like Maybe in Haskell.

import java.util.Optional;
import java.util.List;
import java.util.ArrayList;

public class TestOptional {

  // Task has:
  // fields: name : String, status : boolean
  // constructor: this(String name)
	private List<Task> tasks = new ArrayList<>();

	public Optional<Task> seekTask(String name){
		for (Task task : tasks) {
			if (task.getName() == name) {
				return Optional.of(task);
			}
		}
		return Optional.empty();
	}

	public static void main(String[] args){
    TestOptional tester = new TestOptional();
		tester.tasks.add(new Task("foo"));
		tester.tasks.add(new Task("baz"));
		Optional<Task> goodTask = tester.seekTask("foo");

	  goodTask.ifPresent(System.out::println);
		goodTask.ifPresent(value -> {
			System.out.println(value.getName());
		});

    Optional<Task> noTask = tester.seekTask("barNotBaz");
		noTask.ifPresentOrElse(value -> {
			System.out.println(value.getName());
		}, () -> System.err.println("Not found"));
	}
}

Notice the use of the lambda expressions (modern JavaScript also has the arrow functions; mandatory to make clean lexical closures)!

You also can use Optional.ofNullable(anObject) as if the specified value is null, then this method returns an empty instance of the Optional class: Optional.empty.

Enum

public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    private double mass() { return mass; }
    private double radius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
    public static void main(String[] args) {
        if (args.length != 1) {
            System.err.println("Usage: java Planet <earth_weight>");
            System.exit(-1);
        }
        double earthWeight = Double.parseDouble(args[0]);
        double mass = earthWeight/EARTH.surfaceGravity();
        for (Planet p : Planet.values()) // values() in Enum
           System.out.printf("Your weight on %s is %f%n",
                             p, p.surfaceWeight(mass));
    }
}

Annotations

Declaring an Annotation Type

import java.lang.annotation.*; // import this to use @Documented

@Documented // used to make the intel in @ClassPreamble appear in Javadoc-generated documentation
@interface ClassPreamble {
  String author();
  String date();
  int currentRevision() default 1;
  String lastModified() default "N/A";
  String lastModifiedBy() default "N/A";
  // Note use of array
  String[] reviewers();
}

// usage
@ClassPreamble (
  author = "Martial Boniou",
  date = "12/12/2020",
  currentRevision = 6,
  lastModified = "14/12/2020",
  lastModifiedBy = "Martial Boniou",
  // Note array notation
  reviewers = {"Alan Kay", "Cousin Eddie", "Martin Fowler"}
)
public class TestAnnotation {
  public static void main(String... args){
    System.out.println("And now, the bishop...");
  }
}

An advanced example

Source: Custom Annotations by Justin Albano

Creating your annotation: JsonField

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface JsonField {
  public String value() default "";
}

Using the annotation

public class Car {

  @JsonField("manufacturer") // the name of the parameter (value) can be omitted because only one
  private final String make;

  @JsonField
  private final String model;

  private final String year;

  public Car(String make, String model, String year) {
    this.make = make;
    this.model = model;
    this.year = year;
  }

  public String getMake() {
    return make;
  }

  public String getModel() {
    return model;
  }

  public String getYear() {
    return year;
  }

  @Override
  public String toString() {
    return year + " " + make + " " + model;
  }
}

Creating a serializer

The class

import java.lang.Object;
import java.lang.reflect.Field;

import java.util.Objects; // or /import static java.util.Objects.requireNonNull/ for direct sugae
import java.util.Map;
import java.util.HashMap;
import java.util.stream.Collectors; // or /import static java.util.stream.Collectors.joining/ for direct usage

public class JsonSerializer {

  public String serialize(Object object) throws JsonSerializeException {

    try {

      Class<?> objectClass = Objects.requireNonNull(object).getClass();
      Map<String, String> jsonElements = new HashMap<>();

      for (Field field: objectClass.getDeclaredFields()) {
        // Next, tell the reflection API to suppress the standard Java
        //       access checking in order to access the private field
	field.setAccessible(true);
        if (field.isAnnotationPresent(JsonField.class)) {
          jsonElements.put(getSerializedKey(field), (String) field.get(object));
        }
      }
      System.out.println(toJsonString(jsonElements));
      return toJsonString(jsonElements);
    }
    catch (IllegalAccessException e) {
      throw new JsonSerializeException(e.getMessage());
    }
  }

  private String toJsonString(Map<String, String> jsonMap) {
    String elementString = jsonMap.entrySet()
      .stream()
      .map(entry -> "\"" + entry.getKey() + "\":\"" + entry.getValue() + "\"")
      .collect(Collectors.joining(",")); // works like fold, reduce, #inject:into: in function languages, ruby, Smalltalk resp.
    return "{" + elementString + "}";
  }

  private static String getSerializedKey(Field field) {
    String annotationValue = field.getAnnotation(JsonField.class).value();

    return (annotationValue.isEmpty()) ? field.getName() : annotationValue;
  }
}

Check the elegant JsonSerializableFieldExtractor refactoring here.

A dummy exception

public class JsonSerializeException extends Exception {

  // use serialver to generate this one
  private static final long serialVersionUID = 8713387492080807461L;

  public JsonSerializeException(String message) {
    super(message);
  }
}

Testing the serialization

public class TestJsonSerializer {
  public static void main (String... args) {
    Car car = new Car("Citroen", "Xsara", "2004");
    JsonSerializer serializer = new JsonSerializer();
    try {
      serializer.serialize(car);
    }
    catch (JsonSerializeException e) {
      System.out.println(e.getMessage());
    }
  }
}

Try with resources

Java try with resources construct is an exception handling mechanism that automatically close resources like InputStream or a JDBC connection. Here's an example:

private static void printFile() throws IOException {

  try(FileInputStream input = new FileInputStream("file.txt")) {

    int data = input.read();
    while (data != -1) {
      System.out.println((char) data);
      data = input.read();
    }
  }
}

Since Java 9, you can create a resource outside the parentheses:

FileInputStream input = new FileInputStream("file.txt");
try (input) { // new syntax
  {...}

Make your own with:

public interface AutoClosable {
  public void close() throws Exception;
}

Interfaces

The methods in an interface are public and abstract, so it's not useful to write them with the public and/or abstract keywords. It's not recommended to write these keywords according to the Java SE specifications by Oracle.

/* when you got */
public interface Relatable {
    int isGreaterThan(Relatable object);
}
/* you can write a class */
import java.lang.Integer;
public class MyClass implements Relatable {
    public int value;
    public boolean isGreaterThan(Relatable other) {
        MyClass otherClass = (MyClass)other;
        return Integer.signum(this.value - otherClass.value);
    }
}

REMINDER: When you extend an interface that contains a default method, you can do the following:

  • not mention the default method at all, which lets your extended interface inherit the default method;
  • redeclare the default method, which makes it abstract;
  • redefine the default method, which overrides it.

BEWARE: if 2 or more independently defined default methods conflict, or a default method conflicts with an abstract method, then the Java compiler produces a compiler error. You must explicitly override the supertype methods, like in this example:

// incomplete code
public interface OperateCar {
  default int startEngine(EncryptedKey key) {
    // Implementation
    {...}
  }
}
public interface FlyCar {
 default int startEngine(EncryptedKey key) {
   // Implementation
   {...}
 }
}

The following class must override the method startEngine:

public class FlyingCar implements OperateCar, FlyCar {
  // {...}
  public int startEngine(EncryptedKey key) {
    FlyCar.super.startEngine(key);
    OperateCar.super.startEngine(key);
  }
}

You could invoke any of the default implementations (from OperateCar and FlyCar) with the super keyword.

IMPORTANT: All fields in interfaces are automatically public, static and final, and all methods that you declare or define (as default methods) are public. With abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.

Generic methods

The syntax for a generic method includes a list of type parameters, inside angle brackets, which appears before the method's return type.

public class Util {
  public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
    return p1.getKey().equals(p2.getKey()) &&
      return p1.getValue().equals(p2.getValue());
  }
}

public class Pair<K, V> {

  private K key;
  private V value;

  public Pair(K key, V value) {
    this.key = key;
    this.value = value;
  }

  public void setKey(K key) { this.key = key; }
  public void setValue(V value) { this.value = value; }
  public K getKey() { return key; }
  public V getValue() { return value; }
}

The complete syntax for invoking this static method would be:

Pair<Integer, String> p1 = new Pair<>(1, "apple");
Pair<Integer, String> p2 = new Pair<>(2, "orange");
// syntax one
boolean isSame = Util.<Integer, String>compare(p1, p2);
// syntax two
boolean isSame = Util.compare(p1, p2); // inference checked by the compiler

You should use the syntax two.

Stream

Basics

Since Java 8, it's a monad. Here's some examples:

import java.util.*;
import java.util.stream.Stream;
import java.util.stream.IntStream;

import java.util.List;
import java.util.Arrays;

public class TestStream {

  public static void main(String... args) {

  List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");

  myList
    .stream()
    .filter(s -> s.startsWith("c"))
    .map(String::toUpperCase)
    .sorted()
    .forEach(System.out::println); //C1\nC2

  Stream.of("a1", "a2", "a3") // directly
    .findFirst()
    .ifPresent(System.out::println); //a1

  IntStream.range(1, 4) // useful w/ forEach to replace the regular for-loop
    .mapToObj(i -> "a" + i)
    .forEach(System.out::println); //a1\na2\na3

  Stream.of("a1", "a2", "a3")
    .map(s -> s.substring(1))
    .mapToInt(Integer::parseInt) // also mapToLong(), mapToDouble()
    .max()
    .ifPresent(System.out::println); //3

  /* experiment laziness */
  System.out.println("Lazy1");
  Stream.of("d2", "a2", "b1", "b3", "c")
    .filter(s -> {
      System.out.println("filter: " + s); //nothing b/c intermediate operations will only be executed when a terminal operation is present
      return true;
    });

  System.out.println("Lazy2");
  Stream.of("d2", "a1")
    .filter(s -> {
      System.out.println("filter: " + s);
      return true;
    })
    .forEach(s -> System.out.println("forEach: " + s));
    /*
     * filter: d2
     * forEach: d2
     * filter: a1
     * forEach: a1
     */
  }
}

Notice the laziness of the operations.

Overcoming the reusability

Streams cannot be reused but:

import java.util.*;
import java.util.stream.Stream;
import java.util.function.Supplier;

public class TestSupplierStream {

  public static void main(String... args) {

    Supplier<Stream<String>> streamSupplier =
      () -> Stream.of("d2", "a2", "b1")
              .filter(s -> s.startsWith("a"));

    System.out.println(streamSupplier.get().anyMatch(s -> true)); // true
    System.out.println(streamSupplier.get().noneMatch(s -> true)); // false (no IllegalStateException)
  }
}

Check this for more intel about the Supplier<T> interface.

Advanced operations

collect

import java.util.*;
import java.util.stream.Stream;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import java.util.List;
import java.util.Arrays;

public class TestAdvancedStream {

  public static void main(String... args) {

    // package-private fields
    class Person {
     String name;
      int age;

      Person(String name, int age) {
        this.name = name;
        this.age = age;
      }

      @Override
      public String toString() {
        return name;
      }
    }

    List<Person> persons = Arrays.asList(
      new Person("Max", 18),
      new Person("Peter", 23),
      new Person("Pamela", 23),
      new Person("David", 12)
    );
    // Simple collect
    List<Person> filtered =
      persons
        .stream()
        .filter(p -> p.name.startsWith("P"))
        .collect(Collectors.toList()); // as an ArrayList
    System.out.println(filtered); // [Peter, Pamela]
    // Group collect
    Map<Integer, List<Person>> personsByAge =
      persons
        .stream()
        .collect(Collectors.groupingBy(p -> p.age));
    personsByAge
      .forEach((age, p) -> System.out.format("age %s: %s\n", age, p));
    /*
     * age 18: [Max]
     * age 23: [Peter, Pamela]
     * age 12: [David]
     */
    // Aggregation collect
    Double averageAge = persons
      .stream()
      .collect(Collectors.averagingInt(p -> p.age)); // or summarizingInt() for full stats
    System.out.println(averageAge); // 19.0
    // Joining collect
    String phrase = persons
      .stream()
      .filter(p -> p.age >= 18)
      .map(p -> p.name)
      .collect(Collectors.joining(" and ", "In Germany ", " are of legal age.")); // joining accepts a separator and optional prefix & suffix
    System.out.println(phrase);
    /* In Germany Max and Peter and Pamela are of legal age.
     */
    // Personalizing a collector
    Collector<Person, StringJoiner, String> personNameCollector =
      Collector.of( // IMPORTANT: returns a new Collector described by the given supplier, accumulator, and combiner functions (static <T,R> Collector <T,R,R>)
          () -> new StringJoiner(" | "),        // supplier
          (j,p) -> j.add(p.name.toUpperCase()), // accumulator
          (j1, j2) -> j1.merge(j2),             // combiner (merge 2 StringJoiners into one)
          StringJoiner::toString);              // finisher
    String names = persons
      .stream()
      .collect(personNameCollector);
    System.out.println(names); // MAX | PETER | PAMELA | DAVID
  }
}

flatMap

import java.util.*;
import java.util.stream.Stream;
import java.util.stream.IntStream;

import java.util.List;
import java.util.ArrayList;

public class TestFlatMap {

  public static void main(String... args) {

    // package-private fields
    class Bar {
      String name;

      Bar(String name) {
        this.name = name;
      }
    }
    class Foo {
     String name;
     List<Bar> bars = new ArrayList<>();

     Foo(String name) {
       this.name = name;
     }
    }

    List<Foo> foos = new ArrayList<>();
    // two elegant Smalltalk-like loop to create:
    // - 3 foos
    // - 3 bars in each foo
    IntStream
      .range(1, 4)
      .forEach(i -> foos.add(new Foo("Foo" + i)));
    foos.forEach(f ->
        IntStream
          .range(1, 4)
          .forEach(i -> f.bars.add(new Bar("Bar" + i + " <- " + f.name))));
    //FlatMap accepts a function which has to return a stream of objects
    foos.stream()
      .flatMap(f -> f.bars.stream())
      .forEach(b -> System.out.println(b.name));
    /* Bar1 <- Foo1
     * Bar2 <- Foo1
     * Bar3 <- Foo1
     * Bar1 <- Foo2 etc... */
    // A better version:
    IntStream.range(1, 4)
      .mapToObj(i -> new Foo("Foo" + i))
      .peek(f -> IntStream.range(1, 4) // IMPORTANT: peek NEEDS a terminal operation
          .mapToObj(i -> new Bar("Bar" + i + " <- " + f.name))
          .forEach(f.bars::add))
      .flatMap(f -> f.bars.stream())
      .forEach(b -> System.out.println(b.name));
  }
}

In this example, the stream of 3 foo objects has been transformed into a stream of 9 bar objects. If you're unsure about the usage of peek(), check here. (REMINDER: all intermediate operations like peek() are lazy, and, as a result, no operations will have any effect until the pipeline starts to work.)

3 reduce methods

Try this code example with the persons instance assigned in the collect section.

Accumulator only

    persons
      .stream()
      .reduce((p1,p2) -> p1.age > p2.age ? p1 : p2) // a BinaryOperator accumulator
      .ifPresent(System.out::println); // Pamela

An identity value & an accumulator

    Person result =
      persons
        .stream()
        .reduce(new Person("", 0), (p1, p2) -> { // both an identity value AND a BinaryOperator accumulator
          p1.age += p2.age;
          p1.name += p2.name;
          return p1;
        });
    System.out.format("name=%s; age=%s\n", result.name, result.age); // name=MaxPeterPamelaDavid; age=76

An identity value, an accumulator & a combiner

    Integer ageSum = persons
        .stream() // replace with .parallelStream() to test the parallel version
        .reduce(
            0,                            // an identity value
            (sum, p) -> sum += p.age,     // a BiFunction accumulator
            (sum1, sum2) -> sum1 + sum2); // a BinaryOperator combiner
    System.out.println(ageSum); // 76

If you use stream(), only the accumulator is invoked. If you switched to the parallel stream version parallelStream(), the combiner is invoked too (and both works together). Check the next section.

Parallel streams

Add -Djava.util.concurrent.ForkJoinPool.common.parallelism=<number> to the JVM parameter in the command line if you want to maximize the number of threads, otherwise you'll use the default (7 on my Macbook Air M1).

import java.util.concurrent.ForkJoinPool;
import java.util.Arrays;

public class TestParallelStreams {
  public static void main(String... args) {
    // Checking
    ForkJoinPool commonPool = ForkJoinPool.commonPool();
    System.out.println(commonPool.getParallelism());
    // ParallelStream
    Arrays.asList("a1", "a2", "b1", "c2", "c1")
      .parallelStream()
      .filter(s -> {
        System.out.format("filter: %s [%s]\n",
            s, Thread.currentThread().getName());
        return true;
      })
      .map(s -> {
        System.out.format("map: %s [%s]\n",
            s, Thread.currentThread().getName());
        return s.toUpperCase();
      })
      .sorted((s1, s2) -> { // sort is executed sequentially on the main thread onl
        System.out.format("sort: %s <> %s [%s]\n",
            s1, s2, Thread.currentThread().getName());
        return s1.compareTo(s2);
      })
      .forEach(s -> System.out.format("forEach: %s [%s]\n",
            s, Thread.currentThread().getName()));
  }
}

If the length of the specified array is less than the minimum granulatity, then it is sorted using the appropriate Arrays.sort method (instead of Arrays.parallelSort()).

Private constructor

As in the Singleton pattern:

class Singleton {
  private static Singleton instance;
  int a;

  private Singleton() { // private constructor
    a = 10;
  }
  public static Singleton getInstance() {
    if (instance == null) {
      instance = new Singleton();
    }
    return instance;
  }
  public String toString() {
    return String.valueOf(a);
  }
}

Web applications

A note about JavaEE

When I tried JPA/EJB by hand, I checked the Dominique Liard's tutorial (in french) and I enjoyed this demo but I prefered to create a Maven project with these pom.xml and src/main/resources/META-INF/persistence.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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

    <groupId>net.hondana</groupId>
    <artifactId>intro-jpa</artifactId>
    <packaging>jar</packaging>
    <version>0.1.0</version>

      <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
      </properties>

      <dependencies>
        <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-core</artifactId>
          <version>5.2.17.Final</version>
          <type>pom</type>
        </dependency>
        <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-entitymanager</artifactId>
          <version>5.2.17.Final</version>
        </dependency>
        <dependency>
          <groupId>org.hibernate.javax.persistence</groupId>
          <artifactId>hibernate-jpa-2.1-api</artifactId>
          <version>1.0.0.Final</version>
        </dependency>
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.15</version>
        </dependency>
        <!--<dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.14.1</version>
      </dependency>
      <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.14.1</version>
      </dependency>
        -->
        <dependency>
          <groupId>joda-time</groupId>
          <artifactId>joda-time</artifactId>
          <version>2.9.2</version>
        </dependency>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
        </dependency>
      </dependencies>

      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
              <archive>
                <manifest>
                  <mainClass>net.hondana.webstore.Console</mainClass>
                </manifest>
              </archive>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.4</version>
            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>shade</goal>
                </goals>
                <configuration>
                  <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                      <mainClass>net.hondana.webstore.Console</mainClass>
                    </transformer>
                  </transformers>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
        <resources>
          <resource>
            <directory>src/main/resources/META-INF</directory>
            <targetPath>META-INF</targetPath>
            <includes>
              <include>persistence.xml</include>
            </includes>
          </resource>
        </resources>
      </build>

</project>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
                   http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
  <persistence-unit name="WebStore">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <class>net.hondana.webstore.business.Article</class>
    <properties>
      <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"></property>
      <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/WebStore?useSSL=false"></property>
      <property name="javax.persistence.jdbc.user" value="root"></property>
      <property name="javax.persistence.jdbc.password" value="root"></property>

      <property name="hibernate.dialect"
              value="org.hibernate.dialect.MySQLDialect"/>
    </properties>
  </persistence-unit>
</persistence>

A note about Spring Boot

If you don't use a Maven Wrapper, you may have to repackage (according to remko de knikker, by adding repackage in the executions:execution:goals:goal node in the spring-boot-maven-plugin node of build:plugins:plugin):

mvn -N io.takari:maven:wrapper
./mvnw clean install
./mvnw spring-boot:run

In case of problem, you can simply remove the binaries.

Troubleshooting with Glassfish

In order to try Glassfish 5, I've had to install 5.0 because there's a bug in 5.1 (malformed enctype in the <form>: application/x-www-form-urlencoded instead of multipart/form-data). I've been able to deploy some WARs by disabling the Implicit CDI. For a clean MySQL integration, you need a connector JAR in the domain's lib/ext and a correct JDBC Connection Pool, say:

  • Resource Type: javax.sql.DataSource;
  • Datasource Classname: com.mysql.cj.jdbc.MysqlDataSource;
  • URL: jdbc:mysql://localhost:3306;
  • useSSL: false.

You can use jdbc:mysql://localhost:3306?useSSL=false directly as URL.

Published by Martial BONIOU (2021-03-19)

TOC generated by gh-md-toc and install via Homebrew

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment