Merge branch 'eugenp:master' into master
This commit is contained in:
commit
ce9fa68436
|
@ -7,5 +7,6 @@ This module contains articles about Project Jigsaw and the Java Platform Module
|
|||
- [Introduction to Project Jigsaw](http://www.baeldung.com/project-jigsaw-java-modularity)
|
||||
- [A Guide to Java 9 Modularity](https://www.baeldung.com/java-9-modularity)
|
||||
- [Java 9 java.lang.Module API](https://www.baeldung.com/java-9-module-api)
|
||||
- [Java 9 Illegal Reflective Access Warning](https://www.baeldung.com/java-illegal-reflective-access)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
DIR=baeldung-agent
|
||||
|
||||
# compile
|
||||
mkdir -p out/${DIR}
|
||||
javac -d out/${DIR} $(find ${DIR} -type f -name "*.java")
|
||||
|
||||
# package
|
||||
mkdir -p mods
|
||||
jar --create --file=mods/${DIR}.jar --manifest=${DIR}/manifest.txt -C out/${DIR} .
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
DIR=baeldung-reflected
|
||||
|
||||
# compile
|
||||
mkdir -p out/${DIR}
|
||||
javac -d out/${DIR} $(find ${DIR} -type f -name "*.java")
|
||||
|
||||
# package
|
||||
mkdir -p mods
|
||||
jar --create --file=mods/${DIR}.jar -C out/${DIR} .
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
DIR=baeldung-intermedium
|
||||
|
||||
# compile
|
||||
mkdir -p out/${DIR}
|
||||
javac -d out/${DIR} $(find ${DIR} -type f -name "*.java")
|
||||
|
||||
# package
|
||||
mkdir -p mods
|
||||
jar --create --file=mods/${DIR}.jar -C out/${DIR} .
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
DIR=baeldung-reflecting-named
|
||||
|
||||
# compile
|
||||
mkdir -p out/${DIR}
|
||||
javac -d out/${DIR} --module-path mods $(find ${DIR} -type f -name "*.java")
|
||||
|
||||
# package
|
||||
mkdir -p mods
|
||||
jar --create --file=mods/${DIR}.jar -C out/${DIR} .
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
DIR=baeldung-reflecting-unnamed
|
||||
|
||||
# compile
|
||||
mkdir -p out/${DIR}
|
||||
javac -d out/${DIR} $(find ${DIR} -type f -name "*.java")
|
||||
|
||||
# package
|
||||
mkdir -p mods
|
||||
jar --create --file=mods/${DIR}.jar -C out/${DIR} .
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
java --module-path mods \
|
||||
--add-opens baeldung.reflected/com.baeldung.reflected.internal=baeldung.reflecting.named \
|
||||
--module baeldung.reflecting.named/com.baeldung.reflecting.named.Main
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
java --module-path mods \
|
||||
--add-opens baeldung.reflected/com.baeldung.reflected.internal=baeldung.intermedium \
|
||||
--module baeldung.reflecting.named/com.baeldung.reflecting.named.MainWithForwardOpen
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
java --module-path mods \
|
||||
-javaagent:mods/baeldung-agent.jar=com.baeldung.reflected.internal.InternalNonPublicClass,com.baeldung.reflecting.named.Main \
|
||||
--module baeldung.reflecting.named/com.baeldung.reflecting.named.Main
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/bash
|
||||
java -cp "mods/*" com.baeldung.reflecting.unnamed.Main
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/bash
|
||||
java -cp "mods/*" --add-opens java.base/java.lang=ALL-UNNAMED com.baeldung.reflecting.unnamed.Main
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/bash
|
||||
java -cp "mods/*" -javaagent:mods/baeldung-agent.jar com.baeldung.reflecting.unnamed.Main
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
|
||||
rm -rf out
|
||||
rm -rf mods
|
|
@ -0,0 +1,69 @@
|
|||
package com.baeldung.agent;
|
||||
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.util.*;
|
||||
|
||||
public class LoadTimeAgent {
|
||||
public static void premain(String agentArgs, Instrumentation inst) {
|
||||
System.out.println("agentArgs: " + agentArgs);
|
||||
|
||||
if (agentArgs != null) {
|
||||
addExportsAndOpensByClassName(inst, agentArgs);
|
||||
}
|
||||
else {
|
||||
addExportsAndOpensToUnnamedModule(inst);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addExportsAndOpensByClassName(Instrumentation inst, String agentArgs) {
|
||||
String[] array = agentArgs.split(",");
|
||||
try {
|
||||
String className1 = array[0];
|
||||
String className2 = array[1];
|
||||
Class<?> clazz1 = Class.forName(className1);
|
||||
Class<?> clazz2 = Class.forName(className2);
|
||||
|
||||
Module srcModule = clazz1.getModule();
|
||||
Module targetModule = clazz2.getModule();
|
||||
redefineModule(inst, srcModule, targetModule);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void addExportsAndOpensToUnnamedModule(Instrumentation inst) {
|
||||
Module unnamedModule = ClassLoader.getSystemClassLoader().getUnnamedModule();
|
||||
Set<Module> modules = ModuleLayer.boot().modules();
|
||||
|
||||
for (Module m : modules) {
|
||||
redefineModule(inst, m, unnamedModule);
|
||||
}
|
||||
}
|
||||
|
||||
private static void redefineModule(Instrumentation inst, Module src, Module target) {
|
||||
// prepare extra reads
|
||||
Set<Module> extraReads = Collections.singleton(target);
|
||||
|
||||
// prepare extra exports
|
||||
Set<String> packages = src.getPackages();
|
||||
Map<String, Set<Module>> extraExports = new HashMap<>();
|
||||
for (String pkg : packages) {
|
||||
extraExports.put(pkg, extraReads);
|
||||
}
|
||||
|
||||
// prepare extra opens
|
||||
Map<String, Set<Module>> extraOpens = new HashMap<>();
|
||||
for (String pkg : packages) {
|
||||
extraOpens.put(pkg, extraReads);
|
||||
}
|
||||
|
||||
// prepare extra uses
|
||||
Set<Class<?>> extraUses = Collections.emptySet();
|
||||
|
||||
// prepare extra provides
|
||||
Map<Class<?>, List<Class<?>>> extraProvides = Collections.emptyMap();
|
||||
|
||||
// redefine module
|
||||
inst.redefineModule(src, extraReads, extraExports, extraOpens, extraUses, extraProvides);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
Premain-Class: com.baeldung.agent.LoadTimeAgent
|
||||
Can-Redefine-Classes: true
|
||||
Can-Retransform-Classes: true
|
|
@ -0,0 +1,3 @@
|
|||
module baeldung.agent {
|
||||
requires java.instrument;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.intermedium;
|
||||
|
||||
public class ForwardOpen {
|
||||
public static void addOpens(Class<?> clazz1, Class<?> clazz2) {
|
||||
Module currentModule = ForwardOpen.class.getModule();
|
||||
Module srcModule = clazz1.getModule();
|
||||
Module targetModule = clazz2.getModule();
|
||||
|
||||
System.out.println("current module: " + currentModule.getName());
|
||||
System.out.println("source module: " + srcModule.getName());
|
||||
System.out.println("target module: " + targetModule.getName());
|
||||
|
||||
srcModule.addOpens(clazz1.getPackageName(), targetModule);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
module baeldung.intermedium {
|
||||
exports com.baeldung.intermedium;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.reflected.exported;
|
||||
|
||||
class ExportedNonPublicClass {
|
||||
public static void testPublicStaticMethod() {
|
||||
System.out.println("ExportedNonPublicClass.testPublicStaticMethod()");
|
||||
}
|
||||
|
||||
private static void testPrivateStaticMethod() {
|
||||
System.out.println("ExportedNonPublicClass.testPrivateStaticMethod()");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.reflected.exported;
|
||||
|
||||
public class ExportedPublicClass {
|
||||
public static void testPublicStaticMethod() {
|
||||
System.out.println("ExportedPublicClass.testPublicStaticMethod()");
|
||||
}
|
||||
|
||||
private static void testPrivateStaticMethod() {
|
||||
System.out.println("ExportedPublicClass.testPrivateStaticMethod()");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.reflected.internal;
|
||||
|
||||
class InternalNonPublicClass {
|
||||
public static void testPublicStaticMethod() {
|
||||
System.out.println("InternalNonPublicClass.testPublicStaticMethod()");
|
||||
}
|
||||
|
||||
private static void testPrivateStaticMethod() {
|
||||
System.out.println("InternalNonPublicClass.testPrivateStaticMethod()");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.reflected.internal;
|
||||
|
||||
public class InternalPublicClass {
|
||||
public static void testPublicStaticMethod() {
|
||||
System.out.println("InternalPublicClass.testPublicStaticMethod()");
|
||||
}
|
||||
|
||||
private static void testPrivateStaticMethod() {
|
||||
System.out.println("InternalPublicClass.testPrivateStaticMethod()");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.reflected.opened;
|
||||
|
||||
class OpenedNonPublicClass {
|
||||
public static void testPublicStaticMethod() {
|
||||
System.out.println("OpenedNonPublicClass.testPublicStaticMethod()");
|
||||
}
|
||||
|
||||
private static void testPrivateStaticMethod() {
|
||||
System.out.println("OpenedNonPublicClass.testPrivateStaticMethod()");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.reflected.opened;
|
||||
|
||||
public class OpenedPublicClass {
|
||||
public static void testPublicStaticMethod() {
|
||||
System.out.println("OpenedPublicClass.testPublicStaticMethod()");
|
||||
}
|
||||
|
||||
private static void testPrivateStaticMethod() {
|
||||
System.out.println("OpenedPublicClass.testPrivateStaticMethod()");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
module baeldung.reflected {
|
||||
exports com.baeldung.reflected.exported;
|
||||
opens com.baeldung.reflected.opened;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.baeldung.reflecting.named;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws Exception {
|
||||
Class<?> clazz = Class.forName("com.baeldung.reflected.internal.InternalNonPublicClass");
|
||||
Method method = clazz.getDeclaredMethod("testPrivateStaticMethod");
|
||||
method.setAccessible(true);
|
||||
method.invoke(null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.baeldung.reflecting.named;
|
||||
|
||||
import com.baeldung.intermedium.ForwardOpen;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class MainWithForwardOpen {
|
||||
public static void main(String[] args) throws Exception {
|
||||
Class<?> currentClass = Main.class;
|
||||
Class<?> clazz = Class.forName("com.baeldung.reflected.internal.InternalNonPublicClass");
|
||||
|
||||
ForwardOpen.addOpens(clazz, currentClass);
|
||||
|
||||
Method method = clazz.getDeclaredMethod("testPrivateStaticMethod");
|
||||
method.setAccessible(true);
|
||||
method.invoke(null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
module baeldung.reflecting.named {
|
||||
requires baeldung.intermedium;
|
||||
requires baeldung.reflected;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.reflecting.unnamed;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws Exception {
|
||||
Class<?> clazz = StringBuilder.class;
|
||||
Field f = clazz.getDeclaredField("serialVersionUID");
|
||||
f.setAccessible(true);
|
||||
Object value = f.get(null);
|
||||
System.out.println(value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package test.java.com.baeldung.list.listOfHashMaps;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ListOfHashMapsUnitTest {
|
||||
List<HashMap<String, List<String>>> booksAuthorsMapsList = new ArrayList<>();
|
||||
|
||||
@Test
|
||||
public void givenMaps_whenAddToList_thenListContainsMaps() {
|
||||
HashMap<String, List<String>> javaBooksAuthorsMap = new HashMap<>();
|
||||
HashMap<String, List<String>> phpBooksAuthorsMap = new HashMap<>();
|
||||
javaBooksAuthorsMap.put("Head First Java", Arrays.asList("Kathy Sierra", "Bert Bates"));
|
||||
javaBooksAuthorsMap.put("Effective Java", Arrays.asList("Joshua Bloch"));
|
||||
javaBooksAuthorsMap.put("OCA Java SE 8",
|
||||
Arrays.asList("Kathy Sierra", "Bert Bates", "Elisabeth Robson"));
|
||||
phpBooksAuthorsMap.put("The Joy of PHP", Arrays.asList("Alan Forbes"));
|
||||
phpBooksAuthorsMap.put("Head First PHP & MySQL",
|
||||
Arrays.asList("Lynn Beighley", "Michael Morrison"));
|
||||
|
||||
booksAuthorsMapsList.add(javaBooksAuthorsMap);
|
||||
booksAuthorsMapsList.add(phpBooksAuthorsMap);
|
||||
|
||||
assertTrue(booksAuthorsMapsList.get(0).keySet().containsAll
|
||||
(javaBooksAuthorsMap.keySet().stream().collect(Collectors.toList())));
|
||||
assertTrue(booksAuthorsMapsList.get(1).keySet().containsAll
|
||||
(phpBooksAuthorsMap.keySet().stream().collect(Collectors.toList())));
|
||||
}
|
||||
}
|
|
@ -12,3 +12,4 @@ This module contains articles about the Java Set collection
|
|||
- [Set Operations in Java](https://www.baeldung.com/java-set-operations)
|
||||
- [Copying Sets in Java](https://www.baeldung.com/java-copy-sets)
|
||||
- [Immutable Set in Java](https://www.baeldung.com/java-immutable-set)
|
||||
- [Find the Difference Between Two Sets](https://www.baeldung.com/java-difference-between-sets)
|
||||
|
|
|
@ -11,4 +11,5 @@ This module contains articles about date operations in Java.
|
|||
- [How to determine day of week by passing specific date in Java?](https://www.baeldung.com/java-get-day-of-week)
|
||||
- [Finding Leap Years in Java](https://www.baeldung.com/java-leap-year)
|
||||
- [Getting the Week Number From Any Date](https://www.baeldung.com/java-get-week-number)
|
||||
- [Subtract Days from a Date in Java](https://www.baeldung.com/java-subtract-days-from-date)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-date-operations-1)
|
||||
|
|
|
@ -12,3 +12,4 @@ This module contains articles about parsing and formatting Java date and time ob
|
|||
- [Convert between String and Timestamp](https://www.baeldung.com/java-string-to-timestamp)
|
||||
- [Convert String to Date in Java](http://www.baeldung.com/java-string-to-date)
|
||||
- [Format a Milliseconds Duration to HH:MM:SS](https://www.baeldung.com/java-ms-to-hhmmss)
|
||||
- [Format Instant to String in Java](https://www.baeldung.com/java-instant-to-string)
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package com.baeldung.formatinstant;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.UnsupportedTemporalTypeException;
|
||||
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class FormatInstantUnitTest {
|
||||
|
||||
private static final String PATTERN_FORMAT = "dd.MM.yyyy";
|
||||
|
||||
@Test
|
||||
public void givenInstant_whenUsingDateTimeFormatter_thenFormat() {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN_FORMAT)
|
||||
.withZone(ZoneId.systemDefault());
|
||||
|
||||
Instant instant = Instant.parse("2022-02-15T18:35:24.00Z");
|
||||
String formattedInstant = formatter.format(instant);
|
||||
|
||||
assertThat(formattedInstant).isEqualTo("15.02.2022");
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedTemporalTypeException.class)
|
||||
public void givenInstant_whenNotSpecifyingTimeZone_thenThrowException() {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN_FORMAT);
|
||||
|
||||
Instant instant = Instant.now();
|
||||
formatter.format(instant);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInstant_whenUsingToString_thenFormat() {
|
||||
Instant instant = Instant.ofEpochMilli(1641828224000L);
|
||||
String formattedInstant = instant.toString();
|
||||
|
||||
assertThat(formattedInstant).isEqualTo("2022-01-10T15:23:44Z");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInstant_whenUsingJodaTime_thenFormat() {
|
||||
org.joda.time.Instant instant = new org.joda.time.Instant("2022-03-20T10:11:12");
|
||||
|
||||
String formattedInstant = DateTimeFormat.forPattern(PATTERN_FORMAT)
|
||||
.print(instant);
|
||||
|
||||
assertThat(formattedInstant).isEqualTo("20.03.2022");
|
||||
}
|
||||
|
||||
}
|
|
@ -8,4 +8,5 @@ This module contains articles about core Java input and output (IO)
|
|||
- [Simulate touch Command in Java](https://www.baeldung.com/java-simulate-touch-command)
|
||||
- [SequenceInputStream Class in Java](https://www.baeldung.com/java-sequenceinputstream)
|
||||
- [Read a File Into a Map in Java](https://www.baeldung.com/java-read-file-into-map)
|
||||
- [Read User Input Until a Condition is Met](https://www.baeldung.com/java-read-input-until-condition)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-io-3)
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package com.baeldung.implementsvsextends;
|
||||
|
||||
import com.baeldung.implementsvsextends.media.model.AudioMedia;
|
||||
import com.baeldung.implementsvsextends.media.model.Media;
|
||||
import com.baeldung.implementsvsextends.media.model.VideoMedia;
|
||||
import com.baeldung.implementsvsextends.media.player.impl.AudioMediaPlayer;
|
||||
import com.baeldung.implementsvsextends.media.player.impl.CustomMediaPlayer;
|
||||
import com.baeldung.implementsvsextends.media.player.impl.MultiMediaPlayer;
|
||||
import com.baeldung.implementsvsextends.media.player.impl.VideoMediaPlayer;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
Media media = new Media();
|
||||
media.setId(001);
|
||||
media.setTitle("Media1");
|
||||
media.setArtist("Artist001");
|
||||
|
||||
AudioMedia audioMedia = new AudioMedia();
|
||||
audioMedia.setId(101);
|
||||
audioMedia.setTitle("Audio1");
|
||||
audioMedia.setArtist("Artist101");
|
||||
audioMedia.setBitrate(3500);
|
||||
audioMedia.setFrequency("256kbps");
|
||||
|
||||
VideoMedia videoMedia = new VideoMedia();
|
||||
videoMedia.setId(201);
|
||||
videoMedia.setTitle("Video1");
|
||||
videoMedia.setArtist("Artist201");
|
||||
videoMedia.setResolution("1024x768");
|
||||
videoMedia.setAspectRatio("16:9");
|
||||
|
||||
System.out.println(media);
|
||||
System.out.println(audioMedia);
|
||||
System.out.println(videoMedia);
|
||||
|
||||
AudioMediaPlayer audioMediaPlayer = new AudioMediaPlayer();
|
||||
audioMediaPlayer.play();
|
||||
audioMediaPlayer.pause();
|
||||
|
||||
VideoMediaPlayer videoMediaPlayer = new VideoMediaPlayer();
|
||||
videoMediaPlayer.play();
|
||||
videoMediaPlayer.pause();
|
||||
|
||||
MultiMediaPlayer multiMediaPlayer = new MultiMediaPlayer();
|
||||
multiMediaPlayer.play();
|
||||
multiMediaPlayer.pause();
|
||||
multiMediaPlayer.seek();
|
||||
multiMediaPlayer.fastForward();
|
||||
|
||||
CustomMediaPlayer customMediaPlayer = new CustomMediaPlayer();
|
||||
customMediaPlayer.play();
|
||||
customMediaPlayer.pause();
|
||||
customMediaPlayer.setId(301);
|
||||
customMediaPlayer.setTitle("Custom1");
|
||||
customMediaPlayer.setArtist("Artist301");
|
||||
System.out.println(customMediaPlayer);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.baeldung.implementsvsextends.media.model;
|
||||
|
||||
public class AudioMedia extends Media {
|
||||
|
||||
private int bitrate;
|
||||
|
||||
private String frequency;
|
||||
|
||||
@Override
|
||||
public void printTitle() {
|
||||
System.out.println("AudioMedia Title");
|
||||
}
|
||||
|
||||
public int getBitrate() {
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
public void setBitrate(int bitrate) {
|
||||
this.bitrate = bitrate;
|
||||
}
|
||||
|
||||
public String getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public void setFrequency(String frequency) {
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AudioMedia{" +
|
||||
"id=" + this.getId() +
|
||||
", title='" + this.getTitle() + '\'' +
|
||||
", artist='" + this.getArtist() + '\'' +
|
||||
", bitrate=" + bitrate +
|
||||
", frequency='" + frequency + '\'' +
|
||||
"} ";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.baeldung.implementsvsextends.media.model;
|
||||
|
||||
public class Media {
|
||||
|
||||
private int id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String artist;
|
||||
|
||||
public void printTitle() {
|
||||
System.out.println("Media Title");
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getArtist() {
|
||||
return artist;
|
||||
}
|
||||
|
||||
public void setArtist(String artist) {
|
||||
this.artist = artist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Media{" +
|
||||
"id=" + id +
|
||||
", title='" + title + '\'' +
|
||||
", artist='" + artist + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.baeldung.implementsvsextends.media.model;
|
||||
|
||||
public class VideoMedia extends Media {
|
||||
|
||||
private String resolution;
|
||||
|
||||
private String aspectRatio;
|
||||
|
||||
public String getResolution() {
|
||||
return resolution;
|
||||
}
|
||||
|
||||
public void setResolution(String resolution) {
|
||||
this.resolution = resolution;
|
||||
}
|
||||
|
||||
public String getAspectRatio() {
|
||||
return aspectRatio;
|
||||
}
|
||||
|
||||
public void setAspectRatio(String aspectRatio) {
|
||||
this.aspectRatio = aspectRatio;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VideoMedia{" +
|
||||
"id=" + this.getId() +
|
||||
", title='" + this.getTitle() + '\'' +
|
||||
", artist='" + this.getArtist() + '\'' +
|
||||
"resolution='" + resolution + '\'' +
|
||||
", aspectRatio='" + aspectRatio + '\'' +
|
||||
"} ";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.baeldung.implementsvsextends.media.player;
|
||||
|
||||
public interface AdvancedPlayerOptions {
|
||||
|
||||
void seek();
|
||||
|
||||
void fastForward();
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.baeldung.implementsvsextends.media.player;
|
||||
|
||||
public interface MediaPlayer {
|
||||
|
||||
void play();
|
||||
|
||||
void pause();
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.baeldung.implementsvsextends.media.player.impl;
|
||||
|
||||
import com.baeldung.implementsvsextends.media.player.MediaPlayer;
|
||||
|
||||
public class AudioMediaPlayer implements MediaPlayer {
|
||||
|
||||
@Override
|
||||
public void play() {
|
||||
System.out.println("AudioMediaPlayer is Playing");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
System.out.println("AudioMediaPlayer is Paused");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung.implementsvsextends.media.player.impl;
|
||||
|
||||
import com.baeldung.implementsvsextends.media.model.Media;
|
||||
import com.baeldung.implementsvsextends.media.player.MediaPlayer;
|
||||
|
||||
public class CustomMediaPlayer extends Media implements MediaPlayer {
|
||||
|
||||
@Override
|
||||
public void play() {
|
||||
System.out.println("CustomMediaPlayer is Playing");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
System.out.println("CustomMediaPlayer is Paused");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.baeldung.implementsvsextends.media.player.impl;
|
||||
|
||||
import com.baeldung.implementsvsextends.media.player.AdvancedPlayerOptions;
|
||||
import com.baeldung.implementsvsextends.media.player.MediaPlayer;
|
||||
|
||||
public class MultiMediaPlayer implements MediaPlayer, AdvancedPlayerOptions {
|
||||
|
||||
@Override
|
||||
public void play() {
|
||||
System.out.println("MultiMediaPlayer is Playing");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
System.out.println("MultiMediaPlayer is Paused");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seek() {
|
||||
System.out.println("MultiMediaPlayer is being seeked");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastForward() {
|
||||
System.out.println("MultiMediaPlayer is being fast forwarded");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.baeldung.implementsvsextends.media.player.impl;
|
||||
|
||||
import com.baeldung.implementsvsextends.media.player.MediaPlayer;
|
||||
|
||||
public class VideoMediaPlayer implements MediaPlayer {
|
||||
|
||||
@Override
|
||||
public void play() {
|
||||
System.out.println("VideoMediaPlayer is Playing");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
System.out.println("VideoMediaPlayer is Paused");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.implementsvsextends.media.model;
|
||||
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AudioMediaUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenAudioMediaInstance_whenCheckedType_thenIsInstanceOfMedia() {
|
||||
AudioMedia audioMedia = new AudioMedia();
|
||||
Assert.assertThat(audioMedia, CoreMatchers.<AudioMedia>instanceOf(Media.class));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.implementsvsextends.media.model;
|
||||
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class VideoMediaUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenVideoMediaInstance_whenCheckedType_thenIsInstanceOfMedia() {
|
||||
VideoMedia videoMedia = new VideoMedia();
|
||||
Assert.assertThat(videoMedia, CoreMatchers.<VideoMedia>instanceOf(Media.class));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.baeldung.implementsvsextends.media.player.impl;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class AudioMediaPlayerUnitTest {
|
||||
|
||||
private final PrintStream standardOut = System.out;
|
||||
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
System.setOut(new PrintStream(outputStreamCaptor));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
System.setOut(standardOut);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAudioMediaPlayer_whenPlay_thenPrintsPlayingString() {
|
||||
AudioMediaPlayer audioMediaPlayer = new AudioMediaPlayer();
|
||||
audioMediaPlayer.play();
|
||||
Assert.assertEquals("AudioMediaPlayer is Playing", outputStreamCaptor.toString()
|
||||
.trim());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAudioMediaPlayer_whenPause_thenPrintsPausedString() {
|
||||
AudioMediaPlayer audioMediaPlayer = new AudioMediaPlayer();
|
||||
audioMediaPlayer.pause();
|
||||
Assert.assertEquals("AudioMediaPlayer is Paused", outputStreamCaptor.toString()
|
||||
.trim());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package com.baeldung.implementsvsextends.media.player.impl;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class MultiMediaPlayerUnitTest {
|
||||
|
||||
private final PrintStream standardOut = System.out;
|
||||
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
System.setOut(new PrintStream(outputStreamCaptor));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
System.setOut(standardOut);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMultiMediaPlayer_whenPlay_thenPrintsPlayingString() {
|
||||
MultiMediaPlayer multiMediaPlayer = new MultiMediaPlayer();
|
||||
multiMediaPlayer.play();
|
||||
Assert.assertEquals("MultiMediaPlayer is Playing", outputStreamCaptor.toString()
|
||||
.trim());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMultiMediaPlayer_whenPause_thenPrintsPausedString() {
|
||||
MultiMediaPlayer multiMediaPlayer = new MultiMediaPlayer();
|
||||
multiMediaPlayer.pause();
|
||||
Assert.assertEquals("MultiMediaPlayer is Paused", outputStreamCaptor.toString()
|
||||
.trim());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMultiMediaPlayer_whenSeek_thenPrintsPausedString() {
|
||||
MultiMediaPlayer multiMediaPlayer = new MultiMediaPlayer();
|
||||
multiMediaPlayer.seek();
|
||||
Assert.assertEquals("MultiMediaPlayer is being seeked", outputStreamCaptor.toString()
|
||||
.trim());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMultiMediaPlayer_whenFastForward_thenPrintsPausedString() {
|
||||
MultiMediaPlayer multiMediaPlayer = new MultiMediaPlayer();
|
||||
multiMediaPlayer.fastForward();
|
||||
Assert.assertEquals("MultiMediaPlayer is being fast forwarded",
|
||||
outputStreamCaptor.toString()
|
||||
.trim());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.baeldung.implementsvsextends.media.player.impl;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class VideoMediaPlayerUnitTest {
|
||||
|
||||
private final PrintStream standardOut = System.out;
|
||||
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
System.setOut(new PrintStream(outputStreamCaptor));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
System.setOut(standardOut);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenVideoMediaPlayer_whenPlay_thenPrintsPlayingString() {
|
||||
VideoMediaPlayer videoMediaPlayer = new VideoMediaPlayer();
|
||||
videoMediaPlayer.play();
|
||||
Assert.assertEquals("VideoMediaPlayer is Playing", outputStreamCaptor.toString()
|
||||
.trim());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenVideoMediaPlayer_whenPause_thenPrintsPausedString() {
|
||||
VideoMediaPlayer videoMediaPlayer = new VideoMediaPlayer();
|
||||
videoMediaPlayer.pause();
|
||||
Assert.assertEquals("VideoMediaPlayer is Paused", outputStreamCaptor.toString()
|
||||
.trim());
|
||||
}
|
||||
}
|
|
@ -13,4 +13,5 @@ This module contains articles about Java syntax
|
|||
- [Introduction to Basic Syntax in Java](https://www.baeldung.com/java-syntax)
|
||||
- [Java ‘protected’ Access Modifier](https://www.baeldung.com/java-protected-access-modifier)
|
||||
- [Using the Not Operator in If Conditions in Java](https://www.baeldung.com/java-using-not-in-if-conditions)
|
||||
- [The for-each Loop in Java](https://www.baeldung.com/java-for-each-loop)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-lang-syntax)
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package regex.array;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.*;
|
||||
|
||||
class RegexMatches {
|
||||
|
||||
String[] regexMatch(String strSearch)
|
||||
{
|
||||
List<String> matchesList = new ArrayList<String>();
|
||||
String stringToSearch = strSearch;
|
||||
Pattern p1 = Pattern.compile("780{1}\\d{7}");
|
||||
Matcher m1 = p1.matcher(stringToSearch);
|
||||
while (m1.find())
|
||||
{
|
||||
matchesList.add(m1.group());
|
||||
}
|
||||
int sizeOfNewArray = matchesList.size();
|
||||
String newArrayOfMatches[] = new String[sizeOfNewArray];
|
||||
matchesList.toArray(newArrayOfMatches);
|
||||
return newArrayOfMatches;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package regex.array;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import regex.array.RegexMatches;
|
||||
|
||||
class RegexMatchesUnitTest {
|
||||
|
||||
@Test
|
||||
void whenFourNums_thenFourMatches() {
|
||||
RegexMatches rm = new RegexMatches();
|
||||
String actual[] = rm.regexMatch("7801111211fsdafasdfa 7802222222 sadfsadfsda7803333333 sadfdasfasd 7804444444");
|
||||
|
||||
assertArrayEquals(new String[] {"7801111211", "7802222222", "7803333333", "7804444444"}, actual, "success");
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenThreeNums_thenThreeMatches() {
|
||||
RegexMatches rm = new RegexMatches();
|
||||
String actual[] = rm.regexMatch("7801111211fsdafasdfa 780222222 sadfsadfsda7803333333 sadfdasfasd 7804444444");
|
||||
|
||||
assertArrayEquals(new String[] {"7801111211", "7803333333", "7804444444"}, actual, "success");
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenZeroNums_thenZeroMatches() {
|
||||
RegexMatches rm = new RegexMatches();
|
||||
String actual[] = rm.regexMatch("78011111fsdafasdfa 780222222 sadfsadfsda78033333 sadfdasfasd 7804444");
|
||||
|
||||
assertArrayEquals(new String[] {}, actual, "success");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
### Relevant Articles:
|
||||
- [Send a SOAP Object with Feign Client](https://www.baeldung.com/java-feign-send-soap)
|
|
@ -12,7 +12,7 @@
|
|||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../</relativePath>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<repositories>
|
||||
|
@ -36,51 +36,15 @@
|
|||
<artifactId>graphql-java-annotations</artifactId>
|
||||
<version>${graphql-java-annotations.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ratpack</groupId>
|
||||
<artifactId>ratpack-core</artifactId>
|
||||
<version>${ratpack-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.americanexpress.nodes</groupId>
|
||||
<artifactId>nodes</artifactId>
|
||||
<version>0.5.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.graphql-java</groupId>
|
||||
<artifactId>graphql-java</artifactId>
|
||||
<version>9.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.graphql-java</groupId>
|
||||
<artifactId>graphql-java-tools</artifactId>
|
||||
<version>5.2.4</version>
|
||||
<version>${graphql-java-tools.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.graphql-java</groupId>
|
||||
<artifactId>graphql-java-servlet</artifactId>
|
||||
<version>6.1.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.12.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-netty</artifactId>
|
||||
<version>5.11.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-client-java</artifactId>
|
||||
<version>5.11.2</version>
|
||||
<version>${graphql-java-servlet.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.graphql-java-generator</groupId>
|
||||
|
@ -88,15 +52,47 @@
|
|||
<version>${graphql.java.generator.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.8.2</version>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>${javax.servlet-api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ratpack</groupId>
|
||||
<artifactId>ratpack-core</artifactId>
|
||||
<version>${ratpack-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.americanexpress.nodes</groupId>
|
||||
<artifactId>nodes</artifactId>
|
||||
<version>${nodes.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>${httpclient.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-netty</artifactId>
|
||||
<version>${mockserver-netty.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>3.22.0</version>
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-client-java</artifactId>
|
||||
<version>${mockserver-client-java.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -115,11 +111,11 @@
|
|||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>10.0.7</version>
|
||||
<version>${jetty-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.graphql-java-generator</groupId>
|
||||
|
@ -143,12 +139,21 @@
|
|||
</build>
|
||||
|
||||
<properties>
|
||||
<graphql-java-tools.version>5.2.4</graphql-java-tools.version>
|
||||
<graphql-java-servlet.version>6.1.3</graphql-java-servlet.version>
|
||||
<graphql-java-annotations.version>3.0.3</graphql-java-annotations.version>
|
||||
<ratpack-core.version>1.4.6</ratpack-core.version>
|
||||
<maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>
|
||||
<graphql.java.generator.version>1.18</graphql.java.generator.version>
|
||||
<ratpack-core.version>1.9.0</ratpack-core.version>
|
||||
<nodes.version>0.5.0</nodes.version>
|
||||
<httpclient.version>4.5.13</httpclient.version>
|
||||
|
||||
<mockserver-netty.version>5.13.2</mockserver-netty.version>
|
||||
<mockserver-client-java.version>5.13.2</mockserver-client-java.version>
|
||||
|
||||
<jetty-maven-plugin.version>10.0.7</jetty-maven-plugin.version>
|
||||
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<graphql.java.generator.version>1.18</graphql.java.generator.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -19,24 +19,27 @@ import com.baeldung.graphql.utils.SchemaUtils;
|
|||
import static ratpack.jackson.Jackson.json;
|
||||
|
||||
public class UserHandler implements Handler {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(UserHandler.class.getSimpleName());
|
||||
private GraphQL graphql;
|
||||
private static List<User> users = new ArrayList<>();
|
||||
|
||||
private static final List<User> USERS = new ArrayList<>();
|
||||
|
||||
private final GraphQL graphql;
|
||||
|
||||
public UserHandler() throws Exception {
|
||||
graphql = new GraphQL(new UserSchema().getSchema());
|
||||
graphql = GraphQL.newGraphQL(new UserSchema().getSchema()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Context context) throws Exception {
|
||||
public void handle(Context context) {
|
||||
context.parse(Map.class)
|
||||
.then(payload -> {
|
||||
Map<String, Object> parameters = (Map<String, Object>) payload.get("parameters");
|
||||
ExecutionResult executionResult = graphql.execute(payload.get(SchemaUtils.QUERY)
|
||||
.toString(), null, this, parameters);
|
||||
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
if (executionResult.getErrors()
|
||||
.isEmpty()) {
|
||||
if (executionResult.getErrors().isEmpty()) {
|
||||
result.put(SchemaUtils.DATA, executionResult.getData());
|
||||
} else {
|
||||
result.put(SchemaUtils.ERRORS, executionResult.getErrors());
|
||||
|
@ -46,8 +49,8 @@ public class UserHandler implements Handler {
|
|||
});
|
||||
}
|
||||
|
||||
public static List<User> getUsers() {
|
||||
return users;
|
||||
public List<User> getUsers() {
|
||||
return USERS;
|
||||
}
|
||||
|
||||
public static List<User> getUsers(DataFetchingEnvironment env) {
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
### Relevant Articles:
|
||||
|
||||
- [Getting Started With GraphQL SPQR and Spring Boot](https://www.baeldung.com/spring-boot-graphql-spqr)
|
|
@ -12,4 +12,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
|||
- [Reading an HTTP Response Body as a String in Java](https://www.baeldung.com/java-http-response-body-as-string)
|
||||
- [How To Get Cookies From the Apache HttpClient Response](https://www.baeldung.com/java-apache-httpclient-cookies)
|
||||
- [Enabling Logging for Apache HttpClient](https://www.baeldung.com/apache-httpclient-enable-logging)
|
||||
- [Expand Shortened URLs with Apache HttpClient](https://www.baeldung.com/apache-httpclient-expand-url)
|
||||
- [Apache HttpClient vs. CloseableHttpClient](https://www.baeldung.com/apache-httpclient-vs-closeablehttpclient)
|
||||
- More articles: [[<-- prev]](../httpclient)
|
||||
|
|
|
@ -15,6 +15,11 @@
|
|||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<!-- http client -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
|
@ -50,6 +55,22 @@
|
|||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-netty</artifactId>
|
||||
<version>${mockserver.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mock-server</groupId>
|
||||
<artifactId>mockserver-client-java</artifactId>
|
||||
<version>${mockserver.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -74,8 +95,10 @@
|
|||
</build>
|
||||
|
||||
<properties>
|
||||
<assertj.version>3.22.0</assertj.version>
|
||||
<mockserver.version>5.11.2</mockserver.version>
|
||||
<httpclient.version>4.5.8</httpclient.version>
|
||||
<httpclient5.version>5.1</httpclient5.version>
|
||||
<httpclient5.version>5.1.3</httpclient5.version>
|
||||
<maven.compiler.source.version>11</maven.compiler.source.version>
|
||||
<maven.compiler.target.version>11</maven.compiler.target.version>
|
||||
<spring-boot.version>2.1.7.RELEASE</spring-boot.version>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.httpclient.rare;
|
||||
package com.baeldung.httpclient.expandurl;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -22,35 +22,29 @@ import java.util.List;
|
|||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class HttpClientUnshortenLiveTest {
|
||||
public class HttpClientExpandUrlLiveTest {
|
||||
|
||||
private CloseableHttpClient client;
|
||||
|
||||
// fixtures
|
||||
|
||||
@Before
|
||||
public final void before() {
|
||||
client = HttpClientBuilder.create().disableRedirectHandling().build();
|
||||
}
|
||||
|
||||
// tests
|
||||
|
||||
@Test
|
||||
public final void givenShortenedOnce_whenUrlIsUnshortened_thenCorrectResult() throws IOException {
|
||||
final String expectedResult = "http://www.baeldung.com/rest-versioning";
|
||||
final String actualResult = expandSingleLevel("http://bit.ly/13jEoS1");
|
||||
public final void givenShortenedOnce_whenUrlIsExpanded_thenCorrectResult() throws IOException {
|
||||
final String expectedResult = "https://www.baeldung.com/rest-versioning";
|
||||
final String actualResult = expandSingleLevel("http://bit.ly/3LScTri");
|
||||
assertThat(actualResult, equalTo(expectedResult));
|
||||
}
|
||||
|
||||
@Test
|
||||
public final void givenShortenedMultiple_whenUrlIsUnshortened_thenCorrectResult() throws IOException {
|
||||
final String expectedResult = "http://www.baeldung.com/rest-versioning";
|
||||
public final void givenShortenedMultiple_whenUrlIsExpanded_thenCorrectResult() throws IOException {
|
||||
final String expectedResult = "https://www.baeldung.com/rest-versioning";
|
||||
final String actualResult = expand("http://t.co/e4rDDbnzmk");
|
||||
assertThat(actualResult, equalTo(expectedResult));
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
private String expand(final String urlArg) throws IOException {
|
||||
String originalUrl = urlArg;
|
||||
String newUrl = expandSingleLevel(originalUrl);
|
|
@ -0,0 +1,78 @@
|
|||
package com.baeldung.httpclient.httpclient;
|
||||
|
||||
import org.apache.hc.client5.http.classic.HttpClient;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||
import org.apache.hc.core5.http.HttpEntity;
|
||||
import org.apache.hc.core5.http.HttpResponse;
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class ApacheHttpClientUnitTest extends GetRequestMockServer {
|
||||
|
||||
@Test
|
||||
void givenDeveloperUsedHttpClient_whenExecutingGetRequest_thenStatusIsOkButSonarReportsAnIssue() throws IOException {
|
||||
HttpClient httpClient = HttpClients.createDefault();
|
||||
HttpGet httpGet = new HttpGet(serviceOneUrl);
|
||||
HttpResponse response = httpClient.execute(httpGet);
|
||||
assertThat(response.getCode()).isEqualTo(HttpStatus.SC_OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenDeveloperUsedCloseableHttpClient_whenExecutingGetRequest_thenStatusIsOk() throws IOException {
|
||||
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
|
||||
HttpGet httpGet = new HttpGet(serviceOneUrl);
|
||||
HttpResponse response = httpClient.execute(httpGet);
|
||||
assertThat(response.getCode()).isEqualTo(HttpStatus.SC_OK);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenDeveloperUsedHttpClientBuilder_whenExecutingGetRequest_thenStatusIsOk() throws IOException {
|
||||
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
|
||||
HttpGet httpGet = new HttpGet(serviceOneUrl);
|
||||
HttpResponse response = httpClient.execute(httpGet);
|
||||
assertThat(response.getCode()).isEqualTo(HttpStatus.SC_OK);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenDeveloperUsedCloseableHttpResponse_whenExecutingGetRequest_thenStatusIsOk() throws IOException {
|
||||
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
|
||||
HttpGet httpGet = new HttpGet(serviceOneUrl);
|
||||
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
|
||||
HttpEntity entity = response.getEntity();
|
||||
EntityUtils.consume(entity);
|
||||
assertThat(response.getCode()).isEqualTo(HttpStatus.SC_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenDeveloperUsedSingleClient_whenExecutingTwoGetRequest_thenStatusIsOk() throws IOException {
|
||||
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
|
||||
HttpGet httpGetOne = new HttpGet(serviceOneUrl);
|
||||
try (CloseableHttpResponse responseOne = httpClient.execute(httpGetOne)) {
|
||||
HttpEntity entityOne = responseOne.getEntity();
|
||||
EntityUtils.consume(entityOne);
|
||||
assertThat(responseOne.getCode()).isEqualTo(HttpStatus.SC_OK);
|
||||
}
|
||||
|
||||
HttpGet httpGetTwo = new HttpGet(serviceTwoUrl);
|
||||
try (CloseableHttpResponse responseTwo = httpClient.execute(httpGetTwo)) {
|
||||
HttpEntity entityTwo = responseTwo.getEntity();
|
||||
EntityUtils.consume(entityTwo);
|
||||
assertThat(responseTwo.getCode()).isEqualTo(HttpStatus.SC_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package com.baeldung.httpclient.httpclient;
|
||||
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.mockserver.client.MockServerClient;
|
||||
import org.mockserver.integration.ClientAndServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import static org.mockserver.integration.ClientAndServer.startClientAndServer;
|
||||
import static org.mockserver.matchers.Times.exactly;
|
||||
import static org.mockserver.model.HttpRequest.request;
|
||||
import static org.mockserver.model.HttpResponse.response;
|
||||
|
||||
public class GetRequestMockServer {
|
||||
|
||||
public static ClientAndServer mockServer;
|
||||
public static String serviceOneUrl;
|
||||
public static String serviceTwoUrl;
|
||||
|
||||
private static int serverPort;
|
||||
|
||||
public static final String SERVER_ADDRESS = "127.0.0.1";
|
||||
public static final String PATH_ONE = "/test1";
|
||||
public static final String PATH_TWO = "/test2";
|
||||
public static final String METHOD = "GET";
|
||||
|
||||
@BeforeAll
|
||||
static void startServer() throws IOException, URISyntaxException {
|
||||
serverPort = getFreePort();
|
||||
serviceOneUrl = "http://" + SERVER_ADDRESS + ":" + serverPort + PATH_ONE;
|
||||
serviceTwoUrl = "http://" + SERVER_ADDRESS + ":" + serverPort + PATH_TWO;
|
||||
mockServer = startClientAndServer(serverPort);
|
||||
mockGetRequest();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void stopServer() {
|
||||
mockServer.stop();
|
||||
}
|
||||
|
||||
private static void mockGetRequest() {
|
||||
new MockServerClient(SERVER_ADDRESS, serverPort)
|
||||
.when(
|
||||
request()
|
||||
.withPath(PATH_ONE)
|
||||
.withMethod(METHOD),
|
||||
exactly(5)
|
||||
)
|
||||
.respond(
|
||||
response()
|
||||
.withStatusCode(HttpStatus.SC_OK)
|
||||
.withBody("{\"status\":\"ok\"}")
|
||||
);
|
||||
new MockServerClient(SERVER_ADDRESS, serverPort)
|
||||
.when(
|
||||
request()
|
||||
.withPath(PATH_TWO)
|
||||
.withMethod(METHOD),
|
||||
exactly(1)
|
||||
)
|
||||
.respond(
|
||||
response()
|
||||
.withStatusCode(HttpStatus.SC_OK)
|
||||
.withBody("{\"status\":\"ok\"}")
|
||||
);
|
||||
}
|
||||
|
||||
private static int getFreePort () throws IOException {
|
||||
try (ServerSocket serverSocket = new ServerSocket(0)) {
|
||||
return serverSocket.getLocalPort();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -4,14 +4,14 @@ This module contains articles about HTTPClient that are part of the HTTPClient E
|
|||
|
||||
### Relevant Articles
|
||||
|
||||
- [HttpClient 4 – Get the Status Code](https://www.baeldung.com/httpclient-status-code)
|
||||
- [HttpClient with SSL](https://www.baeldung.com/httpclient-ssl)
|
||||
- [HttpClient Timeout](https://www.baeldung.com/httpclient-timeout)
|
||||
- [HttpClient 4 – Send Custom Cookie](https://www.baeldung.com/httpclient-4-cookies)
|
||||
- [Custom HTTP Header with the HttpClient](https://www.baeldung.com/httpclient-custom-http-header)
|
||||
- [HttpClient Basic Authentication](https://www.baeldung.com/httpclient-4-basic-authentication)
|
||||
- [Posting with HttpClient](https://www.baeldung.com/httpclient-post-http-request)
|
||||
- [Adding Parameters to HttpClient Requests](https://www.baeldung.com/apache-httpclient-parameters)
|
||||
- [Apache HttpClient – Get the Status Code](https://www.baeldung.com/httpclient-status-code)
|
||||
- [Apache HttpClient with SSL](https://www.baeldung.com/httpclient-ssl)
|
||||
- [Apache HttpClient Timeout](https://www.baeldung.com/httpclient-timeout)
|
||||
- [Apache HttpClient – Send Custom Cookie](https://www.baeldung.com/httpclient-cookies)
|
||||
- [Custom HTTP Header with the Apache HttpClient](https://www.baeldung.com/httpclient-custom-http-header)
|
||||
- [Apache HttpClient Basic Authentication](https://www.baeldung.com/httpclient-basic-authentication)
|
||||
- [Posting with Apache HttpClient](https://www.baeldung.com/httpclient-post-http-request)
|
||||
- [Adding Parameters to Apache HttpClient Requests](https://www.baeldung.com/apache-httpclient-parameters)
|
||||
|
||||
|
||||
### Running the Tests
|
||||
|
|
|
@ -7,16 +7,14 @@ This module contains articles about HttpClient 4.x
|
|||
The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- [HttpClient 4 – Cancel Request](https://www.baeldung.com/httpclient-cancel-request)
|
||||
- [HttpClient 4 Cookbook](https://www.baeldung.com/httpclient4)
|
||||
- [Unshorten URLs with HttpClient](https://www.baeldung.com/unshorten-url-httpclient)
|
||||
- [HttpClient 4 – Follow Redirects for POST](https://www.baeldung.com/httpclient-redirect-on-http-post)
|
||||
- [Multipart Upload with HttpClient 4](https://www.baeldung.com/httpclient-multipart-upload)
|
||||
- [HttpAsyncClient Tutorial](https://www.baeldung.com/httpasyncclient-tutorial)
|
||||
- [HttpClient 4 Tutorial](https://www.baeldung.com/httpclient-guide)
|
||||
- [Apache HttpClient – Cancel Request](https://www.baeldung.com/httpclient-cancel-request)
|
||||
- [Apache HttpClient 4 Cookbook](https://www.baeldung.com/httpclient4)
|
||||
- [Apache HttpClient – Follow Redirects for POST](https://www.baeldung.com/httpclient-redirect-on-http-post)
|
||||
- [Multipart Upload with Apache HttpClient](https://www.baeldung.com/httpclient-multipart-upload)
|
||||
- [Apache HttpAsyncClient Tutorial](https://www.baeldung.com/httpasyncclient-tutorial)
|
||||
- [Apache HttpClient Tutorial](https://www.baeldung.com/httpclient-guide)
|
||||
- [Advanced HttpClient Configuration](https://www.baeldung.com/httpclient-advanced-config)
|
||||
- [HttpClient 4 – Do Not Follow Redirects](https://www.baeldung.com/httpclient-stop-follow-redirect)
|
||||
- [Custom User-Agent in HttpClient 4](https://www.baeldung.com/httpclient-user-agent-header)
|
||||
- [Apache HttpClient – Do Not Follow Redirects](https://www.baeldung.com/httpclient-stop-follow-redirect)
|
||||
- [Custom User-Agent in Apache HttpClient](https://www.baeldung.com/httpclient-user-agent-header)
|
||||
- [Apache HttpClient Connection Management](https://www.baeldung.com/httpclient-connection-management)
|
||||
- More articles: [[next -->]](../httpclient-2)
|
||||
|
|
|
@ -15,12 +15,6 @@
|
|||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- utils -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<!-- http client -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
## Immutables
|
||||
|
||||
This module contains articles about the Immutables library.
|
||||
|
||||
### Relevant Articles:
|
||||
- [Introduction to Immutables](https://www.baeldung.com/immutables)
|
|
@ -1,34 +0,0 @@
|
|||
<?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>
|
||||
<artifactId>immutables</artifactId>
|
||||
<name>immutables</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.immutables</groupId>
|
||||
<artifactId>value</artifactId>
|
||||
<version>${immutables.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mutabilitydetector</groupId>
|
||||
<artifactId>MutabilityDetector</artifactId>
|
||||
<version>${mutabilitydetector.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<immutables.version>2.5.6</immutables.version>
|
||||
<mutabilitydetector.version>0.9.6</mutabilitydetector.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -5,3 +5,4 @@
|
|||
- [Determine if an Integer’s Square Root Is an Integer in Java](https://www.baeldung.com/java-find-if-square-root-is-integer)
|
||||
- [Guide to Java BigInteger](https://www.baeldung.com/java-biginteger)
|
||||
- [Automorphic Numbers in Java](https://www.baeldung.com/java-automorphic-numbers)
|
||||
- [Convert Byte Size Into a Human-Readable Format in Java](https://www.baeldung.com/java-human-readable-byte-size)
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package com.baeldung.humanreadablebytes;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class FileSizeFormatUtil {
|
||||
private static final long BYTE = 1L;
|
||||
private static final long KB = BYTE << 10;
|
||||
private static final long MB = KB << 10;
|
||||
private static final long GB = MB << 10;
|
||||
private static final long TB = GB << 10;
|
||||
private static final long PB = TB << 10;
|
||||
private static final long EB = PB << 10;
|
||||
private static final DecimalFormat DEC_FORMAT = new DecimalFormat("#.##");
|
||||
|
||||
public static String toHumanReadable(long size) {
|
||||
if (size < 0)
|
||||
throw new IllegalArgumentException("Invalid file size: " + size);
|
||||
if (size >= EB) return formatSize(size, EB, "EB");
|
||||
if (size >= PB) return formatSize(size, PB, "PB");
|
||||
if (size >= TB) return formatSize(size, TB, "TB");
|
||||
if (size >= GB) return formatSize(size, GB, "GB");
|
||||
if (size >= MB) return formatSize(size, MB, "MB");
|
||||
if (size >= KB) return formatSize(size, KB, "KB");
|
||||
return formatSize(size, BYTE, "Bytes");
|
||||
}
|
||||
|
||||
private static String formatSize(long size, long divider, String unitName) {
|
||||
return DEC_FORMAT.format((double) size / divider) + " " + unitName;
|
||||
}
|
||||
|
||||
public static String toHumanReadableWithEnum(long size) {
|
||||
final List<SizeUnit> units = SizeUnit.unitsInDescending();
|
||||
if (size < 0)
|
||||
throw new IllegalArgumentException("Invalid file size: " + size);
|
||||
String result = null;
|
||||
for (SizeUnit unit : units) {
|
||||
if (size >= unit.getUnitBase()) {
|
||||
result = formatSize(size, unit.getUnitBase(), unit.name());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result == null ? formatSize(size, SizeUnit.Bytes.getUnitBase(), SizeUnit.Bytes.name()) : result;
|
||||
}
|
||||
|
||||
public static String toHumanReadableByNumOfLeadingZeros(long size) {
|
||||
if (size < 0)
|
||||
throw new IllegalArgumentException("Invalid file size: " + size);
|
||||
if (size < 1024) return size + " Bytes";
|
||||
int unitIdx = (63 - Long.numberOfLeadingZeros(size)) / 10;
|
||||
return formatSize(size, 1L << (unitIdx * 10), " KMGTPE".charAt(unitIdx) + "B");
|
||||
}
|
||||
|
||||
enum SizeUnit {
|
||||
Bytes(1L),
|
||||
KB(Bytes.unitBase << 10),
|
||||
MB(KB.unitBase << 10),
|
||||
GB(MB.unitBase << 10),
|
||||
TB(GB.unitBase << 10),
|
||||
PB(TB.unitBase << 10),
|
||||
EB(PB.unitBase << 10);
|
||||
|
||||
private final Long unitBase;
|
||||
|
||||
public static List<SizeUnit> unitsInDescending() {
|
||||
List<SizeUnit> list = Arrays.asList(values());
|
||||
Collections.reverse(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public Long getUnitBase() {
|
||||
return unitBase;
|
||||
}
|
||||
|
||||
SizeUnit(long unitBase) {
|
||||
this.unitBase = unitBase;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.baeldung.humanreadablebytes;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class FileSizeFormatUtilUnitTest {
|
||||
private final static Map<Long, String> DATA_MAP = new HashMap<Long, String>() {{
|
||||
put(0L, "0 Bytes");
|
||||
put(1023L, "1023 Bytes");
|
||||
put(1024L, "1 KB");
|
||||
put(12_345L, "12.06 KB");
|
||||
put(10_123_456L, "9.65 MB");
|
||||
put(10_123_456_798L, "9.43 GB");
|
||||
put(1_777_777_777_777_777_777L, "1.54 EB");
|
||||
}};
|
||||
|
||||
@Test
|
||||
public void givenBytes_whenCalltoHumanReadableMethod_thenGetExpectedResults() {
|
||||
DATA_MAP.forEach((in, expected) -> Assert.assertEquals(expected, FileSizeFormatUtil.toHumanReadable(in)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBytes_whenCalltoHumanReadableWithEnumMethod_thenGetExpectedResults() {
|
||||
DATA_MAP.forEach((in, expected) -> Assert.assertEquals(expected, FileSizeFormatUtil.toHumanReadableWithEnum(in)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBytes_whenCalltoHumanReadableByLeadingZeros_thenGetExpectedResults() {
|
||||
DATA_MAP.forEach((in, expected) -> Assert.assertEquals(expected, FileSizeFormatUtil.toHumanReadableByNumOfLeadingZeros(in)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBytes_whenCalltoHumanReadableByFileUtils_thenOutputExpectedResults() {
|
||||
DATA_MAP.forEach((in, expected) -> System.out.println(in + " bytes -> " + FileUtils.byteCountToDisplaySize(in)));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.jersey.exceptionhandling;
|
||||
|
||||
import javax.ws.rs.ApplicationPath;
|
||||
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.IllegalArgumentExceptionMapper;
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.ServerExceptionMapper;
|
||||
|
||||
@ApplicationPath("/exception-handling/*")
|
||||
public class ExceptionHandlingConfig extends ResourceConfig {
|
||||
|
||||
public ExceptionHandlingConfig() {
|
||||
packages("com.baeldung.jersey.exceptionhandling.rest");
|
||||
register(IllegalArgumentExceptionMapper.class);
|
||||
register(ServerExceptionMapper.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.baeldung.jersey.exceptionhandling.data;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.repo.Identifiable;
|
||||
|
||||
public class Stock implements Identifiable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String id;
|
||||
private Double price;
|
||||
|
||||
public Stock() {
|
||||
}
|
||||
|
||||
public Stock(String id, Double price) {
|
||||
this.id = id;
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(Double price) {
|
||||
this.price = price;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.baeldung.jersey.exceptionhandling.data;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.repo.Identifiable;
|
||||
|
||||
public class Wallet implements Identifiable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final Double MIN_CHARGE = 50.0;
|
||||
public static final String MIN_CHARGE_MSG = "minimum charge is: " + MIN_CHARGE;
|
||||
|
||||
private String id;
|
||||
private Double balance = 0.0;
|
||||
|
||||
public Wallet() {
|
||||
}
|
||||
|
||||
public Wallet(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Double getBalance() {
|
||||
return balance;
|
||||
}
|
||||
|
||||
public void setBalance(Double balance) {
|
||||
this.balance = balance;
|
||||
}
|
||||
|
||||
public Double addBalance(Double amount) {
|
||||
if (balance == null)
|
||||
balance = 0.0;
|
||||
|
||||
return balance += amount;
|
||||
}
|
||||
|
||||
public boolean hasFunds(Double amount) {
|
||||
if (balance == null || amount == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (balance - amount) >= 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.baeldung.jersey.exceptionhandling.repo;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Db<T extends Identifiable> {
|
||||
private Map<String, T> db = new HashMap<>();
|
||||
|
||||
public Optional<T> findById(String id) {
|
||||
return Optional.ofNullable(db.get(id));
|
||||
}
|
||||
|
||||
public String save(T t) {
|
||||
String id = t.getId();
|
||||
if (id == null) {
|
||||
id = UUID.randomUUID()
|
||||
.toString();
|
||||
t.setId(id);
|
||||
}
|
||||
db.put(id, t);
|
||||
return id;
|
||||
}
|
||||
|
||||
public void remove(T t) {
|
||||
db.entrySet()
|
||||
.removeIf(entry -> entry.getValue()
|
||||
.getId()
|
||||
.equals(t.getId()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung.jersey.exceptionhandling.repo;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface Identifiable extends Serializable {
|
||||
void setId(String id);
|
||||
|
||||
String getId();
|
||||
|
||||
public static void assertValid(Identifiable i) {
|
||||
if (i == null)
|
||||
throw new IllegalArgumentException("object cannot be null");
|
||||
|
||||
if (i.getId() == null)
|
||||
throw new IllegalArgumentException("object id cannot be null");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.baeldung.jersey.exceptionhandling.rest;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.data.Stock;
|
||||
import com.baeldung.jersey.exceptionhandling.repo.Db;
|
||||
import com.baeldung.jersey.exceptionhandling.service.Repository;
|
||||
|
||||
@Path("/stocks")
|
||||
public class StocksResource {
|
||||
private static final Db<Stock> stocks = Repository.STOCKS_DB;
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response post(Stock stock) {
|
||||
stocks.save(stock);
|
||||
|
||||
return Response.ok(stock)
|
||||
.build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{ticker}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response get(@PathParam("ticker") String id) {
|
||||
Optional<Stock> stock = stocks.findById(id);
|
||||
stock.orElseThrow(IllegalArgumentException::new);
|
||||
|
||||
return Response.ok(stock.get())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package com.baeldung.jersey.exceptionhandling.rest;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.data.Stock;
|
||||
import com.baeldung.jersey.exceptionhandling.data.Wallet;
|
||||
import com.baeldung.jersey.exceptionhandling.repo.Db;
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.InvalidTradeException;
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.RestErrorResponse;
|
||||
import com.baeldung.jersey.exceptionhandling.service.Repository;
|
||||
|
||||
@Path("/wallets")
|
||||
public class WalletsResource {
|
||||
private static final Db<Stock> stocks = Repository.STOCKS_DB;
|
||||
private static final Db<Wallet> wallets = Repository.WALLETS_DB;
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response post(Wallet wallet) {
|
||||
wallets.save(wallet);
|
||||
|
||||
return Response.ok(wallet)
|
||||
.build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response get(@PathParam("id") String id) {
|
||||
Optional<Wallet> wallet = wallets.findById(id);
|
||||
wallet.orElseThrow(IllegalArgumentException::new);
|
||||
|
||||
return Response.ok(wallet.get())
|
||||
.build();
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/{amount}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response putAmount(@PathParam("id") String id, @PathParam("amount") Double amount) {
|
||||
Optional<Wallet> wallet = wallets.findById(id);
|
||||
wallet.orElseThrow(IllegalArgumentException::new);
|
||||
|
||||
if (amount < Wallet.MIN_CHARGE) {
|
||||
throw new InvalidTradeException(Wallet.MIN_CHARGE_MSG);
|
||||
}
|
||||
|
||||
wallet.get()
|
||||
.addBalance(amount);
|
||||
wallets.save(wallet.get());
|
||||
|
||||
return Response.ok(wallet)
|
||||
.build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/{wallet}/buy/{ticker}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response postBuyStock(@PathParam("wallet") String walletId, @PathParam("ticker") String id) {
|
||||
Optional<Stock> stock = stocks.findById(id);
|
||||
stock.orElseThrow(InvalidTradeException::new);
|
||||
|
||||
Optional<Wallet> w = wallets.findById(walletId);
|
||||
w.orElseThrow(InvalidTradeException::new);
|
||||
|
||||
Wallet wallet = w.get();
|
||||
Double price = stock.get()
|
||||
.getPrice();
|
||||
|
||||
if (!wallet.hasFunds(price)) {
|
||||
RestErrorResponse response = new RestErrorResponse();
|
||||
response.setSubject(wallet);
|
||||
response.setMessage("insufficient balance");
|
||||
throw new WebApplicationException(Response.status(Status.NOT_ACCEPTABLE)
|
||||
.entity(response)
|
||||
.build());
|
||||
}
|
||||
|
||||
wallet.addBalance(-price);
|
||||
wallets.save(wallet);
|
||||
|
||||
return Response.ok(wallet)
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.baeldung.jersey.exceptionhandling.rest.exceptions;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.ext.ExceptionMapper;
|
||||
|
||||
public class IllegalArgumentExceptionMapper implements ExceptionMapper<IllegalArgumentException> {
|
||||
public static final String DEFAULT_MESSAGE = "an illegal argument was provided";
|
||||
|
||||
@Override
|
||||
public Response toResponse(final IllegalArgumentException exception) {
|
||||
return Response.status(Response.Status.EXPECTATION_FAILED)
|
||||
.entity(build(exception.getMessage()))
|
||||
.type(MediaType.APPLICATION_JSON)
|
||||
.build();
|
||||
}
|
||||
|
||||
private RestErrorResponse build(String message) {
|
||||
RestErrorResponse response = new RestErrorResponse();
|
||||
response.setMessage(DEFAULT_MESSAGE + ": " + message);
|
||||
return response;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung.jersey.exceptionhandling.rest.exceptions;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
public class InvalidTradeException extends WebApplicationException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String MESSAGE = "invalid trade operation";
|
||||
|
||||
public InvalidTradeException() {
|
||||
super(MESSAGE, Response.Status.NOT_ACCEPTABLE);
|
||||
}
|
||||
|
||||
public InvalidTradeException(String detail) {
|
||||
super(MESSAGE + ": " + detail, Response.Status.NOT_ACCEPTABLE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.baeldung.jersey.exceptionhandling.rest.exceptions;
|
||||
|
||||
public class RestErrorResponse {
|
||||
private Object subject;
|
||||
private String message;
|
||||
|
||||
public RestErrorResponse() {
|
||||
}
|
||||
|
||||
public RestErrorResponse(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public RestErrorResponse(Object subject, String message) {
|
||||
this.subject = subject;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Object getSubject() {
|
||||
return subject;
|
||||
}
|
||||
|
||||
public void setSubject(Object subject) {
|
||||
this.subject = subject;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.baeldung.jersey.exceptionhandling.rest.exceptions;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.ext.ExceptionMapper;
|
||||
|
||||
public class ServerExceptionMapper implements ExceptionMapper<WebApplicationException> {
|
||||
public static final String HTTP_405_MESSAGE = "METHOD_NOT_ALLOWED";
|
||||
|
||||
@Override
|
||||
public Response toResponse(final WebApplicationException exception) {
|
||||
String message = exception.getMessage();
|
||||
Response response = exception.getResponse();
|
||||
Status status = response.getStatusInfo()
|
||||
.toEnum();
|
||||
|
||||
switch (status) {
|
||||
case METHOD_NOT_ALLOWED:
|
||||
message = HTTP_405_MESSAGE;
|
||||
break;
|
||||
case INTERNAL_SERVER_ERROR:
|
||||
message = "internal validation - " + exception;
|
||||
break;
|
||||
default:
|
||||
message = "[unhandled response code] " + exception;
|
||||
}
|
||||
|
||||
return Response.status(status)
|
||||
.entity(status + ": " + message)
|
||||
.type(MediaType.TEXT_PLAIN)
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.jersey.exceptionhandling.service;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.data.Stock;
|
||||
import com.baeldung.jersey.exceptionhandling.data.Wallet;
|
||||
import com.baeldung.jersey.exceptionhandling.repo.Db;
|
||||
|
||||
public class Repository {
|
||||
public static Db<Stock> STOCKS_DB = new Db<>();
|
||||
public static Db<Wallet> WALLETS_DB = new Db<>();
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package com.baeldung.jersey.exceptionhandling.rest;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.ws.rs.client.Entity;
|
||||
import javax.ws.rs.client.Invocation;
|
||||
import javax.ws.rs.core.Application;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.glassfish.jersey.test.JerseyTest;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.ExceptionHandlingConfig;
|
||||
import com.baeldung.jersey.exceptionhandling.data.Stock;
|
||||
import com.baeldung.jersey.exceptionhandling.data.Wallet;
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.IllegalArgumentExceptionMapper;
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.RestErrorResponse;
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.ServerExceptionMapper;
|
||||
|
||||
public class StocksResourceIntegrationTest extends JerseyTest {
|
||||
private static final Entity<String> EMPTY_BODY = Entity.json("");
|
||||
private static final Stock STOCK = new Stock("BAEL", 51.57);
|
||||
private static final String MY_WALLET = "MY-WALLET";
|
||||
private static final Wallet WALLET = new Wallet(MY_WALLET);
|
||||
private static final int INSUFFICIENT_AMOUNT = (int) (Wallet.MIN_CHARGE - 1);
|
||||
|
||||
@Override
|
||||
protected Application configure() {
|
||||
return new ExceptionHandlingConfig();
|
||||
}
|
||||
|
||||
private Invocation.Builder stocks(String path) {
|
||||
return target("/stocks" + path).request();
|
||||
}
|
||||
|
||||
private Invocation.Builder wallets(String path, Object... args) {
|
||||
return target("/wallets" + String.format(path, args)).request();
|
||||
}
|
||||
|
||||
private Entity<?> entity(Object object) {
|
||||
return Entity.entity(object, MediaType.APPLICATION_JSON_TYPE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenMethodNotAllowed_thenCustomMessage() {
|
||||
Response response = stocks("").get();
|
||||
|
||||
assertEquals(Status.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatus());
|
||||
|
||||
String content = response.readEntity(String.class);
|
||||
assertThat(content, containsString(ServerExceptionMapper.HTTP_405_MESSAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenTickerNotExists_thenRestErrorResponse() {
|
||||
Response response = stocks("/UNDEFINED").get();
|
||||
|
||||
assertEquals(Status.EXPECTATION_FAILED.getStatusCode(), response.getStatus());
|
||||
|
||||
RestErrorResponse content = response.readEntity(RestErrorResponse.class);
|
||||
assertThat(content.getMessage(), startsWith(IllegalArgumentExceptionMapper.DEFAULT_MESSAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAmountLessThanMinimum_whenAddingToWallet_thenInvalidTradeException() {
|
||||
wallets("").post(entity(WALLET));
|
||||
Response response = wallets("/%s/%d", MY_WALLET, INSUFFICIENT_AMOUNT).put(EMPTY_BODY);
|
||||
|
||||
assertEquals(Status.NOT_ACCEPTABLE.getStatusCode(), response.getStatus());
|
||||
|
||||
String content = response.readEntity(String.class);
|
||||
assertThat(content, containsString(Wallet.MIN_CHARGE_MSG));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInsifficientFunds_whenBuyingStock_thenWebApplicationException() {
|
||||
stocks("").post(entity(STOCK));
|
||||
wallets("").post(entity(WALLET));
|
||||
|
||||
Response response = wallets("/%s/buy/%s", MY_WALLET, STOCK.getId()).post(EMPTY_BODY);
|
||||
assertEquals(Status.NOT_ACCEPTABLE.getStatusCode(), response.getStatus());
|
||||
|
||||
RestErrorResponse content = response.readEntity(RestErrorResponse.class);
|
||||
assertNotNull(content.getSubject());
|
||||
|
||||
HashMap<?, ?> subject = (HashMap<?, ?>) content.getSubject();
|
||||
assertEquals(subject.get("id"), WALLET.getId());
|
||||
assertTrue(WALLET.getBalance() < Wallet.MIN_CHARGE);
|
||||
}
|
||||
}
|
|
@ -53,3 +53,4 @@ Enjoy it :)
|
|||
- [Intro to Performance Testing using JMeter](https://www.baeldung.com/jmeter)
|
||||
- [Configure Jenkins to Run and Show JMeter Tests](https://www.baeldung.com/ops/jenkins-and-jmeter)
|
||||
- [Write Extracted Data to a File Using JMeter](https://www.baeldung.com/jmeter-write-to-file)
|
||||
- [Basic Authentication in JMeter](https://www.baeldung.com/jmeter-basic-auth)
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package com.baeldung.configuration;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
@Configuration
|
||||
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
|
||||
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
|
||||
auth.inMemoryAuthentication()
|
||||
.withUser("admin").password(encoder.encode("admin")).roles("USER", "ADMIN")
|
||||
.and()
|
||||
.withUser("user1").password(encoder.encode("password1")).roles("USER")
|
||||
.and()
|
||||
.withUser("user2").password(encoder.encode("password2")).roles("USER")
|
||||
.and()
|
||||
.withUser("user3").password(encoder.encode("password3")).roles("USER")
|
||||
.and()
|
||||
.withUser("user4").password(encoder.encode("password4")).roles("USER")
|
||||
.and()
|
||||
.withUser("user5").password(encoder.encode("password5")).roles("USER")
|
||||
.and()
|
||||
.withUser("user6").password(encoder.encode("password6")).roles("USER")
|
||||
.and()
|
||||
.withUser("user7").password(encoder.encode("password7")).roles("USER")
|
||||
.and()
|
||||
.withUser("user8").password(encoder.encode("password8")).roles("USER")
|
||||
.and()
|
||||
.withUser("user9").password(encoder.encode("password9")).roles("USER")
|
||||
.and()
|
||||
.withUser("user10").password(encoder.encode("password10")).roles("USER");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/secured/**").authenticated()
|
||||
.anyRequest().permitAll()
|
||||
.and()
|
||||
.httpBasic();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.baeldung.controller;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.model.Response;
|
||||
|
||||
@RestController
|
||||
public class SecuredUuidController {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SecuredUuidController.class);
|
||||
|
||||
@GetMapping("/secured/uuid")
|
||||
public Response uuid() {
|
||||
|
||||
LOGGER.info("Returning response");
|
||||
|
||||
return new Response(String.format("Secured test message... %s.", UUID.randomUUID()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.4.3">
|
||||
<hashTree>
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
|
||||
<stringProp name="TestPlan.comments"></stringProp>
|
||||
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
||||
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||
</TestPlan>
|
||||
<hashTree>
|
||||
<Arguments guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="host" elementType="Argument">
|
||||
<stringProp name="Argument.name">host</stringProp>
|
||||
<stringProp name="Argument.value">localhost</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<stringProp name="Argument.desc">Host of Webservice</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="port" elementType="Argument">
|
||||
<stringProp name="Argument.name">port</stringProp>
|
||||
<stringProp name="Argument.value">8080</stringProp>
|
||||
<stringProp name="Argument.desc">Port of web server</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="username" elementType="Argument">
|
||||
<stringProp name="Argument.name">username</stringProp>
|
||||
<stringProp name="Argument.value">user1</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="password" elementType="Argument">
|
||||
<stringProp name="Argument.name">password</stringProp>
|
||||
<stringProp name="Argument.value">password1</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</Arguments>
|
||||
<hashTree/>
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Number of Users" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">1</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">1</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
|
||||
<longProp name="ThreadGroup.start_time">1375525852000</longProp>
|
||||
<longProp name="ThreadGroup.end_time">1375525852000</longProp>
|
||||
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
||||
<stringProp name="ThreadGroup.duration"></stringProp>
|
||||
<stringProp name="ThreadGroup.delay"></stringProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">false</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Soap Request" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain">${host}</stringProp>
|
||||
<stringProp name="HTTPSampler.port">${port}</stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/secured/uuid</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">false</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="JSR223 PreProcessor" enabled="true">
|
||||
<stringProp name="cacheKey">false</stringProp>
|
||||
<stringProp name="filename"></stringProp>
|
||||
<stringProp name="parameters"></stringProp>
|
||||
<stringProp name="script">import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
String username = vars.get("username");
|
||||
String password = vars.get("password");
|
||||
String credentials = username + ":" + password;
|
||||
byte[] encodedUsernamePassword = Base64.encodeBase64(credentials.getBytes());
|
||||
vars.put("base64Credentials", new String(encodedUsernamePassword));
|
||||
</stringProp>
|
||||
<stringProp name="scriptLanguage">java</stringProp>
|
||||
</JSR223PreProcessor>
|
||||
<hashTree/>
|
||||
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
|
||||
<collectionProp name="HeaderManager.headers">
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Content-Type</stringProp>
|
||||
<stringProp name="Header.value">text/xml; charset=utf-8</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Authorization</stringProp>
|
||||
<stringProp name="Header.value">basic ${base64Credentials}</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</HeaderManager>
|
||||
<hashTree/>
|
||||
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="HTTP 200 Status" enabled="true">
|
||||
<collectionProp name="Asserion.test_strings">
|
||||
<stringProp name="49586">200</stringProp>
|
||||
</collectionProp>
|
||||
<stringProp name="Assertion.custom_message"></stringProp>
|
||||
<stringProp name="Assertion.test_field">Assertion.response_code</stringProp>
|
||||
<boolProp name="Assertion.assume_success">false</boolProp>
|
||||
<intProp name="Assertion.test_type">8</intProp>
|
||||
</ResponseAssertion>
|
||||
<hashTree/>
|
||||
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response content assertion" enabled="true">
|
||||
<collectionProp name="Asserion.test_strings">
|
||||
<stringProp name="1645228770">Secured test message...</stringProp>
|
||||
</collectionProp>
|
||||
<stringProp name="TestPlan.comments">Verify content in response</stringProp>
|
||||
<stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
|
||||
<boolProp name="Assertion.assume_success">false</boolProp>
|
||||
<intProp name="Assertion.test_type">16</intProp>
|
||||
<stringProp name="Assertion.custom_message"></stringProp>
|
||||
</ResponseAssertion>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
|
||||
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||
<objProp>
|
||||
<name>saveConfig</name>
|
||||
<value class="SampleSaveConfiguration">
|
||||
<time>true</time>
|
||||
<latency>true</latency>
|
||||
<timestamp>true</timestamp>
|
||||
<success>true</success>
|
||||
<label>true</label>
|
||||
<code>true</code>
|
||||
<message>true</message>
|
||||
<threadName>true</threadName>
|
||||
<dataType>false</dataType>
|
||||
<encoding>false</encoding>
|
||||
<assertions>true</assertions>
|
||||
<subresults>false</subresults>
|
||||
<responseData>false</responseData>
|
||||
<samplerData>false</samplerData>
|
||||
<xml>false</xml>
|
||||
<fieldNames>true</fieldNames>
|
||||
<responseHeaders>false</responseHeaders>
|
||||
<requestHeaders>false</requestHeaders>
|
||||
<responseDataOnError>true</responseDataOnError>
|
||||
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
|
||||
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||
<bytes>true</bytes>
|
||||
<hostname>true</hostname>
|
||||
<threadCounts>true</threadCounts>
|
||||
<sampleCount>true</sampleCount>
|
||||
</value>
|
||||
</objProp>
|
||||
<stringProp name="filename"></stringProp>
|
||||
</ResultCollector>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</jmeterTestPlan>
|
|
@ -0,0 +1,166 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.4.3">
|
||||
<hashTree>
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
|
||||
<stringProp name="TestPlan.comments"></stringProp>
|
||||
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
||||
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||
</TestPlan>
|
||||
<hashTree>
|
||||
<Arguments guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="host" elementType="Argument">
|
||||
<stringProp name="Argument.name">host</stringProp>
|
||||
<stringProp name="Argument.value">localhost</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<stringProp name="Argument.desc">Host of Webservice</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="port" elementType="Argument">
|
||||
<stringProp name="Argument.name">port</stringProp>
|
||||
<stringProp name="Argument.value">8080</stringProp>
|
||||
<stringProp name="Argument.desc">Port of web server</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="csvFileLocation" elementType="Argument">
|
||||
<stringProp name="Argument.name">csvFileLocation</stringProp>
|
||||
<stringProp name="Argument.value">D:\\work\\credentials.csv</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</Arguments>
|
||||
<hashTree/>
|
||||
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
|
||||
<collectionProp name="HeaderManager.headers">
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Content-Type</stringProp>
|
||||
<stringProp name="Header.value">text/xml; charset=utf-8</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</HeaderManager>
|
||||
<hashTree/>
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Number of Users" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">20</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">1</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">0</stringProp>
|
||||
<longProp name="ThreadGroup.start_time">1375525852000</longProp>
|
||||
<longProp name="ThreadGroup.end_time">1375525852000</longProp>
|
||||
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
||||
<stringProp name="ThreadGroup.duration"></stringProp>
|
||||
<stringProp name="ThreadGroup.delay"></stringProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">false</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<CSVDataSet guiclass="TestBeanGUI" testclass="CSVDataSet" testname="CSV Data Set Config" enabled="true">
|
||||
<stringProp name="delimiter">,</stringProp>
|
||||
<stringProp name="fileEncoding"></stringProp>
|
||||
<stringProp name="filename">${csvFileLocation}</stringProp>
|
||||
<boolProp name="ignoreFirstLine">false</boolProp>
|
||||
<boolProp name="quotedData">false</boolProp>
|
||||
<boolProp name="recycle">true</boolProp>
|
||||
<stringProp name="shareMode">shareMode.all</stringProp>
|
||||
<boolProp name="stopThread">false</boolProp>
|
||||
<stringProp name="variableNames">username,password</stringProp>
|
||||
</CSVDataSet>
|
||||
<hashTree/>
|
||||
<AuthManager guiclass="AuthPanel" testclass="AuthManager" testname="HTTP Authorization Manager" enabled="true">
|
||||
<collectionProp name="AuthManager.auth_list">
|
||||
<elementProp name="" elementType="Authorization">
|
||||
<stringProp name="Authorization.url">http://${host}:${port}/secured/uuid</stringProp>
|
||||
<stringProp name="Authorization.username">${username}</stringProp>
|
||||
<stringProp name="Authorization.password">${password}</stringProp>
|
||||
<stringProp name="Authorization.domain"></stringProp>
|
||||
<stringProp name="Authorization.realm"></stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
<boolProp name="AuthManager.controlledByThreadGroup">false</boolProp>
|
||||
<boolProp name="AuthManager.clearEachIteration">true</boolProp>
|
||||
</AuthManager>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Soap Request" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain">${host}</stringProp>
|
||||
<stringProp name="HTTPSampler.port">${port}</stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/secured/uuid</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">false</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="HTTP 200 Status" enabled="true">
|
||||
<collectionProp name="Asserion.test_strings">
|
||||
<stringProp name="49586">200</stringProp>
|
||||
</collectionProp>
|
||||
<stringProp name="Assertion.custom_message"></stringProp>
|
||||
<stringProp name="Assertion.test_field">Assertion.response_code</stringProp>
|
||||
<boolProp name="Assertion.assume_success">false</boolProp>
|
||||
<intProp name="Assertion.test_type">8</intProp>
|
||||
</ResponseAssertion>
|
||||
<hashTree/>
|
||||
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response content assertion" enabled="true">
|
||||
<collectionProp name="Asserion.test_strings">
|
||||
<stringProp name="1645228770">Secured test message...</stringProp>
|
||||
</collectionProp>
|
||||
<stringProp name="TestPlan.comments">Verify content in response</stringProp>
|
||||
<stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
|
||||
<boolProp name="Assertion.assume_success">false</boolProp>
|
||||
<intProp name="Assertion.test_type">16</intProp>
|
||||
<stringProp name="Assertion.custom_message"></stringProp>
|
||||
</ResponseAssertion>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
|
||||
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||
<objProp>
|
||||
<name>saveConfig</name>
|
||||
<value class="SampleSaveConfiguration">
|
||||
<time>true</time>
|
||||
<latency>true</latency>
|
||||
<timestamp>true</timestamp>
|
||||
<success>true</success>
|
||||
<label>true</label>
|
||||
<code>true</code>
|
||||
<message>true</message>
|
||||
<threadName>true</threadName>
|
||||
<dataType>false</dataType>
|
||||
<encoding>false</encoding>
|
||||
<assertions>true</assertions>
|
||||
<subresults>false</subresults>
|
||||
<responseData>false</responseData>
|
||||
<samplerData>false</samplerData>
|
||||
<xml>false</xml>
|
||||
<fieldNames>true</fieldNames>
|
||||
<responseHeaders>false</responseHeaders>
|
||||
<requestHeaders>false</requestHeaders>
|
||||
<responseDataOnError>true</responseDataOnError>
|
||||
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
|
||||
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||
<bytes>true</bytes>
|
||||
<hostname>true</hostname>
|
||||
<threadCounts>true</threadCounts>
|
||||
<sampleCount>true</sampleCount>
|
||||
</value>
|
||||
</objProp>
|
||||
<stringProp name="filename"></stringProp>
|
||||
</ResultCollector>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</jmeterTestPlan>
|
|
@ -0,0 +1,159 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.4.3">
|
||||
<hashTree>
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
|
||||
<stringProp name="TestPlan.comments"></stringProp>
|
||||
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
||||
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||
</TestPlan>
|
||||
<hashTree>
|
||||
<Arguments guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="host" elementType="Argument">
|
||||
<stringProp name="Argument.name">host</stringProp>
|
||||
<stringProp name="Argument.value">localhost</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<stringProp name="Argument.desc">Host of Webservice</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="port" elementType="Argument">
|
||||
<stringProp name="Argument.name">port</stringProp>
|
||||
<stringProp name="Argument.value">8080</stringProp>
|
||||
<stringProp name="Argument.desc">Port of web server</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="username" elementType="Argument">
|
||||
<stringProp name="Argument.name">username</stringProp>
|
||||
<stringProp name="Argument.value">user1</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="password" elementType="Argument">
|
||||
<stringProp name="Argument.name">password</stringProp>
|
||||
<stringProp name="Argument.value">password1</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</Arguments>
|
||||
<hashTree/>
|
||||
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
|
||||
<collectionProp name="HeaderManager.headers">
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Content-Type</stringProp>
|
||||
<stringProp name="Header.value">text/xml; charset=utf-8</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</HeaderManager>
|
||||
<hashTree/>
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Number of Users" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">1</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">1</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">0</stringProp>
|
||||
<longProp name="ThreadGroup.start_time">1375525852000</longProp>
|
||||
<longProp name="ThreadGroup.end_time">1375525852000</longProp>
|
||||
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
||||
<stringProp name="ThreadGroup.duration"></stringProp>
|
||||
<stringProp name="ThreadGroup.delay"></stringProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">false</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<AuthManager guiclass="AuthPanel" testclass="AuthManager" testname="HTTP Authorization Manager" enabled="true">
|
||||
<collectionProp name="AuthManager.auth_list">
|
||||
<elementProp name="" elementType="Authorization">
|
||||
<stringProp name="Authorization.url">http://${host}:${port}/secured/uuid</stringProp>
|
||||
<stringProp name="Authorization.username">${username}</stringProp>
|
||||
<stringProp name="Authorization.password">${password}</stringProp>
|
||||
<stringProp name="Authorization.domain"></stringProp>
|
||||
<stringProp name="Authorization.realm"></stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
<boolProp name="AuthManager.controlledByThreadGroup">false</boolProp>
|
||||
<boolProp name="AuthManager.clearEachIteration">true</boolProp>
|
||||
</AuthManager>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Soap Request" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain">${host}</stringProp>
|
||||
<stringProp name="HTTPSampler.port">${port}</stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/secured/uuid</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">false</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="HTTP 200 Status" enabled="true">
|
||||
<collectionProp name="Asserion.test_strings">
|
||||
<stringProp name="49586">200</stringProp>
|
||||
</collectionProp>
|
||||
<stringProp name="Assertion.custom_message"></stringProp>
|
||||
<stringProp name="Assertion.test_field">Assertion.response_code</stringProp>
|
||||
<boolProp name="Assertion.assume_success">false</boolProp>
|
||||
<intProp name="Assertion.test_type">8</intProp>
|
||||
</ResponseAssertion>
|
||||
<hashTree/>
|
||||
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response content assertion" enabled="true">
|
||||
<collectionProp name="Asserion.test_strings">
|
||||
<stringProp name="1645228770">Secured test message...</stringProp>
|
||||
</collectionProp>
|
||||
<stringProp name="TestPlan.comments">Verify content in response</stringProp>
|
||||
<stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
|
||||
<boolProp name="Assertion.assume_success">false</boolProp>
|
||||
<intProp name="Assertion.test_type">16</intProp>
|
||||
<stringProp name="Assertion.custom_message"></stringProp>
|
||||
</ResponseAssertion>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
|
||||
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||
<objProp>
|
||||
<name>saveConfig</name>
|
||||
<value class="SampleSaveConfiguration">
|
||||
<time>true</time>
|
||||
<latency>true</latency>
|
||||
<timestamp>true</timestamp>
|
||||
<success>true</success>
|
||||
<label>true</label>
|
||||
<code>true</code>
|
||||
<message>true</message>
|
||||
<threadName>true</threadName>
|
||||
<dataType>false</dataType>
|
||||
<encoding>false</encoding>
|
||||
<assertions>true</assertions>
|
||||
<subresults>false</subresults>
|
||||
<responseData>false</responseData>
|
||||
<samplerData>false</samplerData>
|
||||
<xml>false</xml>
|
||||
<fieldNames>true</fieldNames>
|
||||
<responseHeaders>false</responseHeaders>
|
||||
<requestHeaders>false</requestHeaders>
|
||||
<responseDataOnError>true</responseDataOnError>
|
||||
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
|
||||
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||
<bytes>true</bytes>
|
||||
<hostname>true</hostname>
|
||||
<threadCounts>true</threadCounts>
|
||||
<sampleCount>true</sampleCount>
|
||||
</value>
|
||||
</objProp>
|
||||
<stringProp name="filename"></stringProp>
|
||||
</ResultCollector>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</jmeterTestPlan>
|
|
@ -0,0 +1,139 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.4.3">
|
||||
<hashTree>
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
|
||||
<stringProp name="TestPlan.comments"></stringProp>
|
||||
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
|
||||
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||
</TestPlan>
|
||||
<hashTree>
|
||||
<Arguments guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="host" elementType="Argument">
|
||||
<stringProp name="Argument.name">host</stringProp>
|
||||
<stringProp name="Argument.value">localhost</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<stringProp name="Argument.desc">Host of Webservice</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="port" elementType="Argument">
|
||||
<stringProp name="Argument.name">port</stringProp>
|
||||
<stringProp name="Argument.value">8080</stringProp>
|
||||
<stringProp name="Argument.desc">Port of web server</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</Arguments>
|
||||
<hashTree/>
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Number of Users" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">2</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">5</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">5</stringProp>
|
||||
<longProp name="ThreadGroup.start_time">1375525852000</longProp>
|
||||
<longProp name="ThreadGroup.end_time">1375525852000</longProp>
|
||||
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
||||
<stringProp name="ThreadGroup.duration"></stringProp>
|
||||
<stringProp name="ThreadGroup.delay"></stringProp>
|
||||
<boolProp name="ThreadGroup.same_user_on_next_iteration">false</boolProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Soap Request" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain">${host}</stringProp>
|
||||
<stringProp name="HTTPSampler.port">${port}</stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">/secured/uuid</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">false</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
|
||||
<collectionProp name="HeaderManager.headers">
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Content-Type</stringProp>
|
||||
<stringProp name="Header.value">text/xml; charset=utf-8</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="" elementType="Header">
|
||||
<stringProp name="Header.name">Authorization</stringProp>
|
||||
<stringProp name="Header.value">dXNlcjE6cGFzc3dvcmQx</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</HeaderManager>
|
||||
<hashTree/>
|
||||
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="HTTP 200 Status" enabled="true">
|
||||
<collectionProp name="Asserion.test_strings">
|
||||
<stringProp name="49586">200</stringProp>
|
||||
</collectionProp>
|
||||
<stringProp name="Assertion.custom_message"></stringProp>
|
||||
<stringProp name="Assertion.test_field">Assertion.response_code</stringProp>
|
||||
<boolProp name="Assertion.assume_success">false</boolProp>
|
||||
<intProp name="Assertion.test_type">8</intProp>
|
||||
</ResponseAssertion>
|
||||
<hashTree/>
|
||||
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response content assertion" enabled="true">
|
||||
<collectionProp name="Asserion.test_strings">
|
||||
<stringProp name="1645228770">Secured test message...</stringProp>
|
||||
</collectionProp>
|
||||
<stringProp name="TestPlan.comments">Verify content in response</stringProp>
|
||||
<stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
|
||||
<boolProp name="Assertion.assume_success">false</boolProp>
|
||||
<intProp name="Assertion.test_type">16</intProp>
|
||||
<stringProp name="Assertion.custom_message"></stringProp>
|
||||
</ResponseAssertion>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
|
||||
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||
<objProp>
|
||||
<name>saveConfig</name>
|
||||
<value class="SampleSaveConfiguration">
|
||||
<time>true</time>
|
||||
<latency>true</latency>
|
||||
<timestamp>true</timestamp>
|
||||
<success>true</success>
|
||||
<label>true</label>
|
||||
<code>true</code>
|
||||
<message>true</message>
|
||||
<threadName>true</threadName>
|
||||
<dataType>false</dataType>
|
||||
<encoding>false</encoding>
|
||||
<assertions>true</assertions>
|
||||
<subresults>false</subresults>
|
||||
<responseData>false</responseData>
|
||||
<samplerData>false</samplerData>
|
||||
<xml>false</xml>
|
||||
<fieldNames>true</fieldNames>
|
||||
<responseHeaders>false</responseHeaders>
|
||||
<requestHeaders>false</requestHeaders>
|
||||
<responseDataOnError>true</responseDataOnError>
|
||||
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
|
||||
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||
<bytes>true</bytes>
|
||||
<hostname>true</hostname>
|
||||
<threadCounts>true</threadCounts>
|
||||
<sampleCount>true</sampleCount>
|
||||
</value>
|
||||
</objProp>
|
||||
<stringProp name="filename"></stringProp>
|
||||
</ResultCollector>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</jmeterTestPlan>
|
|
@ -0,0 +1,10 @@
|
|||
user1,password1
|
||||
user2,password2
|
||||
user3,password3
|
||||
user4,password4
|
||||
user5,password5
|
||||
user6,password6
|
||||
user7,password7
|
||||
user8,password8
|
||||
user9,password9
|
||||
user10,password10
|
|
|
@ -1,6 +0,0 @@
|
|||
## JTA
|
||||
|
||||
This module contains articles about the Java Transaction API (JTA).
|
||||
|
||||
### Relevant Articles:
|
||||
- [Guide to Jakarta EE JTA](https://www.baeldung.com/jee-jta)
|
55
jta/pom.xml
55
jta/pom.xml
|
@ -1,55 +0,0 @@
|
|||
<?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>
|
||||
<artifactId>jta</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>jta</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>JEE JTA demo</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-bom</artifactId>
|
||||
<version>${log4j2.version}</version>
|
||||
<scope>import</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jta-bitronix</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<spring-boot.version>2.4.7</spring-boot.version>
|
||||
<log4j2.version>2.17.1</log4j2.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="true" scanPeriod="15 seconds" debug="false">
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>[%d{ISO8601}]-[%thread] %-5level %logger - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -16,4 +16,6 @@ Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-m
|
|||
- [Introduction to Takes](https://www.baeldung.com/java-takes)
|
||||
- [Using NullAway to Avoid NullPointerExceptions](https://www.baeldung.com/java-nullaway)
|
||||
- [Introduction to Alibaba Arthas](https://www.baeldung.com/java-alibaba-arthas-intro)
|
||||
- More articles [[<-- prev]](/libraries-2) [[next -->]](/libraries-4)
|
||||
- [Introduction to Structurizr](https://www.baeldung.com/structurizr)
|
||||
- [Introduction to Immutables](https://www.baeldung.com/immutables)
|
||||
- More articles [[<-- prev]](../libraries-2) [[next -->]](../libraries-4)
|
||||
|
|
|
@ -86,6 +86,43 @@
|
|||
<artifactId>error_prone_core</artifactId>
|
||||
<version>${errorprone.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.structurizr</groupId>
|
||||
<artifactId>structurizr-core</artifactId>
|
||||
<version>${structurizr.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.structurizr</groupId>
|
||||
<artifactId>structurizr-spring</artifactId>
|
||||
<version>${structurizr.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.structurizr</groupId>
|
||||
<artifactId>structurizr-client</artifactId>
|
||||
<version>${structurizr.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.structurizr</groupId>
|
||||
<artifactId>structurizr-analysis</artifactId>
|
||||
<version>${structurizr.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.structurizr</groupId>
|
||||
<artifactId>structurizr-plantuml</artifactId>
|
||||
<version>${structurizr.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.immutables</groupId>
|
||||
<artifactId>value</artifactId>
|
||||
<version>${immutables.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mutabilitydetector</groupId>
|
||||
<artifactId>MutabilityDetector</artifactId>
|
||||
<version>${mutabilitydetector.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
|
@ -140,7 +177,7 @@
|
|||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs>
|
||||
<!-- NullAway will warn by default, uncomment the next line to make the build
|
||||
<!-- NullAway will warn by default, uncomment the next line to make the build
|
||||
fail -->
|
||||
<!-- <arg>-Xep:NullAway:ERROR</arg> -->
|
||||
<arg>-XepExcludedPaths:(.*)/test/.*|(.*)/jcabi/.*</arg>
|
||||
|
@ -153,7 +190,7 @@
|
|||
<artifactId>plexus-compiler-javac-errorprone</artifactId>
|
||||
<version>2.8</version>
|
||||
</dependency>
|
||||
<!-- override plexus-compiler-javac-errorprone's dependency on Error Prone with the
|
||||
<!-- override plexus-compiler-javac-errorprone's dependency on Error Prone with the
|
||||
latest version -->
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
|
@ -229,6 +266,9 @@
|
|||
<nullaway.version>0.3.0</nullaway.version>
|
||||
<plexus-compiler.version>2.8</plexus-compiler.version>
|
||||
<errorprone.version>2.1.3</errorprone.version>
|
||||
<structurizr.version>1.0.0</structurizr.version>
|
||||
<immutables.version>2.5.6</immutables.version>
|
||||
<mutabilitydetector.version>0.9.6</mutabilitydetector.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue