diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalaccesserror/Class1.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalaccesserror/Class1.java new file mode 100644 index 0000000000..d50d2bc5f5 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalaccesserror/Class1.java @@ -0,0 +1,8 @@ +package com.baeldung.exceptions.illegalaccesserror; + +public class Class1 { + + public void bar() { + System.out.println("SUCCESS"); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalaccesserror/Class2.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalaccesserror/Class2.java new file mode 100644 index 0000000000..766ceccb6b --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalaccesserror/Class2.java @@ -0,0 +1,10 @@ +package com.baeldung.exceptions.illegalaccesserror; + +public class Class2 { + + public void foo() { + Class1 c1 = new Class1(); + c1.bar(); + } +} + \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalaccesserror/IllegalAccessErrorExample.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalaccesserror/IllegalAccessErrorExample.java new file mode 100644 index 0000000000..2cc1abbb1d --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalaccesserror/IllegalAccessErrorExample.java @@ -0,0 +1,20 @@ +package com.baeldung.exceptions.illegalaccesserror; + +public class IllegalAccessErrorExample { + + interface Baeldung { + public default void foobar() { + System.out.println("This is a default method."); + } + } + + class Super { + private void foobar() { + System.out.println("SuperClass method foobar"); + } + } + + class MySubClass extends Super implements Baeldung { + + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalaccesserror/IllegalAccessErrorSolved.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalaccesserror/IllegalAccessErrorSolved.java new file mode 100644 index 0000000000..8f6a4c14a4 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/illegalaccesserror/IllegalAccessErrorSolved.java @@ -0,0 +1,20 @@ +package com.baeldung.exceptions.illegalaccesserror; + +public class IllegalAccessErrorSolved { + + interface BaeldungSolved { + public default void foobar() { + System.out.println("This is a default method."); + } + } + + class SuperSolved { + public void foobar() { + System.out.println("SuperClass method foobar"); + } + } + + class MySubClassSolved extends SuperSolved implements BaeldungSolved { + + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalaccesserror/IllegalAccessErrorExampleUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalaccesserror/IllegalAccessErrorExampleUnitTest.java new file mode 100644 index 0000000000..201e782229 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalaccesserror/IllegalAccessErrorExampleUnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.exceptions.illegalaccesserror; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class IllegalAccessErrorExampleUnitTest { + + @Test() + public void givenInterfaceDefaultMethOverriddenPrivateAccess_whenInvoked_thenIllegalAccessError() { + Assertions.assertThrows(IllegalAccessError.class, () -> { + new IllegalAccessErrorExample().new MySubClass().foobar(); + }); + } + + @Test() + public void givenClass1Class2_whenSameClassDefintion_thenNoIllegalAccessError() { + Assertions.assertDoesNotThrow(() -> { + new Class2().foo(); + }); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalaccesserror/IllegalAccessErrorSolvedUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalaccesserror/IllegalAccessErrorSolvedUnitTest.java new file mode 100644 index 0000000000..ad150334d4 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalaccesserror/IllegalAccessErrorSolvedUnitTest.java @@ -0,0 +1,14 @@ +package com.baeldung.exceptions.illegalaccesserror; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class IllegalAccessErrorSolvedUnitTest { + + @Test() + public void givenInterfaceDefaultMethOverriddenNonPrivateAccess_whenInvoked_thenNoIllegalAccessError() { + Assertions.assertDoesNotThrow(() -> { + new IllegalAccessErrorSolved().new MySubClassSolved().foobar(); + }); + } +} diff --git a/core-java-modules/core-java-io-4/src/main/java/com/baeldung/deserialization/vulnerabilities/BadThing.java b/core-java-modules/core-java-io-4/src/main/java/com/baeldung/deserialization/vulnerabilities/BadThing.java new file mode 100644 index 0000000000..ce13a9c372 --- /dev/null +++ b/core-java-modules/core-java-io-4/src/main/java/com/baeldung/deserialization/vulnerabilities/BadThing.java @@ -0,0 +1,28 @@ +package com.baeldung.deserialization.vulnerabilities; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.reflect.Method; + +public class BadThing implements Serializable { + private static final long serialVersionUID = 0L; + + Object looselyDefinedThing; + String methodName; + + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { + ois.defaultReadObject(); + try { + Method method = looselyDefinedThing.getClass().getMethod(methodName); + method.invoke(looselyDefinedThing); + } catch (Exception e) { + // handle error... + } + } + + private void writeObject(ObjectOutputStream oos) throws IOException { + oos.defaultWriteObject(); + } +} diff --git a/core-java-modules/core-java-io-4/src/main/java/com/baeldung/deserialization/vulnerabilities/MyCustomAttackObject.java b/core-java-modules/core-java-io-4/src/main/java/com/baeldung/deserialization/vulnerabilities/MyCustomAttackObject.java new file mode 100644 index 0000000000..9b4e2d4b76 --- /dev/null +++ b/core-java-modules/core-java-io-4/src/main/java/com/baeldung/deserialization/vulnerabilities/MyCustomAttackObject.java @@ -0,0 +1,14 @@ +package com.baeldung.deserialization.vulnerabilities; + +import java.io.IOException; +import java.io.Serializable; + +public class MyCustomAttackObject implements Serializable { + public static void methodThatTriggersAttack() { + try { + Runtime.getRuntime().exec("echo \"Oh, no! I've been hacked\""); + } catch (IOException e) { + // handle error... + } + } +} diff --git a/core-java-modules/core-java-io-4/src/test/java/com/baeldung/deserialization/vulnerabilities/BadThingUnitTest.java b/core-java-modules/core-java-io-4/src/test/java/com/baeldung/deserialization/vulnerabilities/BadThingUnitTest.java new file mode 100644 index 0000000000..ea2180d178 --- /dev/null +++ b/core-java-modules/core-java-io-4/src/test/java/com/baeldung/deserialization/vulnerabilities/BadThingUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.deserialization.vulnerabilities; + +import org.junit.Test; +import org.junit.jupiter.api.DisplayName; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +public class BadThingUnitTest { + + @Test + @DisplayName("When a BadThing object is deserialized, then code execution in MyCustomAttackObject is run.") + public void givenABadThingObject_whenItsDeserialized_thenExecutionIsRun() throws Exception { + BadThing bt = new BadThing(); + + bt.looselyDefinedThing = new MyCustomAttackObject(); + bt.methodName = "methodThatTriggersAttack"; + + byte[] serializedObject = serialize(bt); + + try (InputStream bis = new ByteArrayInputStream(serializedObject); + ObjectInputStream ois = new ObjectInputStream(bis)) { + + ois.readObject(); // malicious code is run + } + } + + private static byte[] serialize(Object object) throws Exception { + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos)) { + + oos.writeObject(object); + oos.flush(); + return bos.toByteArray(); + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-strings/pom.xml b/core-java-modules/core-java-strings/pom.xml index 137499de6b..aca0bb3346 100644 --- a/core-java-modules/core-java-strings/pom.xml +++ b/core-java-modules/core-java-strings/pom.xml @@ -57,6 +57,7 @@ 3.6.1 61.1 + 15 \ No newline at end of file diff --git a/core-java-modules/core-java-strings/src/main/java/com/baeldung/multiline/MultiLineString.java b/core-java-modules/core-java-strings/src/main/java/com/baeldung/multiline/MultiLineString.java index 987bc751cd..5d333799c4 100644 --- a/core-java-modules/core-java-strings/src/main/java/com/baeldung/multiline/MultiLineString.java +++ b/core-java-modules/core-java-strings/src/main/java/com/baeldung/multiline/MultiLineString.java @@ -64,4 +64,11 @@ public class MultiLineString { return new String(Files.readAllBytes(Paths.get("src/main/resources/stephenking.txt"))); } + public String textBlocks() { + return """ + Get busy living + or + get busy dying. + --Stephen King"""; + } } diff --git a/core-java-modules/core-java-strings/src/test/java/com/baeldung/multiline/MultiLineStringUnitTest.java b/core-java-modules/core-java-strings/src/test/java/com/baeldung/multiline/MultiLineStringUnitTest.java index 04d318c71b..66bc0a655b 100644 --- a/core-java-modules/core-java-strings/src/test/java/com/baeldung/multiline/MultiLineStringUnitTest.java +++ b/core-java-modules/core-java-strings/src/test/java/com/baeldung/multiline/MultiLineStringUnitTest.java @@ -16,6 +16,7 @@ public class MultiLineStringUnitTest { assertEquals(ms.stringJoin(), ms.stringBuilder()); assertEquals(ms.stringBuilder(), ms.guavaJoiner()); assertEquals(ms.guavaJoiner(), ms.loadFromFile()); + assertEquals(ms.loadFromFile(), ms.textBlocks()); } } diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index b4aae7949f..905fd30ee8 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -111,7 +111,6 @@ core-java-string-operations core-java-string-operations-2 core-java-string-operations-3 - core-java-strings core-java-sun core-java-regex pre-jpms diff --git a/lombok/pom.xml b/lombok/pom.xml index 334d1defc9..c5758ea8df 100644 --- a/lombok/pom.xml +++ b/lombok/pom.xml @@ -73,8 +73,6 @@ - - 1.18.10 1.0.0.Final diff --git a/maven-modules/maven-pom-types/effective-pom.xml b/maven-modules/maven-pom-types/effective-pom.xml new file mode 100644 index 0000000000..a2f8460809 --- /dev/null +++ b/maven-modules/maven-pom-types/effective-pom.xml @@ -0,0 +1,238 @@ + + + 4.0.0 + com.baeldung + maven-pom-types + 1.0-SNAPSHOT + + + + false + + central + Central Repository + https://repo.maven.apache.org/maven2 + + + + + + never + + + false + + central + Central Repository + https://repo.maven.apache.org/maven2 + + + + C:\Users\emicu\Desktop\tutorials\maven-modules\maven-pom-types\src\main\java + C:\Users\emicu\Desktop\tutorials\maven-modules\maven-pom-types\src\main\scripts + + C:\Users\emicu\Desktop\tutorials\maven-modules\maven-pom-types\src\test\java + + C:\Users\emicu\Desktop\tutorials\maven-modules\maven-pom-types\customTarget\classes + + C:\Users\emicu\Desktop\tutorials\maven-modules\maven-pom-types\customTarget\test-classes + + + + C:\Users\emicu\Desktop\tutorials\maven-modules\maven-pom-types\src\main\resources + + + + + C:\Users\emicu\Desktop\tutorials\maven-modules\maven-pom-types\src\test\resources + + + C:\Users\emicu\Desktop\tutorials\maven-modules\maven-pom-types\customTarget + simplestPOM-1.0-SNAPSHOT + + + + maven-antrun-plugin + 1.3 + + + maven-assembly-plugin + 2.2-beta-5 + + + maven-dependency-plugin + 2.8 + + + maven-release-plugin + 2.5.3 + + + + + + maven-clean-plugin + 2.5 + + + default-clean + clean + + clean + + + + + + maven-resources-plugin + 2.6 + + + default-testResources + process-test-resources + + testResources + + + + default-resources + process-resources + + resources + + + + + + maven-jar-plugin + 2.4 + + + default-jar + package + + jar + + + + + + maven-compiler-plugin + 3.1 + + + default-compile + compile + + compile + + + + default-testCompile + test-compile + + testCompile + + + + + + maven-surefire-plugin + 2.12.4 + + + default-test + test + + test + + + + + + maven-install-plugin + 2.4 + + + default-install + install + + install + + + + + + maven-deploy-plugin + 2.7 + + + default-deploy + deploy + + deploy + + + + + + maven-site-plugin + 3.3 + + + default-site + site + + site + + + + C:\Users\emicu\Desktop\tutorials\maven-modules\maven-pom-types\customTarget\site + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + + + + default-deploy + site-deploy + + deploy + + + + C:\Users\emicu\Desktop\tutorials\maven-modules\maven-pom-types\customTarget\site + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + + + + + C:\Users\emicu\Desktop\tutorials\maven-modules\maven-pom-types\customTarget\site + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + + + + + + C:\Users\emicu\Desktop\tutorials\maven-modules\maven-pom-types\customTarget\site + + + diff --git a/maven-modules/maven-pom-types/pom-4.0.0.xml b/maven-modules/maven-pom-types/pom-4.0.0.xml new file mode 100644 index 0000000000..24b15984af --- /dev/null +++ b/maven-modules/maven-pom-types/pom-4.0.0.xml @@ -0,0 +1,148 @@ + + + + + + + 4.0.0 + + + + central + Central Repository + https://repo.maven.apache.org/maven2 + default + + false + + + + + + + central + Central Repository + https://repo.maven.apache.org/maven2 + default + + false + + + never + + + + + + ${project.basedir}/target + ${project.build.directory}/classes + ${project.artifactId}-${project.version} + ${project.build.directory}/test-classes + + ${project.basedir}/src/main/java + ${project.basedir}/src/main/scripts + + ${project.basedir}/src/test/java + + + + ${project.basedir}/src/main/resources + + + + + ${project.basedir}/src/test/resources + + + + + + + + maven-antrun-plugin + 1.3 + + + maven-assembly-plugin + 2.2-beta-5 + + + maven-dependency-plugin + 2.8 + + + maven-release-plugin + 2.5.3 + + + + + + + ${project.build.directory}/site + + + + + + release-profile + + + + performRelease + true + + + + + + + true + maven-source-plugin + + + attach-sources + + jar-no-fork + + + + + + true + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + true + maven-deploy-plugin + + true + + + + + + + + + diff --git a/maven-modules/maven-pom-types/pom.xml b/maven-modules/maven-pom-types/pom.xml new file mode 100644 index 0000000000..98fbc828a0 --- /dev/null +++ b/maven-modules/maven-pom-types/pom.xml @@ -0,0 +1,9 @@ + + + 4.0.0 + com.baeldung + maven-pom-types + 1.0-SNAPSHOT + \ No newline at end of file diff --git a/maven-modules/maven-printing-plugins/README.md b/maven-modules/maven-printing-plugins/README.md new file mode 100644 index 0000000000..862c4bcdd1 --- /dev/null +++ b/maven-modules/maven-printing-plugins/README.md @@ -0,0 +1,7 @@ +## Maven Printing Plugins + +This module contains articles about printing from Maven plugins. + +### Relevant Articles + +- [How to Display a Message in Maven](https://www.baeldung.com/maven-print-message-during-execution) diff --git a/patterns/.gitignore b/patterns/.gitignore new file mode 100644 index 0000000000..1d420f6aaf --- /dev/null +++ b/patterns/.gitignore @@ -0,0 +1 @@ +/product-service/ diff --git a/patterns/enterprise-patterns/pom.xml b/patterns/enterprise-patterns/pom.xml new file mode 100644 index 0000000000..3637072c58 --- /dev/null +++ b/patterns/enterprise-patterns/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + com.baeldung + patterns + 1.0.0-SNAPSHOT + + + enterprise-patterns + pom + + + 3.7.4 + + + + + org.apache.camel.springboot + camel-spring-boot-starter + + + org.apache.camel.springboot + camel-activemq-starter + + + + + org.springframework.boot + spring-boot-starter-test + 2.2.2.RELEASE + + + org.apache.camel + camel-test-spring-junit5 + test + + + + + + + org.apache.camel.springboot + camel-spring-boot-dependencies + ${camel.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/patterns/enterprise-patterns/wire-tap/README.md b/patterns/enterprise-patterns/wire-tap/README.md new file mode 100644 index 0000000000..5f2aaf0d5a --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/README.md @@ -0,0 +1,34 @@ +# Wire Tap Pattern + +The application shows you how to use a Wire Tap to monitor, debug or troubleshoot messages flowing through the system, without permanently consuming them off, or making any changes to the expected message in the output channel. + +This example shows how to implement this with a simple Apache Camel application using Spring Boot and Apache ActiveMq. +For convenience, we are using in-memory activeMq. + + + +### Configuring and using the Connection Factory + +1. Create CamelContext. +2. Connect to embedded (or remote) ActiveMQ JMS broker. +3. Add JMS queue to CamelContext. +4. Load file orders (xml/csv) from src/data into the JMS queue. +5. Based on the extension of the incoming file message, route to the respective queues. +6. Test that the destination route is working. +7. Audit the received file (order) from the wire tap queue. + +### How to run the example: + + mvn spring-boot:run + + +The Wire Tap processor, by default, makes a shallow copy of the Camel Exchange instance. The copy of the exchange is sent to the endpoint specified in the wireTap statement. The body of the wire tapped message contains the same object as that in the original message which means any change to the internal state of that object during the wire tap route may also end up changing the main message’s body. + +To solve this, we need to create a deep copy of the object before passing it to the wire tap destination. Wire Tap EIP provides us with a mechanism to perform a “deep” copy of the message, by implementing the org.apache.camel.Processor class. This needs to be be called using onPrepare statement right after wireTap. +For more details, check out the AmqApplicationUnitTest.class. + +### Relevant Articles: + +- [Wire tap (Enterprise Integration Pattern)](https://drafts.baeldung.com/?p=103346&preview=true) +- [Intro to Apache camel](https://www.baeldung.com/apache-camel-intro) + diff --git a/patterns/enterprise-patterns/wire-tap/pom.xml b/patterns/enterprise-patterns/wire-tap/pom.xml new file mode 100644 index 0000000000..9169c4ac91 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + wire-tap + 1.0 + jar + + + enterprise-patterns + com.baeldung + 1.0.0-SNAPSHOT + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/patterns/enterprise-patterns/wire-tap/src/data/.camel/msg1.xml b/patterns/enterprise-patterns/wire-tap/src/data/.camel/msg1.xml new file mode 100644 index 0000000000..0a6fa64552 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/src/data/.camel/msg1.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/src/data/msg.xml b/patterns/enterprise-patterns/wire-tap/src/data/msg.xml new file mode 100644 index 0000000000..0a6fa64552 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/src/data/msg.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/src/main/java/com/baeldung/AmqApplication.java b/patterns/enterprise-patterns/wire-tap/src/main/java/com/baeldung/AmqApplication.java new file mode 100644 index 0000000000..eacef86d75 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/src/main/java/com/baeldung/AmqApplication.java @@ -0,0 +1,70 @@ +package com.baeldung; + +import org.apache.activemq.ActiveMQConnectionFactory; +import org.apache.camel.CamelContext; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.jms.JmsComponent; +import org.apache.camel.impl.DefaultCamelContext; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AmqApplication { + + public static void main(String[] args) throws Exception { + SpringApplication.run(AmqApplication.class, args); + + try (CamelContext context = new DefaultCamelContext()) { + ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory( + "vm://localhost?broker.persistent=false"); + connectionFactory.setTrustAllPackages(true); + context.addComponent("direct", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory)); + addRoute(context); + + try (ProducerTemplate template = context.createProducerTemplate()) { + context.start(); + + MyPayload payload = new MyPayload("One"); + template.sendBody("direct:source", payload); + Thread.sleep(10000); + } finally { + context.stop(); + } + } + } + + private static void addRoute(CamelContext context) throws Exception { + context.addRoutes(newExchangeRoute()); + } + + static RoutesBuilder traditionalWireTapRoute() { + return new RouteBuilder() { + public void configure() { + + from("direct:source").log("Main route: Send '${body}' to tap router").wireTap("direct:tap").delay(1000) + .log("Main route: Add 'two' to '${body}'").bean(MyBean.class, "addTwo").to("direct:destination") + .log("Main route: Output '${body}'"); + + from("direct:tap").log("Tap Wire route: received '${body}'") + .log("Tap Wire route: Add 'three' to '${body}'").bean(MyBean.class, "addThree") + .log("Tap Wire route: Output '${body}'"); + + from("direct:destination").log("Output at destination: '${body}'"); + } + }; + } + + static RoutesBuilder newExchangeRoute() throws Exception { + return new RouteBuilder() { + public void configure() throws Exception { + + from("direct:source").wireTap("direct:tap").onPrepare(new MyPayloadClonePrepare()).end().delay(1000); + + from("direct:tap").bean(MyBean.class, "addThree"); + } + }; + } + +} diff --git a/patterns/enterprise-patterns/wire-tap/src/main/java/com/baeldung/MyBean.java b/patterns/enterprise-patterns/wire-tap/src/main/java/com/baeldung/MyBean.java new file mode 100644 index 0000000000..62c45725b0 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/src/main/java/com/baeldung/MyBean.java @@ -0,0 +1,14 @@ +package com.baeldung; + +public class MyBean { + + public MyPayload addTwo(MyPayload body) { + body.setValue(body.getValue() + " and two"); + return body; + } + + public MyPayload addThree(MyPayload body) { + body.setValue(body.getValue() + " and three"); + return body; + } +} diff --git a/patterns/enterprise-patterns/wire-tap/src/main/java/com/baeldung/MyPayload.java b/patterns/enterprise-patterns/wire-tap/src/main/java/com/baeldung/MyPayload.java new file mode 100644 index 0000000000..84d6a22733 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/src/main/java/com/baeldung/MyPayload.java @@ -0,0 +1,31 @@ +package com.baeldung; + +import java.io.Serializable; + +public class MyPayload implements Serializable { + + private static final long serialVersionUID = 1L; + private String value; + + public MyPayload(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String toString() { + return value; + } + + public MyPayload deepClone() { + MyPayload myPayload = new MyPayload(value); + return myPayload; + } + +} diff --git a/patterns/enterprise-patterns/wire-tap/src/main/java/com/baeldung/MyPayloadClonePrepare.java b/patterns/enterprise-patterns/wire-tap/src/main/java/com/baeldung/MyPayloadClonePrepare.java new file mode 100644 index 0000000000..938194bc1a --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/src/main/java/com/baeldung/MyPayloadClonePrepare.java @@ -0,0 +1,15 @@ +package com.baeldung; + +import java.util.Date; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; + +public class MyPayloadClonePrepare implements Processor { + + public void process(Exchange exchange) throws Exception { + MyPayload myPayload = exchange.getIn().getBody(MyPayload.class); + exchange.getIn().setBody(myPayload.deepClone()); + exchange.getIn().setHeader("date", new Date()); + } +} diff --git a/patterns/enterprise-patterns/wire-tap/src/main/resources/application.properties b/patterns/enterprise-patterns/wire-tap/src/main/resources/application.properties new file mode 100644 index 0000000000..a74f494fa5 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/src/main/resources/application.properties @@ -0,0 +1,9 @@ +# to keep the JVM running +camel.springboot.main-run-controller = true + +#configure the URL of the remote ActiveMQ broker +#camel.component.activemq.broker-url=tcp://localhost:61616 +#spring.activemq.broker-url=tcp://localhost:61616 + +spring.activemq.in-memory=true +spring.activemq.pool.enabled=false \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/src/main/resources/log4j.properties b/patterns/enterprise-patterns/wire-tap/src/main/resources/log4j.properties new file mode 100644 index 0000000000..28aa51259a --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/src/main/resources/log4j.properties @@ -0,0 +1,16 @@ +# Root logger option +log4j.rootLogger=INFO, file, console + +log4j.logger.com.javarticles=INFO, file + +# Direct log messages to a log file +log4j.appender.file=org.apache.log4j.FileAppender +log4j.appender.file.File=javarticles.log +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d | %p | %F %L | %m%n + +# Direct log messages to stdout +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.Target=System.out +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%d{HH:mm}| %p | %F %L | %m%n \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-10-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-10-1-1-1 new file mode 100644 index 0000000000..25b70e3283 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-10-1-1-1 @@ -0,0 +1 @@ +Test Message: 8 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-11-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-11-1-1-1 new file mode 100644 index 0000000000..3948af158c --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-11-1-1-1 @@ -0,0 +1 @@ +Test Message: 9 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-2-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-2-1-1-1 new file mode 100644 index 0000000000..262fbf6de5 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-2-1-1-1 @@ -0,0 +1 @@ +Test Message: 0 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-3-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-3-1-1-1 new file mode 100644 index 0000000000..64a5c33134 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-3-1-1-1 @@ -0,0 +1 @@ +Test Message: 1 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-4-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-4-1-1-1 new file mode 100644 index 0000000000..de22e70d38 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-4-1-1-1 @@ -0,0 +1 @@ +Test Message: 2 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-5-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-5-1-1-1 new file mode 100644 index 0000000000..d400e1afeb --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-5-1-1-1 @@ -0,0 +1 @@ +Test Message: 3 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-6-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-6-1-1-1 new file mode 100644 index 0000000000..660c960fcb --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-6-1-1-1 @@ -0,0 +1 @@ +Test Message: 4 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-7-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-7-1-1-1 new file mode 100644 index 0000000000..c97f21578a --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-7-1-1-1 @@ -0,0 +1 @@ +Test Message: 5 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-8-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-8-1-1-1 new file mode 100644 index 0000000000..be38d662ff --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-8-1-1-1 @@ -0,0 +1 @@ +Test Message: 6 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-9-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-9-1-1-1 new file mode 100644 index 0000000000..518e4227fc --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-34209-1621429668568-4-9-1-1-1 @@ -0,0 +1 @@ +Test Message: 7 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-10-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-10-1-1-1 new file mode 100644 index 0000000000..25b70e3283 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-10-1-1-1 @@ -0,0 +1 @@ +Test Message: 8 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-11-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-11-1-1-1 new file mode 100644 index 0000000000..3948af158c --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-11-1-1-1 @@ -0,0 +1 @@ +Test Message: 9 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-2-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-2-1-1-1 new file mode 100644 index 0000000000..262fbf6de5 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-2-1-1-1 @@ -0,0 +1 @@ +Test Message: 0 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-3-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-3-1-1-1 new file mode 100644 index 0000000000..64a5c33134 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-3-1-1-1 @@ -0,0 +1 @@ +Test Message: 1 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-4-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-4-1-1-1 new file mode 100644 index 0000000000..de22e70d38 --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-4-1-1-1 @@ -0,0 +1 @@ +Test Message: 2 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-5-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-5-1-1-1 new file mode 100644 index 0000000000..d400e1afeb --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-5-1-1-1 @@ -0,0 +1 @@ +Test Message: 3 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-6-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-6-1-1-1 new file mode 100644 index 0000000000..660c960fcb --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-6-1-1-1 @@ -0,0 +1 @@ +Test Message: 4 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-7-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-7-1-1-1 new file mode 100644 index 0000000000..c97f21578a --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-7-1-1-1 @@ -0,0 +1 @@ +Test Message: 5 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-8-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-8-1-1-1 new file mode 100644 index 0000000000..be38d662ff --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-8-1-1-1 @@ -0,0 +1 @@ +Test Message: 6 \ No newline at end of file diff --git a/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-9-1-1-1 b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-9-1-1-1 new file mode 100644 index 0000000000..518e4227fc --- /dev/null +++ b/patterns/enterprise-patterns/wire-tap/test/ID-PRINHYLTPDL1209-46717-1621429562728-4-9-1-1-1 @@ -0,0 +1 @@ +Test Message: 7 \ No newline at end of file diff --git a/patterns/pom.xml b/patterns/pom.xml index 3bde26cae2..6e92ad2813 100644 --- a/patterns/pom.xml +++ b/patterns/pom.xml @@ -28,6 +28,7 @@ intercepting-filter solid clean-architecture + enterprise-patterns diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/returnmultipleentities/Channel.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/returnmultipleentities/Channel.java new file mode 100644 index 0000000000..7f60dd8de4 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/returnmultipleentities/Channel.java @@ -0,0 +1,43 @@ +package com.baeldung.jpa.returnmultipleentities; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.util.Objects; + +@Entity +public class Channel { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String code; + + private Long subscriptionId; + + public void setCode(String code) { + this.code = code; + } + + public String getCode() { + return code; + } + + public void setSubscriptionId(Long subscriptionId) { + this.subscriptionId = subscriptionId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Channel channel = (Channel) o; + return Objects.equals(id, channel.id) && Objects.equals(code, channel.code) && Objects.equals(subscriptionId, channel.subscriptionId); + } + + @Override + public int hashCode() { + return Objects.hash(id, code, subscriptionId); + } +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/returnmultipleentities/ReportRepository.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/returnmultipleentities/ReportRepository.java new file mode 100644 index 0000000000..ae574de7d5 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/returnmultipleentities/ReportRepository.java @@ -0,0 +1,23 @@ +package com.baeldung.jpa.returnmultipleentities; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.Query; +import java.util.List; + +public class ReportRepository { + private final EntityManagerFactory emf; + + public ReportRepository() { + emf = Persistence.createEntityManagerFactory("jpa-h2-return-multiple-entities"); + } + + public List find(String email) { + EntityManager entityManager = emf.createEntityManager(); + Query query = entityManager.createQuery("SELECT c, s, u FROM Channel c, Subscription s, User u WHERE c.subscriptionId = s.id AND s.id = u.subscriptionId AND u.email=:email"); + query.setParameter("email", email); + + return query.getResultList(); + } +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/returnmultipleentities/Subscription.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/returnmultipleentities/Subscription.java new file mode 100644 index 0000000000..91510ebb9f --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/returnmultipleentities/Subscription.java @@ -0,0 +1,41 @@ +package com.baeldung.jpa.returnmultipleentities; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.util.Objects; + +@Entity +public class Subscription { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String code; + + public void setCode(String code) { + this.code = code; + } + + public String getCode() { + return code; + } + + public Long getId() { + return id; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Subscription subscription = (Subscription) o; + return Objects.equals(id, subscription.id) && Objects.equals(code, subscription.code); + } + + @Override + public int hashCode() { + return Objects.hash(id, code); + } +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/returnmultipleentities/User.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/returnmultipleentities/User.java new file mode 100644 index 0000000000..35d546b57d --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/returnmultipleentities/User.java @@ -0,0 +1,29 @@ +package com.baeldung.jpa.returnmultipleentities; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class User { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String email; + + private Long subscriptionId; + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public void setSubscriptionId(Long subscriptionId) { + this.subscriptionId = subscriptionId; + } +} diff --git a/persistence-modules/java-jpa-3/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa-3/src/main/resources/META-INF/persistence.xml index bc41f35c01..666fc1500a 100644 --- a/persistence-modules/java-jpa-3/src/main/resources/META-INF/persistence.xml +++ b/persistence-modules/java-jpa-3/src/main/resources/META-INF/persistence.xml @@ -113,4 +113,24 @@ + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.returnmultipleentities.Channel + com.baeldung.jpa.returnmultipleentities.Subscription + com.baeldung.jpa.returnmultipleentities.User + com.baeldung.jpa.returnmultipleentities.ReportRepository + true + + + + + + + + + + + + + diff --git a/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/returnmultipleentities/ReturnMultipleEntitiesIntegrationTest.java b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/returnmultipleentities/ReturnMultipleEntitiesIntegrationTest.java new file mode 100644 index 0000000000..eb71060f22 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/returnmultipleentities/ReturnMultipleEntitiesIntegrationTest.java @@ -0,0 +1,84 @@ +package com.baeldung.jpa.returnmultipleentities; + +import org.junit.Before; +import org.junit.Test; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class ReturnMultipleEntitiesIntegrationTest { + private static EntityManagerFactory factory; + private static EntityManager entityManager; + private ReportRepository reportRepository; + + @Before + public void setup() { + factory = Persistence.createEntityManagerFactory("jpa-h2-return-multiple-entities"); + entityManager = factory.createEntityManager(); + reportRepository = new ReportRepository(); + populateH2DB(); + } + + @Test + public void whenQueryingForMultipleEntitiesInOneQuery_thenJPAReturnsMultipleEntitiesInCorrectOrder() { + List reportDetails = reportRepository.find("user1@gmail.com"); + + assertEquals(2, reportDetails.size()); + + for (Object[] reportDetail : reportDetails) { + assertEquals(3, reportDetail.length); + + Channel channel = (Channel) reportDetail[0]; + Subscription subscription = (Subscription) reportDetail[1]; + User user = (User) reportDetail[2]; + + assertEquals("single", subscription.getCode()); + assertEquals("user1@gmail.com", user.getEmail()); + if (!("eurosport".equals(channel.getCode()) || "hbo".equals(channel.getCode()))) { + fail(); + } + } + } + + private static void populateH2DB() { + entityManager.getTransaction().begin(); + + Subscription single = new Subscription(); + single.setCode("single"); + + Subscription family = new Subscription(); + family.setCode("family"); + + entityManager.persist(single); + entityManager.persist(family); + + Channel bbc = new Channel(); + bbc.setCode("bbc"); + bbc.setSubscriptionId(family.getId()); + + Channel eurosport = new Channel(); + eurosport.setCode("eurosport"); + eurosport.setSubscriptionId(single.getId()); + + Channel hbo = new Channel(); + hbo.setCode("hbo"); + hbo.setSubscriptionId(single.getId()); + + entityManager.persist(bbc); + entityManager.persist(eurosport); + entityManager.persist(hbo); + + User user1 = new User(); + user1.setEmail("user1@gmail.com"); + user1.setSubscriptionId(single.getId()); + + entityManager.persist(user1); + + entityManager.getTransaction().commit(); + } +} diff --git a/pom.xml b/pom.xml index d8bf527184..686db65e8f 100644 --- a/pom.xml +++ b/pom.xml @@ -1340,6 +1340,7 @@ core-java-modules/core-java-os core-java-modules/core-java-time-measurements core-java-modules/multimodulemavenproject + core-java-modules/core-java-strings @@ -1405,7 +1406,7 @@ 3.0.0 3.13.0 - 1.16.12 + 1.18.20 1.4.197 diff --git a/spring-boot-modules/spring-boot-admin/spring-boot-admin-client/pom.xml b/spring-boot-modules/spring-boot-admin/spring-boot-admin-client/pom.xml index a565b94c79..eca92ff3a5 100644 --- a/spring-boot-modules/spring-boot-admin/spring-boot-admin-client/pom.xml +++ b/spring-boot-modules/spring-boot-admin/spring-boot-admin-client/pom.xml @@ -60,7 +60,7 @@ - 2.4.0 + 2.4.1 2.0.4.RELEASE diff --git a/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/pom.xml b/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/pom.xml index b53394cdef..63bc286b45 100644 --- a/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/pom.xml +++ b/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/pom.xml @@ -76,8 +76,8 @@ - 2.4.0 - 2.4.0 + 2.4.1 + 2.4.1 1.5.7 2.0.4.RELEASE diff --git a/spring-boot-modules/spring-boot-annotations/pom.xml b/spring-boot-modules/spring-boot-annotations/pom.xml index b495c5de04..22572e7492 100644 --- a/spring-boot-modules/spring-boot-annotations/pom.xml +++ b/spring-boot-modules/spring-boot-annotations/pom.xml @@ -24,6 +24,10 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-autoconfigure + org.springframework.boot spring-boot-starter-data-jpa @@ -44,6 +48,11 @@ spring-boot-starter-test test + + org.mockito + mockito-inline + test + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/AdditionalWebConfiguration.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/AdditionalWebConfiguration.java new file mode 100644 index 0000000000..22b41a28e0 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/AdditionalWebConfiguration.java @@ -0,0 +1,9 @@ +package com.baeldung.annotations.conditional; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnWarDeployment; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnWarDeployment +public class AdditionalWebConfiguration { +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/ConditionalUtils.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/ConditionalUtils.java new file mode 100644 index 0000000000..7294d843d1 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/ConditionalUtils.java @@ -0,0 +1,20 @@ +package com.baeldung.annotations.conditional; + +import org.apache.commons.lang3.SystemUtils; +import org.springframework.boot.system.JavaVersion; + +public class ConditionalUtils { + + public static boolean isWindows() { + return SystemUtils.IS_OS_WINDOWS; + } + + public static boolean isJava8() { + return JavaVersion.getJavaVersion().equals(JavaVersion.EIGHT); + } + + public static boolean isJava9() { + return JavaVersion.getJavaVersion().equals(JavaVersion.NINE); + } + +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/DevEnvLoggingConfiguration.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/DevEnvLoggingConfiguration.java new file mode 100644 index 0000000000..39f1d568f0 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/DevEnvLoggingConfiguration.java @@ -0,0 +1,16 @@ +package com.baeldung.annotations.conditional; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; + +@Configuration +@Conditional(IsDevEnvCondition.class) +public class DevEnvLoggingConfiguration { + + @Bean + @Conditional(IsDevEnvCondition.class) + LoggingService loggingService() { + return new LoggingService(); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/IsDevEnvCondition.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/IsDevEnvCondition.java new file mode 100644 index 0000000000..768cd9f6ed --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/IsDevEnvCondition.java @@ -0,0 +1,13 @@ +package com.baeldung.annotations.conditional; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class IsDevEnvCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return "dev".equals(System.getProperty("env")); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/IsWindowsCondition.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/IsWindowsCondition.java new file mode 100644 index 0000000000..24aa4f4b1c --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/IsWindowsCondition.java @@ -0,0 +1,13 @@ +package com.baeldung.annotations.conditional; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class IsWindowsCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return ConditionalUtils.isWindows(); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8Condition.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8Condition.java new file mode 100644 index 0000000000..c5f5e16d52 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8Condition.java @@ -0,0 +1,13 @@ +package com.baeldung.annotations.conditional; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class Java8Condition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return ConditionalUtils.isJava8(); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8DependedService.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8DependedService.java new file mode 100644 index 0000000000..ab76dcd930 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8DependedService.java @@ -0,0 +1,9 @@ +package com.baeldung.annotations.conditional; + +import org.springframework.context.annotation.Conditional; +import org.springframework.stereotype.Service; + +@Service +@Conditional(Java8Condition.class) +public class Java8DependedService { +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8OrJava9.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8OrJava9.java new file mode 100644 index 0000000000..77c501ed08 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java8OrJava9.java @@ -0,0 +1,16 @@ +package com.baeldung.annotations.conditional; + +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; +import org.springframework.context.annotation.Conditional; + +public class Java8OrJava9 extends AnyNestedCondition { + Java8OrJava9() { + super(ConfigurationPhase.REGISTER_BEAN); + } + + @Conditional(Java8Condition.class) + static class Java8 { } + + @Conditional(Java9Condition.class) + static class Java9 { } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java9Condition.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java9Condition.java new file mode 100644 index 0000000000..2afa8b25a7 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/Java9Condition.java @@ -0,0 +1,13 @@ +package com.baeldung.annotations.conditional; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class Java9Condition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return ConditionalUtils.isJava9(); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/LoggingService.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/LoggingService.java new file mode 100644 index 0000000000..e104ec86e1 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/conditional/LoggingService.java @@ -0,0 +1,19 @@ +package com.baeldung.annotations.conditional; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.condition.ConditionalOnJava; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.system.JavaVersion; +import org.springframework.context.annotation.Conditional; +import org.springframework.stereotype.Service; + +@Service +@Conditional({IsDevEnvCondition.class, IsWindowsCondition.class, Java8Condition.class}) +@ConditionalOnProperty( + value = "logging.enabled", + havingValue = "true", + matchIfMissing = true) +@ConditionalOnExpression("${logging.enabled:true} and '${logging.level}'.equals('DEBUG')") +@ConditionalOnJava(JavaVersion.EIGHT) +public class LoggingService { +} diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/ConditionalTestConfiguration.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/ConditionalTestConfiguration.java new file mode 100644 index 0000000000..6b23433422 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/ConditionalTestConfiguration.java @@ -0,0 +1,10 @@ +package com.baeldung.annotations.conditional; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.ComponentScan; + +@TestConfiguration +@ComponentScan("com.baeldung.annotations.conditional") +public class ConditionalTestConfiguration { + +} diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/DevEnvLoggingConfigurationUnitTest.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/DevEnvLoggingConfigurationUnitTest.java new file mode 100644 index 0000000000..e7c1975127 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/DevEnvLoggingConfigurationUnitTest.java @@ -0,0 +1,52 @@ +package com.baeldung.annotations.conditional; + +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +public class DevEnvLoggingConfigurationUnitTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + + @Test + public void whenDevEnvEnabled_thenDevEnvLoggingConfigurationAndLoggingServiceShouldBeCreated() { + System.setProperty("env", "dev"); + + contextRunner + .withUserConfiguration(ConditionalTestConfiguration.class) + .run(context -> + Assertions.assertNotNull( + context.getBean(DevEnvLoggingConfiguration.class) + ) + ); + contextRunner + .withUserConfiguration(ConditionalTestConfiguration.class) + .run(context -> + Assertions.assertNotNull( + context.getBean(LoggingService.class) + ) + ); + } + + @Test + public void whenDevEnvNotEnabled_thenDevEnvLoggingConfigurationAndLoggingServiceShouldNotBeCreated() { + System.setProperty("env", "not-dev"); + + contextRunner + .withUserConfiguration(ConditionalTestConfiguration.class) + .run(context -> + Assertions.assertThrows(NoSuchBeanDefinitionException.class, () -> + context.getBean(DevEnvLoggingConfiguration.class) + ) + ); + contextRunner + .withUserConfiguration(ConditionalTestConfiguration.class) + .run(context -> + Assertions.assertThrows(NoSuchBeanDefinitionException.class, () -> + context.getBean(LoggingService.class) + ) + ); + } + +} diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/IsDevEnvConditionUnitTest.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/IsDevEnvConditionUnitTest.java new file mode 100644 index 0000000000..5302fc79dd --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/IsDevEnvConditionUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.annotations.conditional; + +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.mockito.Mockito; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class IsDevEnvConditionUnitTest { + + @Test + public void whenDevEnvEnabled_thenDevEnvConditionShouldPass() { + System.setProperty("env", "dev"); + + Assertions.assertTrue( + new IsDevEnvCondition().matches( + Mockito.mock(ConditionContext.class), Mockito.mock(AnnotatedTypeMetadata.class) + ) + ); + } + + @Test + public void whenDevEnvNotEnabled_thenDevEnvConditionShouldNotPass() { + System.setProperty("env", "not-dev"); + + Assertions.assertFalse( + new IsDevEnvCondition().matches( + Mockito.mock(ConditionContext.class), Mockito.mock(AnnotatedTypeMetadata.class) + ) + ); + } + +} diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/IsWindowsConditionUnitTest.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/IsWindowsConditionUnitTest.java new file mode 100644 index 0000000000..45ae65a0e2 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/IsWindowsConditionUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.annotations.conditional; + +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class IsWindowsConditionUnitTest { + + @Test + public void whenOnWindows_thenIsWindowsConditionShouldPass() { + try (MockedStatic theMock = Mockito.mockStatic(ConditionalUtils.class)) { + theMock.when(ConditionalUtils::isWindows) + .thenReturn(true); + Assertions.assertTrue( + new IsWindowsCondition().matches( + Mockito.mock(ConditionContext.class), Mockito.mock(AnnotatedTypeMetadata.class) + ) + ); + } + + } + + @Test + public void whenNotOnWindows_thenIsWindowsConditionShouldNotPass() { + try (MockedStatic theMock = Mockito.mockStatic(ConditionalUtils.class)) { + theMock.when(ConditionalUtils::isWindows) + .thenReturn(false); + Assertions.assertFalse( + new IsWindowsCondition().matches( + Mockito.mock(ConditionContext.class), Mockito.mock(AnnotatedTypeMetadata.class) + ) + ); + } + } + +} diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/Java8ConditionUnitTest.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/Java8ConditionUnitTest.java new file mode 100644 index 0000000000..0d1b1eded6 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/Java8ConditionUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.annotations.conditional; + +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class Java8ConditionUnitTest { + + @Test + public void whenOnJava8_thenJava8ConditionShouldPass() { + try (MockedStatic theMock = Mockito.mockStatic(ConditionalUtils.class)) { + theMock.when(ConditionalUtils::isJava8) + .thenReturn(true); + Assertions.assertTrue( + new Java8Condition().matches( + Mockito.mock(ConditionContext.class), Mockito.mock(AnnotatedTypeMetadata.class) + ) + ); + } + + } + + @Test + public void whenNotOnJava8_thenJava8ConditionShouldNotPass() { + try (MockedStatic theMock = Mockito.mockStatic(ConditionalUtils.class)) { + theMock.when(ConditionalUtils::isJava8) + .thenReturn(false); + Assertions.assertFalse( + new Java8Condition().matches( + Mockito.mock(ConditionContext.class), Mockito.mock(AnnotatedTypeMetadata.class) + ) + ); + } + } + +} diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/Java9ConditionUnitTest.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/Java9ConditionUnitTest.java new file mode 100644 index 0000000000..ce277e81fe --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/test/java/com/baeldung/annotations/conditional/Java9ConditionUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.annotations.conditional; + +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class Java9ConditionUnitTest { + + @Test + public void whenOnJava9_thenJava9ConditionShouldPass() { + try (MockedStatic theMock = Mockito.mockStatic(ConditionalUtils.class)) { + theMock.when(ConditionalUtils::isJava9) + .thenReturn(true); + Assertions.assertTrue( + new Java9Condition().matches( + Mockito.mock(ConditionContext.class), Mockito.mock(AnnotatedTypeMetadata.class) + ) + ); + } + + } + + @Test + public void whenNotOnJava9_thenJava9ConditionShouldNotPass() { + try (MockedStatic theMock = Mockito.mockStatic(ConditionalUtils.class)) { + theMock.when(ConditionalUtils::isJava9) + .thenReturn(false); + Assertions.assertFalse( + new Java9Condition().matches( + Mockito.mock(ConditionContext.class), Mockito.mock(AnnotatedTypeMetadata.class) + ) + ); + } + } + +} diff --git a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/WebController.java b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/WebController.java index 3bafe1f195..bbd96c8135 100644 --- a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/WebController.java +++ b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/WebController.java @@ -8,6 +8,8 @@ import java.security.Principal; import org.springframework.beans.factory.annotation.Autowired; +import javax.servlet.http.HttpServletRequest; + @Controller public class WebController { @@ -19,6 +21,12 @@ public class WebController { return "external"; } + @GetMapping("/logout") + public String logout(HttpServletRequest request) throws Exception { + request.logout(); + return "redirect:/"; + } + @GetMapping(path = "/customers") public String customers(Principal principal, Model model) { addCustomers(); diff --git a/spring-boot-modules/spring-boot-keycloak/src/main/resources/templates/customers.html b/spring-boot-modules/spring-boot-keycloak/src/main/resources/templates/customers.html index 5a060d31da..de2df93ef1 100644 --- a/spring-boot-modules/spring-boot-keycloak/src/main/resources/templates/customers.html +++ b/spring-boot-modules/spring-boot-keycloak/src/main/resources/templates/customers.html @@ -27,6 +27,7 @@ + Logout diff --git a/spring-core-5/pom.xml b/spring-core-5/pom.xml index 68229b80b8..1c2e80be44 100644 --- a/spring-core-5/pom.xml +++ b/spring-core-5/pom.xml @@ -19,6 +19,11 @@ spring-boot-starter ${spring-boot-starter.version} + + org.springframework.boot + spring-boot-starter-web + ${spring-boot-starter.version} + org.springframework.boot spring-boot-starter-test diff --git a/spring-core-5/src/main/java/com/baeldung/aliasfor/MyMapping.java b/spring-core-5/src/main/java/com/baeldung/aliasfor/MyMapping.java new file mode 100644 index 0000000000..05263297b5 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/aliasfor/MyMapping.java @@ -0,0 +1,29 @@ +package com.baeldung.aliasfor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.core.annotation.AliasFor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@RequestMapping +public @interface MyMapping { + + @AliasFor(annotation = RequestMapping.class, attribute = "method") + RequestMethod[] action() default {}; + + @AliasFor(annotation = RequestMapping.class, attribute = "path") + String[] value() default {}; + + @AliasFor(annotation = RequestMapping.class, attribute = "path") + String[] mapping() default {}; + + @AliasFor(annotation = RequestMapping.class, attribute = "path") + String[] route() default {}; + +} diff --git a/spring-core-5/src/main/java/com/baeldung/aliasfor/MyMappingController.java b/spring-core-5/src/main/java/com/baeldung/aliasfor/MyMappingController.java new file mode 100644 index 0000000000..c3dc2784f8 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/aliasfor/MyMappingController.java @@ -0,0 +1,13 @@ +package com.baeldung.aliasfor; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +public class MyMappingController { + + @MyMapping(action = RequestMethod.PATCH, route = "/test") + public void mappingMethod() { + } + +} diff --git a/spring-core-5/src/test/java/com/baeldung/aliasfor/AliasForUnitTest.java b/spring-core-5/src/test/java/com/baeldung/aliasfor/AliasForUnitTest.java new file mode 100644 index 0000000000..7beada3f35 --- /dev/null +++ b/spring-core-5/src/test/java/com/baeldung/aliasfor/AliasForUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.aliasfor; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Method; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = MyMappingController.class) +public class AliasForUnitTest { + + @Autowired + private ConfigurableApplicationContext context; + + Class controllerClass; + + @Before + public void setControllerBean() { + MyMappingController controllerBean = context.getBean(MyMappingController.class); + controllerClass = controllerBean.getClass(); + } + + @Test + public void givenComposedAnnotation_whenExplicitAlias_thenMetaAnnotationAttributeOverridden() { + + for (Method method : controllerClass.getMethods()) { + if (method.isAnnotationPresent(MyMapping.class)) { + MyMapping annotation = AnnotationUtils.findAnnotation(method, MyMapping.class); + RequestMapping metaAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class); + + assertEquals(RequestMethod.PATCH, annotation.action()[0]); + + assertEquals(0, metaAnnotation.method().length); + } + } + } + + @Test + public void givenComposedAnnotation_whenImplictAlias_thenAttributesEqual() { + for (Method method : controllerClass.getMethods()) { + if (method.isAnnotationPresent(MyMapping.class)) { + MyMapping annotationOnBean = AnnotationUtils.findAnnotation(method, MyMapping.class); + + assertEquals(annotationOnBean.mapping()[0], annotationOnBean.route()[0]); + assertEquals(annotationOnBean.value()[0], annotationOnBean.route()[0]); + } + } + } + +} diff --git a/spring-security-modules/spring-security-web-rest/pom.xml b/spring-security-modules/spring-security-web-rest/pom.xml index c3f2c09e9e..2fc50b2674 100644 --- a/spring-security-modules/spring-security-web-rest/pom.xml +++ b/spring-security-modules/spring-security-web-rest/pom.xml @@ -249,7 +249,7 @@ 2.9.0 - 2.9.2 + 3.0.0 1.6.1 diff --git a/spring-security-modules/spring-security-web-rest/src/main/java/com/baeldung/swagger2/SwaggerConfig.java b/spring-security-modules/spring-security-web-rest/src/main/java/com/baeldung/swagger2/SwaggerConfig.java index c8c4227ebf..08a5931f7d 100644 --- a/spring-security-modules/spring-security-web-rest/src/main/java/com/baeldung/swagger2/SwaggerConfig.java +++ b/spring-security-modules/spring-security-web-rest/src/main/java/com/baeldung/swagger2/SwaggerConfig.java @@ -6,12 +6,11 @@ import java.util.Collections; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.http.HttpMethod; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.builders.ResponseMessageBuilder; -import springfox.documentation.schema.ModelRef; +import springfox.documentation.builders.ResponseBuilder; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; @@ -30,13 +29,12 @@ public class SwaggerConfig { .build() .apiInfo(apiInfo()) .useDefaultResponseMessages(false) - .globalResponseMessage(RequestMethod.GET, newArrayList(new ResponseMessageBuilder().code(500) - .message("500 message") - .responseModel(new ModelRef("Error")) - .build(), - new ResponseMessageBuilder().code(403) - .message("Forbidden!!!!!") - .build())); + .globalResponses(HttpMethod.GET, newArrayList( + new ResponseBuilder().code("500") + .description("500 message").build(), + new ResponseBuilder().code("403") + .description("Forbidden!!!!!").build() + )); } private ApiInfo apiInfo() {