Merge branch 'BAEL-1447-v2' of https://github.com/eugenp/tutorials into BAEL-1447-v2
This commit is contained in:
commit
9101461a0a
|
@ -0,0 +1,3 @@
|
||||||
|
### Relevant Articles:
|
||||||
|
================================
|
||||||
|
- [Building a Microservice with Apache Meecrowave](http://www.baeldung.com/apache-meecrowave)
|
|
@ -46,7 +46,6 @@
|
||||||
- [Overview of Java Built-in Annotations](http://www.baeldung.com/java-default-annotations)
|
- [Overview of Java Built-in Annotations](http://www.baeldung.com/java-default-annotations)
|
||||||
- [Finding Min/Max in an Array with Java](http://www.baeldung.com/java-array-min-max)
|
- [Finding Min/Max in an Array with Java](http://www.baeldung.com/java-array-min-max)
|
||||||
- [Internationalization and Localization in Java 8](http://www.baeldung.com/java-8-localization)
|
- [Internationalization and Localization in Java 8](http://www.baeldung.com/java-8-localization)
|
||||||
- [Filtering Kotlin Collections](http://www.baeldung.com/kotlin-filter-collection)
|
|
||||||
- [How to Find an Element in a List with Java](http://www.baeldung.com/find-list-element-java)
|
- [How to Find an Element in a List with Java](http://www.baeldung.com/find-list-element-java)
|
||||||
- [Measure Elapsed Time in Java](http://www.baeldung.com/java-measure-elapsed-time)
|
- [Measure Elapsed Time in Java](http://www.baeldung.com/java-measure-elapsed-time)
|
||||||
- [Java Optional – orElse() vs orElseGet()](http://www.baeldung.com/java-optional-or-else-vs-or-else-get)
|
- [Java Optional – orElse() vs orElseGet()](http://www.baeldung.com/java-optional-or-else-vs-or-else-get)
|
||||||
|
@ -55,3 +54,5 @@
|
||||||
- [Java 8 Unsigned Arithmetic Support](http://www.baeldung.com/java-unsigned-arithmetic)
|
- [Java 8 Unsigned Arithmetic Support](http://www.baeldung.com/java-unsigned-arithmetic)
|
||||||
- [How to Get the Start and the End of a Day using Java](http://www.baeldung.com/java-day-start-end)
|
- [How to Get the Start and the End of a Day using Java](http://www.baeldung.com/java-day-start-end)
|
||||||
- [Generalized Target-Type Inference in Java](http://www.baeldung.com/java-generalized-target-type-inference)
|
- [Generalized Target-Type Inference in Java](http://www.baeldung.com/java-generalized-target-type-inference)
|
||||||
|
- [Image to Base64 String Conversion](http://www.baeldung.com/java-base64-image-string)
|
||||||
|
- [Calculate Age in Java](http://www.baeldung.com/java-get-age)
|
||||||
|
|
|
@ -99,6 +99,16 @@
|
||||||
<artifactId>joda-time</artifactId>
|
<artifactId>joda-time</artifactId>
|
||||||
<version>${joda.version}</version>
|
<version>${joda.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.aspectj</groupId>
|
||||||
|
<artifactId>aspectjrt</artifactId>
|
||||||
|
<version>${asspectj.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.aspectj</groupId>
|
||||||
|
<artifactId>aspectjweaver</artifactId>
|
||||||
|
<version>${asspectj.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -170,6 +180,7 @@
|
||||||
<joda.version>2.10</joda.version>
|
<joda.version>2.10</joda.version>
|
||||||
<!-- testing -->
|
<!-- testing -->
|
||||||
<assertj.version>3.6.1</assertj.version>
|
<assertj.version>3.6.1</assertj.version>
|
||||||
|
<asspectj.version>1.8.9</asspectj.version>
|
||||||
<avaitility.version>1.7.0</avaitility.version>
|
<avaitility.version>1.7.0</avaitility.version>
|
||||||
<jmh-core.version>1.19</jmh-core.version>
|
<jmh-core.version>1.19</jmh-core.version>
|
||||||
<jmh-generator.version>1.19</jmh-generator.version>
|
<jmh-generator.version>1.19</jmh-generator.version>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.baeldung.aspect;
|
||||||
|
|
||||||
|
public aspect ChangeCallsToCurrentTimeInMillisMethod {
|
||||||
|
long around():
|
||||||
|
call(public static native long java.lang.System.currentTimeMillis())
|
||||||
|
&& within(user.code.base.pckg.*) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package com.baeldung.util;
|
package com.baeldung.util;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
@ -9,6 +10,8 @@ import java.time.LocalTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.temporal.ChronoField;
|
import java.time.temporal.ChronoField;
|
||||||
|
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
import org.joda.time.DateTimeUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class CurrentDateTimeUnitTest {
|
public class CurrentDateTimeUnitTest {
|
||||||
|
@ -39,5 +42,4 @@ public class CurrentDateTimeUnitTest {
|
||||||
|
|
||||||
assertEquals(clock.instant().getEpochSecond(), now.getEpochSecond());
|
assertEquals(clock.instant().getEpochSecond(), now.getEpochSecond());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,3 +30,4 @@
|
||||||
- [How to TDD a List Implementation in Java](http://www.baeldung.com/java-test-driven-list)
|
- [How to TDD a List Implementation in Java](http://www.baeldung.com/java-test-driven-list)
|
||||||
- [How to Store Duplicate Keys in a Map in Java?](http://www.baeldung.com/java-map-duplicate-keys)
|
- [How to Store Duplicate Keys in a Map in Java?](http://www.baeldung.com/java-map-duplicate-keys)
|
||||||
- [Getting the Size of an Iterable in Java](http://www.baeldung.com/java-iterable-size)
|
- [Getting the Size of an Iterable in Java](http://www.baeldung.com/java-iterable-size)
|
||||||
|
- [Iterating Backward Through a List](http://www.baeldung.com/java-list-iterate-backwards)
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package com.baeldung.convertlisttomap;
|
package com.baeldung.convertlisttomap;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import org.apache.commons.collections4.MapUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.collections4.MapUtils;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
public class ConvertListToMapService {
|
public class ConvertListToMapService {
|
||||||
|
|
||||||
public Map<Integer, Animal> convertListBeforeJava8(List<Animal> list) {
|
public Map<Integer, Animal> convertListBeforeJava8(List<Animal> list) {
|
|
@ -1,13 +1,14 @@
|
||||||
package com.baeldung.convertlisttomap;
|
package com.baeldung.convertlisttomap;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import org.junit.Before;
|
||||||
import static org.hamcrest.Matchers.*;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.Before;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import org.junit.Test;
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
|
|
||||||
public class ConvertListToMapServiceUnitTest {
|
public class ConvertListToMapServiceUnitTest {
|
||||||
List<Animal> list;
|
List<Animal> list;
|
|
@ -1,15 +1,15 @@
|
||||||
package com.baeldung.convertlisttomap;
|
package com.baeldung.convertlisttomap;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import org.junit.Before;
|
||||||
import static org.hamcrest.Matchers.hasItem;
|
import org.junit.Test;
|
||||||
import static org.hamcrest.Matchers.hasSize;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.Before;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import org.junit.Test;
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
|
|
||||||
public class ConvertListWithDiplicatedIdToMapServiceUnitTest {
|
public class ConvertListWithDiplicatedIdToMapServiceUnitTest {
|
||||||
List<Animal> duplicatedIdList;
|
List<Animal> duplicatedIdList;
|
|
@ -28,3 +28,5 @@
|
||||||
- [Guide to Java NIO2 Asynchronous Channel APIs](http://www.baeldung.com/java-nio-2-async-channels)
|
- [Guide to Java NIO2 Asynchronous Channel APIs](http://www.baeldung.com/java-nio-2-async-channels)
|
||||||
- [A Guide to NIO2 Asynchronous Socket Channel](http://www.baeldung.com/java-nio2-async-socket-channel)
|
- [A Guide to NIO2 Asynchronous Socket Channel](http://www.baeldung.com/java-nio2-async-socket-channel)
|
||||||
- [Download a File From an URL in Java](http://www.baeldung.com/java-download-file)
|
- [Download a File From an URL in Java](http://www.baeldung.com/java-download-file)
|
||||||
|
- [Create a Symbolic Link with Java](http://www.baeldung.com/java-symlink)
|
||||||
|
- [Quick Use of FilenameFilter](http://www.baeldung.com/java-filename-filter)
|
||||||
|
|
|
@ -163,3 +163,8 @@
|
||||||
- [Console I/O in Java](http://www.baeldung.com/java-console-input-output)
|
- [Console I/O in Java](http://www.baeldung.com/java-console-input-output)
|
||||||
- [Guide to the java.util.Arrays Class](http://www.baeldung.com/java-util-arrays)
|
- [Guide to the java.util.Arrays Class](http://www.baeldung.com/java-util-arrays)
|
||||||
- [Create a Custom Exception in Java](http://www.baeldung.com/java-new-custom-exception)
|
- [Create a Custom Exception in Java](http://www.baeldung.com/java-new-custom-exception)
|
||||||
|
- [Guide to java.util.GregorianCalendar](http://www.baeldung.com/java-gregorian-calendar)
|
||||||
|
- [Java Global Exception Handler](http://www.baeldung.com/java-global-exception-handler)
|
||||||
|
- [Encrypting and Decrypting Files in Java](http://www.baeldung.com/java-cipher-input-output-stream)
|
||||||
|
- [How to Get the Size of an Object in Java](http://www.baeldung.com/java-size-of-object)
|
||||||
|
- [Exception Handling in Java](http://www.baeldung.com/java-exceptions)
|
||||||
|
|
|
@ -173,6 +173,19 @@
|
||||||
<artifactId>c3p0</artifactId>
|
<artifactId>c3p0</artifactId>
|
||||||
<version>${c3p0.version}</version>
|
<version>${c3p0.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- instrumentation -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.javassist</groupId>
|
||||||
|
<artifactId>javassist</artifactId>
|
||||||
|
<version>${javaassist.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sun</groupId>
|
||||||
|
<artifactId>tools</artifactId>
|
||||||
|
<version>1.8.0</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${java.home}/../lib/tools.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -400,6 +413,111 @@
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
|
<!-- java instrumentation profiles to build jars -->
|
||||||
|
<profile>
|
||||||
|
<id>buildAgentLoader</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<classifier>agentLoader</classifier>
|
||||||
|
<classesDirectory>target/classes</classesDirectory>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<addClasspath>true</addClasspath>
|
||||||
|
</manifest>
|
||||||
|
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||||
|
</archive>
|
||||||
|
|
||||||
|
<includes>
|
||||||
|
<include>com/baeldung/instrumentation/application/AgentLoader.class</include>
|
||||||
|
<include>com/baeldung/instrumentation/application/Launcher.class</include>
|
||||||
|
</includes>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>buildApplication</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<classifier>application</classifier>
|
||||||
|
<classesDirectory>target/classes</classesDirectory>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<addClasspath>true</addClasspath>
|
||||||
|
</manifest>
|
||||||
|
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||||
|
</archive>
|
||||||
|
|
||||||
|
<includes>
|
||||||
|
<include>com/baeldung/instrumentation/application/MyAtm.class</include>
|
||||||
|
<include>com/baeldung/instrumentation/application/MyAtmApplication.class</include>
|
||||||
|
<include>com/baeldung/instrumentation/application/Launcher.class</include>
|
||||||
|
</includes>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>buildAgent</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<classifier>agent</classifier>
|
||||||
|
<classesDirectory>target/classes</classesDirectory>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<addClasspath>true</addClasspath>
|
||||||
|
</manifest>
|
||||||
|
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||||
|
</archive>
|
||||||
|
|
||||||
|
<includes>
|
||||||
|
<include>com/baeldung/instrumentation/agent/AtmTransformer.class</include>
|
||||||
|
<include>com/baeldung/instrumentation/agent/MyInstrumentationAgent.class</include>
|
||||||
|
</includes>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -453,6 +571,8 @@
|
||||||
<!-- Mime Type Libraries -->
|
<!-- Mime Type Libraries -->
|
||||||
<tika.version>1.18</tika.version>
|
<tika.version>1.18</tika.version>
|
||||||
<jmime-magic.version>0.1.5</jmime-magic.version>
|
<jmime-magic.version>0.1.5</jmime-magic.version>
|
||||||
|
<!-- instrumentation -->
|
||||||
|
<javaassist.version>3.21.0-GA</javaassist.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class BasicConnectionPool implements ConnectionPool {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Connection getConnection() throws SQLException {
|
public Connection getConnection() throws SQLException {
|
||||||
if (connectionPool.size() == 0) {
|
if (connectionPool.isEmpty()) {
|
||||||
if (usedConnections.size() < MAX_POOL_SIZE) {
|
if (usedConnections.size() < MAX_POOL_SIZE) {
|
||||||
connectionPool.add(createConnection(url, user, password));
|
connectionPool.add(createConnection(url, user, password));
|
||||||
} else {
|
} else {
|
||||||
|
@ -76,9 +76,7 @@ public class BasicConnectionPool implements ConnectionPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() throws SQLException {
|
public void shutdown() throws SQLException {
|
||||||
for (Connection c : usedConnections) {
|
usedConnections.forEach(this::releaseConnection);
|
||||||
this.releaseConnection(c);
|
|
||||||
}
|
|
||||||
for (Connection c : connectionPool) {
|
for (Connection c : connectionPool) {
|
||||||
c.close();
|
c.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.baeldung.instrumentation.agent;
|
||||||
|
|
||||||
|
import javassist.CannotCompileException;
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import javassist.CtMethod;
|
||||||
|
import javassist.NotFoundException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
|
import java.lang.instrument.IllegalClassFormatException;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
|
|
||||||
|
public class AtmTransformer implements ClassFileTransformer {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(AtmTransformer.class);
|
||||||
|
|
||||||
|
private static final String WITHDRAW_MONEY_METHOD = "withdrawMoney";
|
||||||
|
|
||||||
|
/** The internal form class name of the class to transform */
|
||||||
|
private String targetClassName;
|
||||||
|
/** The class loader of the class we want to transform */
|
||||||
|
private ClassLoader targetClassLoader;
|
||||||
|
|
||||||
|
public AtmTransformer(String targetClassName, ClassLoader targetClassLoader) {
|
||||||
|
this.targetClassName = targetClassName;
|
||||||
|
this.targetClassLoader = targetClassLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
|
||||||
|
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
|
||||||
|
byte[] byteCode = classfileBuffer;
|
||||||
|
|
||||||
|
String finalTargetClassName = this.targetClassName.replaceAll("\\.", "/"); //replace . with /
|
||||||
|
if (!className.equals(finalTargetClassName)) {
|
||||||
|
return byteCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (className.equals(finalTargetClassName) && loader.equals(targetClassLoader)) {
|
||||||
|
LOGGER.info("[Agent] Transforming class MyAtm");
|
||||||
|
try {
|
||||||
|
ClassPool cp = ClassPool.getDefault();
|
||||||
|
CtClass cc = cp.get(targetClassName);
|
||||||
|
CtMethod m = cc.getDeclaredMethod(WITHDRAW_MONEY_METHOD);
|
||||||
|
m.addLocalVariable("startTime", CtClass.longType);
|
||||||
|
m.insertBefore("startTime = System.currentTimeMillis();");
|
||||||
|
|
||||||
|
StringBuilder endBlock = new StringBuilder();
|
||||||
|
|
||||||
|
m.addLocalVariable("endTime", CtClass.longType);
|
||||||
|
m.addLocalVariable("opTime", CtClass.longType);
|
||||||
|
endBlock.append("endTime = System.currentTimeMillis();");
|
||||||
|
endBlock.append("opTime = (endTime-startTime)/1000;");
|
||||||
|
|
||||||
|
endBlock.append("LOGGER.info(\"[Application] Withdrawal operation completed in:\" + opTime + \" seconds!\");");
|
||||||
|
|
||||||
|
m.insertAfter(endBlock.toString());
|
||||||
|
|
||||||
|
byteCode = cc.toBytecode();
|
||||||
|
cc.detach();
|
||||||
|
} catch (NotFoundException | CannotCompileException | IOException e) {
|
||||||
|
LOGGER.error("Exception", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return byteCode;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.baeldung.instrumentation.agent;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.lang.instrument.Instrumentation;
|
||||||
|
|
||||||
|
public class MyInstrumentationAgent {
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(MyInstrumentationAgent.class);
|
||||||
|
|
||||||
|
public static void premain(String agentArgs, Instrumentation inst) {
|
||||||
|
LOGGER.info("[Agent] In premain method");
|
||||||
|
|
||||||
|
String className = "com.baeldung.instrumentation.application.MyAtm";
|
||||||
|
transformClass(className,inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void agentmain(String agentArgs, Instrumentation inst) {
|
||||||
|
LOGGER.info("[Agent] In agentmain method");
|
||||||
|
|
||||||
|
String className = "com.baeldung.instrumentation.application.MyAtm";
|
||||||
|
transformClass(className,inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void transformClass(String className, Instrumentation instrumentation) {
|
||||||
|
Class<?> targetCls = null;
|
||||||
|
ClassLoader targetClassLoader = null;
|
||||||
|
// see if we can get the class using forName
|
||||||
|
try {
|
||||||
|
targetCls = Class.forName(className);
|
||||||
|
targetClassLoader = targetCls.getClassLoader();
|
||||||
|
transform(targetCls, targetClassLoader, instrumentation);
|
||||||
|
return;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LOGGER.error("Class [{}] not found with Class.forName");
|
||||||
|
}
|
||||||
|
// otherwise iterate all loaded classes and find what we want
|
||||||
|
for(Class<?> clazz: instrumentation.getAllLoadedClasses()) {
|
||||||
|
if(clazz.getName().equals(className)) {
|
||||||
|
targetCls = clazz;
|
||||||
|
targetClassLoader = targetCls.getClassLoader();
|
||||||
|
transform(targetCls, targetClassLoader, instrumentation);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Failed to find class [" + className + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void transform(Class<?> clazz, ClassLoader classLoader, Instrumentation instrumentation) {
|
||||||
|
AtmTransformer dt = new AtmTransformer(clazz.getName(), classLoader);
|
||||||
|
instrumentation.addTransformer(dt, true);
|
||||||
|
try {
|
||||||
|
instrumentation.retransformClasses(clazz);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new RuntimeException("Transform failed for class: [" + clazz.getName() + "]", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.baeldung.instrumentation.application;
|
||||||
|
|
||||||
|
import com.sun.tools.attach.VirtualMachine;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by adi on 6/10/18.
|
||||||
|
*/
|
||||||
|
public class AgentLoader {
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(AgentLoader.class);
|
||||||
|
|
||||||
|
public static void run(String[] args) {
|
||||||
|
String agentFilePath = "/home/adi/Desktop/agent-1.0.0-jar-with-dependencies.jar";
|
||||||
|
String applicationName = "MyAtmApplication";
|
||||||
|
|
||||||
|
//iterate all jvms and get the first one that matches our application name
|
||||||
|
Optional<String> jvmProcessOpt = Optional.ofNullable(VirtualMachine.list()
|
||||||
|
.stream()
|
||||||
|
.filter(jvm -> {
|
||||||
|
LOGGER.info("jvm:{}", jvm.displayName());
|
||||||
|
return jvm.displayName().contains(applicationName);
|
||||||
|
})
|
||||||
|
.findFirst().get().id());
|
||||||
|
|
||||||
|
if(!jvmProcessOpt.isPresent()) {
|
||||||
|
LOGGER.error("Target Application not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File agentFile = new File(agentFilePath);
|
||||||
|
try {
|
||||||
|
String jvmPid = jvmProcessOpt.get();
|
||||||
|
LOGGER.info("Attaching to target JVM with PID: " + jvmPid);
|
||||||
|
VirtualMachine jvm = VirtualMachine.attach(jvmPid);
|
||||||
|
jvm.loadAgent(agentFile.getAbsolutePath());
|
||||||
|
jvm.detach();
|
||||||
|
LOGGER.info("Attached to target JVM and loaded Java agent successfully");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung.instrumentation.application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by adi on 6/14/18.
|
||||||
|
*/
|
||||||
|
public class Launcher {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
if(args[0].equals("StartMyAtmApplication")) {
|
||||||
|
new MyAtmApplication().run(args);
|
||||||
|
} else if(args[0].equals("LoadAgent")) {
|
||||||
|
new AgentLoader().run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.instrumentation.application;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by adi on 6/11/18.
|
||||||
|
*/
|
||||||
|
public class MyAtm {
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(MyAtm.class);
|
||||||
|
|
||||||
|
private static final int account = 10;
|
||||||
|
|
||||||
|
public static void withdrawMoney(int amount) throws InterruptedException {
|
||||||
|
Thread.sleep(2000l); //processing going on here
|
||||||
|
LOGGER.info("[Application] Successful Withdrawal of [{}] units!", amount);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.instrumentation.application;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class MyAtmApplication {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(MyAtmApplication.class);
|
||||||
|
|
||||||
|
public static void run(String[] args) throws Exception {
|
||||||
|
LOGGER.info("[Application] Starting ATM application");
|
||||||
|
MyAtm.withdrawMoney(Integer.parseInt(args[2]));
|
||||||
|
|
||||||
|
Thread.sleep(Long.valueOf(args[1]));
|
||||||
|
|
||||||
|
MyAtm.withdrawMoney(Integer.parseInt(args[3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
Agent-Class: com.baeldung.instrumentation.agent.MyInstrumentationAgent
|
||||||
|
Can-Redefine-Classes: true
|
||||||
|
Can-Retransform-Classes: true
|
||||||
|
Premain-Class: com.baeldung.instrumentation.agent.MyInstrumentationAgent
|
||||||
|
Main-Class: com.baeldung.instrumentation.application.Launcher
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Configuration status="WARN">
|
||||||
|
<Appenders>
|
||||||
|
<Console name="Console" target="SYSTEM_OUT">
|
||||||
|
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level - %msg%n"/>
|
||||||
|
</Console>
|
||||||
|
</Appenders>
|
||||||
|
<Loggers>
|
||||||
|
<Root level="debug">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
</Root>
|
||||||
|
</Loggers>
|
||||||
|
</Configuration>
|
|
@ -34,3 +34,5 @@
|
||||||
- [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security)
|
- [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security)
|
||||||
- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor)
|
- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor)
|
||||||
- [Working with Enums in Kotlin](http://www.baeldung.com/kotlin-enum)
|
- [Working with Enums in Kotlin](http://www.baeldung.com/kotlin-enum)
|
||||||
|
- [Create a Java and Kotlin Project with Maven](http://www.baeldung.com/kotlin-maven-java-project)
|
||||||
|
- [Reflection with Kotlin](http://www.baeldung.com/kotlin-reflection)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
### Relevant Articles:
|
||||||
|
- [Introduction to GWT](http://www.baeldung.com/gwt)
|
|
@ -85,7 +85,7 @@
|
||||||
- [Implementing a FTP-Client in Java](http://www.baeldung.com/java-ftp-client)
|
- [Implementing a FTP-Client in Java](http://www.baeldung.com/java-ftp-client)
|
||||||
- [Convert String to Date in Java](http://www.baeldung.com/java-string-to-date)
|
- [Convert String to Date in Java](http://www.baeldung.com/java-string-to-date)
|
||||||
- [Histograms with Apache Commons Frequency](http://www.baeldung.com/apache-commons-frequency)
|
- [Histograms with Apache Commons Frequency](http://www.baeldung.com/apache-commons-frequency)
|
||||||
|
- [Guide to Resilience4j](http://www.baeldung.com/resilience4j)
|
||||||
|
|
||||||
The libraries module contains examples related to small libraries that are relatively easy to use and does not require any separate module of its own.
|
The libraries module contains examples related to small libraries that are relatively easy to use and does not require any separate module of its own.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
###Relevant Articles:
|
### Relevant Articles:
|
||||||
- [A Guide to the Front Controller Pattern in Java](http://www.baeldung.com/java-front-controller-pattern)
|
- [A Guide to the Front Controller Pattern in Java](http://www.baeldung.com/java-front-controller-pattern)
|
||||||
- [Introduction to Intercepting Filter Pattern in Java](http://www.baeldung.com/intercepting-filter-pattern-in-java)
|
- [Introduction to Intercepting Filter Pattern in Java](http://www.baeldung.com/intercepting-filter-pattern-in-java)
|
||||||
- [Implementing the Template Method Pattern in Java](http://www.baeldung.com/java-template-method-pattern)
|
- [Implementing the Template Method Pattern in Java](http://www.baeldung.com/java-template-method-pattern)
|
||||||
|
|
|
@ -10,3 +10,4 @@
|
||||||
- [Composite Design Pattern in Java](http://www.baeldung.com/java-composite-pattern)
|
- [Composite Design Pattern in Java](http://www.baeldung.com/java-composite-pattern)
|
||||||
- [Visitor Design Pattern in Java](http://www.baeldung.com/java-visitor-pattern)
|
- [Visitor Design Pattern in Java](http://www.baeldung.com/java-visitor-pattern)
|
||||||
- [The DAO Pattern in Java](http://www.baeldung.com/java-dao-pattern)
|
- [The DAO Pattern in Java](http://www.baeldung.com/java-dao-pattern)
|
||||||
|
- [Interpreter Design Pattern in Java](http://www.baeldung.com/java-interpreter-pattern)
|
||||||
|
|
5
pom.xml
5
pom.xml
|
@ -422,6 +422,7 @@
|
||||||
<module>spring-boot-persistence</module>
|
<module>spring-boot-persistence</module>
|
||||||
<module>spring-boot-security</module>
|
<module>spring-boot-security</module>
|
||||||
<module>spring-boot-mvc</module>
|
<module>spring-boot-mvc</module>
|
||||||
|
<module>spring-boot-vue</module>
|
||||||
<module>spring-boot-logging-log4j2</module>
|
<module>spring-boot-logging-log4j2</module>
|
||||||
<module>spring-cloud-data-flow</module>
|
<module>spring-cloud-data-flow</module>
|
||||||
<module>spring-cloud</module>
|
<module>spring-cloud</module>
|
||||||
|
@ -433,6 +434,7 @@
|
||||||
<module>spring-data-couchbase-2</module>
|
<module>spring-data-couchbase-2</module>
|
||||||
<module>persistence-modules/spring-data-dynamodb</module>
|
<module>persistence-modules/spring-data-dynamodb</module>
|
||||||
<module>spring-data-elasticsearch</module>
|
<module>spring-data-elasticsearch</module>
|
||||||
|
<module>spring-data-jpa</module>
|
||||||
<module>spring-data-keyvalue</module>
|
<module>spring-data-keyvalue</module>
|
||||||
<module>spring-data-mongodb</module>
|
<module>spring-data-mongodb</module>
|
||||||
<module>persistence-modules/spring-data-neo4j</module>
|
<module>persistence-modules/spring-data-neo4j</module>
|
||||||
|
@ -1222,4 +1224,5 @@
|
||||||
<maven-pmd-plugin.version>3.8</maven-pmd-plugin.version>
|
<maven-pmd-plugin.version>3.8</maven-pmd-plugin.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
||||||
|
|
|
@ -15,3 +15,4 @@
|
||||||
- [RxJava Maybe](http://www.baeldung.com/rxjava-maybe)
|
- [RxJava Maybe](http://www.baeldung.com/rxjava-maybe)
|
||||||
- [Introduction to RxRelay for RxJava](http://www.baeldung.com/rx-relay)
|
- [Introduction to RxRelay for RxJava](http://www.baeldung.com/rx-relay)
|
||||||
- [Filtering Observables in RxJava](http://www.baeldung.com/rxjava-filtering)
|
- [Filtering Observables in RxJava](http://www.baeldung.com/rxjava-filtering)
|
||||||
|
- [RxJava One Observable, Multiple Subscribers](http://www.baeldung.com/rxjava-multiple-subscribers-observable)
|
||||||
|
|
|
@ -11,4 +11,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||||
- [Exploring the Spring 5 MVC URL Matching Improvements](http://www.baeldung.com/spring-5-mvc-url-matching)
|
- [Exploring the Spring 5 MVC URL Matching Improvements](http://www.baeldung.com/spring-5-mvc-url-matching)
|
||||||
- [Spring Security 5 for Reactive Applications](http://www.baeldung.com/spring-security-5-reactive)
|
- [Spring Security 5 for Reactive Applications](http://www.baeldung.com/spring-security-5-reactive)
|
||||||
- [Reactive WebSockets with Spring 5](http://www.baeldung.com/spring-5-reactive-websockets)
|
- [Reactive WebSockets with Spring 5](http://www.baeldung.com/spring-5-reactive-websockets)
|
||||||
- [Spring Webflux Filters](http://www.baeldung.com/spring-webflux-filters)
|
- [Spring Webflux Filters](http://www.baeldung.com/spring-webflux-filters)
|
||||||
|
- [How to Set a Header on a Response with Spring 5](http://www.baeldung.com/spring-response-header)
|
||||||
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip
|
|
|
@ -1,225 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
# Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
# or more contributor license agreements. See the NOTICE file
|
|
||||||
# distributed with this work for additional information
|
|
||||||
# regarding copyright ownership. The ASF licenses this file
|
|
||||||
# to you under the Apache License, Version 2.0 (the
|
|
||||||
# "License"); you may not use this file except in compliance
|
|
||||||
# with the License. You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing,
|
|
||||||
# software distributed under the License is distributed on an
|
|
||||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
# KIND, either express or implied. See the License for the
|
|
||||||
# specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
# Maven2 Start Up Batch script
|
|
||||||
#
|
|
||||||
# Required ENV vars:
|
|
||||||
# ------------------
|
|
||||||
# JAVA_HOME - location of a JDK home dir
|
|
||||||
#
|
|
||||||
# Optional ENV vars
|
|
||||||
# -----------------
|
|
||||||
# M2_HOME - location of maven2's installed home dir
|
|
||||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
|
||||||
# e.g. to debug Maven itself, use
|
|
||||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
|
||||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
|
||||||
|
|
||||||
if [ -f /etc/mavenrc ] ; then
|
|
||||||
. /etc/mavenrc
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "$HOME/.mavenrc" ] ; then
|
|
||||||
. "$HOME/.mavenrc"
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
# OS specific support. $var _must_ be set to either true or false.
|
|
||||||
cygwin=false;
|
|
||||||
darwin=false;
|
|
||||||
mingw=false
|
|
||||||
case "`uname`" in
|
|
||||||
CYGWIN*) cygwin=true ;;
|
|
||||||
MINGW*) mingw=true;;
|
|
||||||
Darwin*) darwin=true
|
|
||||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
|
||||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
|
||||||
if [ -z "$JAVA_HOME" ]; then
|
|
||||||
if [ -x "/usr/libexec/java_home" ]; then
|
|
||||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
|
||||||
else
|
|
||||||
export JAVA_HOME="/Library/Java/Home"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ] ; then
|
|
||||||
if [ -r /etc/gentoo-release ] ; then
|
|
||||||
JAVA_HOME=`java-config --jre-home`
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$M2_HOME" ] ; then
|
|
||||||
## resolve links - $0 may be a link to maven's home
|
|
||||||
PRG="$0"
|
|
||||||
|
|
||||||
# need this for relative symlinks
|
|
||||||
while [ -h "$PRG" ] ; do
|
|
||||||
ls=`ls -ld "$PRG"`
|
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
|
||||||
PRG="$link"
|
|
||||||
else
|
|
||||||
PRG="`dirname "$PRG"`/$link"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
saveddir=`pwd`
|
|
||||||
|
|
||||||
M2_HOME=`dirname "$PRG"`/..
|
|
||||||
|
|
||||||
# make it fully qualified
|
|
||||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
|
||||||
|
|
||||||
cd "$saveddir"
|
|
||||||
# echo Using m2 at $M2_HOME
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
|
||||||
if $cygwin ; then
|
|
||||||
[ -n "$M2_HOME" ] &&
|
|
||||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
|
||||||
[ -n "$JAVA_HOME" ] &&
|
|
||||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
|
||||||
[ -n "$CLASSPATH" ] &&
|
|
||||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Migwn, ensure paths are in UNIX format before anything is touched
|
|
||||||
if $mingw ; then
|
|
||||||
[ -n "$M2_HOME" ] &&
|
|
||||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
|
||||||
[ -n "$JAVA_HOME" ] &&
|
|
||||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
|
||||||
# TODO classpath?
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ]; then
|
|
||||||
javaExecutable="`which javac`"
|
|
||||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
|
||||||
# readlink(1) is not available as standard on Solaris 10.
|
|
||||||
readLink=`which readlink`
|
|
||||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
|
||||||
if $darwin ; then
|
|
||||||
javaHome="`dirname \"$javaExecutable\"`"
|
|
||||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
|
||||||
else
|
|
||||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
|
||||||
fi
|
|
||||||
javaHome="`dirname \"$javaExecutable\"`"
|
|
||||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
|
||||||
JAVA_HOME="$javaHome"
|
|
||||||
export JAVA_HOME
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$JAVACMD" ] ; then
|
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
|
||||||
else
|
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
JAVACMD="`which java`"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
|
||||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
|
||||||
echo " We cannot execute $JAVACMD" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ] ; then
|
|
||||||
echo "Warning: JAVA_HOME environment variable is not set."
|
|
||||||
fi
|
|
||||||
|
|
||||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
|
||||||
|
|
||||||
# traverses directory structure from process work directory to filesystem root
|
|
||||||
# first directory with .mvn subdirectory is considered project base directory
|
|
||||||
find_maven_basedir() {
|
|
||||||
|
|
||||||
if [ -z "$1" ]
|
|
||||||
then
|
|
||||||
echo "Path not specified to find_maven_basedir"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
basedir="$1"
|
|
||||||
wdir="$1"
|
|
||||||
while [ "$wdir" != '/' ] ; do
|
|
||||||
if [ -d "$wdir"/.mvn ] ; then
|
|
||||||
basedir=$wdir
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
|
||||||
if [ -d "${wdir}" ]; then
|
|
||||||
wdir=`cd "$wdir/.."; pwd`
|
|
||||||
fi
|
|
||||||
# end of workaround
|
|
||||||
done
|
|
||||||
echo "${basedir}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# concatenates all lines of a file
|
|
||||||
concat_lines() {
|
|
||||||
if [ -f "$1" ]; then
|
|
||||||
echo "$(tr -s '\n' ' ' < "$1")"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
|
||||||
if [ -z "$BASE_DIR" ]; then
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
|
|
||||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
|
||||||
echo $MAVEN_PROJECTBASEDIR
|
|
||||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
|
||||||
if $cygwin; then
|
|
||||||
[ -n "$M2_HOME" ] &&
|
|
||||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
|
||||||
[ -n "$JAVA_HOME" ] &&
|
|
||||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
|
||||||
[ -n "$CLASSPATH" ] &&
|
|
||||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
|
||||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
|
||||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
|
||||||
|
|
||||||
exec "$JAVACMD" \
|
|
||||||
$MAVEN_OPTS \
|
|
||||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
|
||||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
|
||||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
|
|
@ -1,143 +0,0 @@
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
@REM or more contributor license agreements. See the NOTICE file
|
|
||||||
@REM distributed with this work for additional information
|
|
||||||
@REM regarding copyright ownership. The ASF licenses this file
|
|
||||||
@REM to you under the Apache License, Version 2.0 (the
|
|
||||||
@REM "License"); you may not use this file except in compliance
|
|
||||||
@REM with the License. You may obtain a copy of the License at
|
|
||||||
@REM
|
|
||||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
@REM
|
|
||||||
@REM Unless required by applicable law or agreed to in writing,
|
|
||||||
@REM software distributed under the License is distributed on an
|
|
||||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
@REM KIND, either express or implied. See the License for the
|
|
||||||
@REM specific language governing permissions and limitations
|
|
||||||
@REM under the License.
|
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
@REM Maven2 Start Up Batch script
|
|
||||||
@REM
|
|
||||||
@REM Required ENV vars:
|
|
||||||
@REM JAVA_HOME - location of a JDK home dir
|
|
||||||
@REM
|
|
||||||
@REM Optional ENV vars
|
|
||||||
@REM M2_HOME - location of maven2's installed home dir
|
|
||||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
|
||||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
|
||||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
|
||||||
@REM e.g. to debug Maven itself, use
|
|
||||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
|
||||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
|
||||||
@echo off
|
|
||||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
|
||||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
|
||||||
|
|
||||||
@REM set %HOME% to equivalent of $HOME
|
|
||||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
|
||||||
|
|
||||||
@REM Execute a user defined script before this one
|
|
||||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
|
||||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
|
||||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
|
||||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
|
||||||
:skipRcPre
|
|
||||||
|
|
||||||
@setlocal
|
|
||||||
|
|
||||||
set ERROR_CODE=0
|
|
||||||
|
|
||||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
|
||||||
@setlocal
|
|
||||||
|
|
||||||
@REM ==== START VALIDATION ====
|
|
||||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo Error: JAVA_HOME not found in your environment. >&2
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
|
||||||
echo location of your Java installation. >&2
|
|
||||||
echo.
|
|
||||||
goto error
|
|
||||||
|
|
||||||
:OkJHome
|
|
||||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
|
||||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
|
||||||
echo location of your Java installation. >&2
|
|
||||||
echo.
|
|
||||||
goto error
|
|
||||||
|
|
||||||
@REM ==== END VALIDATION ====
|
|
||||||
|
|
||||||
:init
|
|
||||||
|
|
||||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
|
||||||
@REM Fallback to current working directory if not found.
|
|
||||||
|
|
||||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
|
||||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
|
||||||
|
|
||||||
set EXEC_DIR=%CD%
|
|
||||||
set WDIR=%EXEC_DIR%
|
|
||||||
:findBaseDir
|
|
||||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
|
||||||
cd ..
|
|
||||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
|
||||||
set WDIR=%CD%
|
|
||||||
goto findBaseDir
|
|
||||||
|
|
||||||
:baseDirFound
|
|
||||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
|
||||||
cd "%EXEC_DIR%"
|
|
||||||
goto endDetectBaseDir
|
|
||||||
|
|
||||||
:baseDirNotFound
|
|
||||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
|
||||||
cd "%EXEC_DIR%"
|
|
||||||
|
|
||||||
:endDetectBaseDir
|
|
||||||
|
|
||||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
|
||||||
|
|
||||||
@setlocal EnableExtensions EnableDelayedExpansion
|
|
||||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
|
||||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
|
||||||
|
|
||||||
:endReadAdditionalConfig
|
|
||||||
|
|
||||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
|
||||||
|
|
||||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
|
||||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
|
||||||
|
|
||||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
|
||||||
if ERRORLEVEL 1 goto error
|
|
||||||
goto end
|
|
||||||
|
|
||||||
:error
|
|
||||||
set ERROR_CODE=1
|
|
||||||
|
|
||||||
:end
|
|
||||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
|
||||||
|
|
||||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
|
||||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
|
||||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
|
||||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
|
||||||
:skipRcPost
|
|
||||||
|
|
||||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
|
||||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
|
||||||
|
|
||||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
|
||||||
|
|
||||||
exit /B %ERROR_CODE%
|
|
|
@ -1,107 +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>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>spring-boot-compare-embedded</artifactId>
|
|
||||||
<version>0.0.1</version>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
<name>spring-boot-compare-embedded</name>
|
|
||||||
<description>This is a simple application with used to compare embedded servlet containers.</description>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-boot-2</artifactId>
|
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
|
||||||
<relativePath>../parent-boot-2</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- tomcat -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- jetty -->
|
|
||||||
<!-- <dependency> -->
|
|
||||||
<!-- <groupId>org.springframework.boot</groupId> -->
|
|
||||||
<!-- <artifactId>spring-boot-starter-web</artifactId> -->
|
|
||||||
<!-- <exclusions> -->
|
|
||||||
<!-- <exclusion> -->
|
|
||||||
<!-- <groupId>org.springframework.boot</groupId> -->
|
|
||||||
<!-- <artifactId>spring-boot-starter-tomcat</artifactId> -->
|
|
||||||
<!-- </exclusion> -->
|
|
||||||
<!-- </exclusions> -->
|
|
||||||
<!-- </dependency> -->
|
|
||||||
<!-- <dependency> -->
|
|
||||||
<!-- <groupId>org.springframework.boot</groupId> -->
|
|
||||||
<!-- <artifactId>spring-boot-starter-jetty</artifactId> -->
|
|
||||||
<!-- </dependency> -->
|
|
||||||
|
|
||||||
<!-- undertow -->
|
|
||||||
<!-- <dependency> -->
|
|
||||||
<!-- <groupId>org.springframework.boot</groupId> -->
|
|
||||||
<!-- <artifactId>spring-boot-starter-web</artifactId> -->
|
|
||||||
<!-- <exclusions> -->
|
|
||||||
<!-- <exclusion> -->
|
|
||||||
<!-- <groupId>org.springframework.boot</groupId> -->
|
|
||||||
<!-- <artifactId>spring-boot-starter-tomcat</artifactId> -->
|
|
||||||
<!-- </exclusion> -->
|
|
||||||
<!-- </exclusions> -->
|
|
||||||
<!-- </dependency> -->
|
|
||||||
<!-- <dependency> -->
|
|
||||||
<!-- <groupId>org.springframework.boot</groupId> -->
|
|
||||||
<!-- <artifactId>spring-boot-starter-undertow</artifactId> -->
|
|
||||||
<!-- </dependency> -->
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openjdk.jmh</groupId>
|
|
||||||
<artifactId>jmh-core</artifactId>
|
|
||||||
<version>1.21</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openjdk.jmh</groupId>
|
|
||||||
<artifactId>jmh-generator-annprocess</artifactId>
|
|
||||||
<version>1.21</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.jayway.jsonpath</groupId>
|
|
||||||
<artifactId>json-path</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,119 +0,0 @@
|
||||||
package com.baeldung.embedded;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.assertj.core.util.Lists;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.openjdk.jmh.annotations.Benchmark;
|
|
||||||
import org.openjdk.jmh.annotations.Mode;
|
|
||||||
import org.openjdk.jmh.runner.Runner;
|
|
||||||
import org.openjdk.jmh.runner.options.Options;
|
|
||||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
|
||||||
import org.openjdk.jmh.runner.options.TimeValue;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
|
|
||||||
import com.jayway.jsonpath.JsonPath;
|
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
|
||||||
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
|
|
||||||
public class ComparisonBenchmarkTest {
|
|
||||||
|
|
||||||
private static final String BASE_URL = "http://localhost:8080/actuator/metrics";
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void getAndPrintActuatorMetrics() {
|
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
|
||||||
for (MetricConfiguration c : getMetricConfigs()) {
|
|
||||||
getAndPrintActuatorMetric(restTemplate, c);
|
|
||||||
}
|
|
||||||
System.out.println("");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void launchBenchmark() throws Exception {
|
|
||||||
Options opt = new OptionsBuilder()
|
|
||||||
.include(this.getClass().getName() + ".*")
|
|
||||||
.mode(Mode.Throughput)
|
|
||||||
.timeUnit(TimeUnit.SECONDS)
|
|
||||||
.warmupIterations(3)
|
|
||||||
.warmupTime(TimeValue.seconds(10))
|
|
||||||
.measurementIterations(3)
|
|
||||||
.measurementTime(TimeValue.minutes(1))
|
|
||||||
.threads(5)
|
|
||||||
.forks(1)
|
|
||||||
.shouldFailOnError(true)
|
|
||||||
.shouldDoGC(true)
|
|
||||||
.build();
|
|
||||||
new Runner(opt).run();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark
|
|
||||||
public void benchmark() throws Exception {
|
|
||||||
RestTemplate template = new RestTemplate();
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
MetricNames metricNames = template.getForObject(BASE_URL, MetricNames.class);
|
|
||||||
metricNames.getNames().stream().forEach(n -> {
|
|
||||||
template.getForObject(BASE_URL + "/" + n, String.class);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MetricNames {
|
|
||||||
private String[] names;
|
|
||||||
|
|
||||||
public List<String> getNames() {
|
|
||||||
return Arrays.asList(this.names);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MetricConfiguration {
|
|
||||||
|
|
||||||
private String label;
|
|
||||||
private String metric;
|
|
||||||
private Class<?> type;
|
|
||||||
private String jsonPath;
|
|
||||||
|
|
||||||
public MetricConfiguration(String label, String metric, Class<?> type, String path) {
|
|
||||||
this.label = label;
|
|
||||||
this.metric = metric;
|
|
||||||
this.type = type;
|
|
||||||
this.jsonPath = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLabel() {
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<?> getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getJsonPath() {
|
|
||||||
return jsonPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMetric() {
|
|
||||||
return metric;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<MetricConfiguration> getMetricConfigs() {
|
|
||||||
return Lists.newArrayList(
|
|
||||||
new MetricConfiguration("jvm.memory.used", "jvm.memory.used", Integer.class, "$.measurements[0].value"),
|
|
||||||
new MetricConfiguration("jvm.classes.loaded", "jvm.classes.loaded", Integer.class, "$.measurements[0].value"),
|
|
||||||
new MetricConfiguration("jvm.threads.live", "jvm.threads.live", Integer.class, "$.measurements[0].value"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getAndPrintActuatorMetric(RestTemplate restTemplate, MetricConfiguration c) {
|
|
||||||
String response = restTemplate.getForObject(BASE_URL + "/" + c.getMetric(), String.class);
|
|
||||||
String value = (JsonPath.parse(response).read(c.getJsonPath(), c.getType())).toString();
|
|
||||||
System.out.println("Startup Metric >>> " + c.getLabel() + "=" + value);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration>
|
|
||||||
<include resource="org/springframework/boot/logging/logback/base.xml" />
|
|
||||||
<logger name="org.springframework" level="INFO"/>
|
|
||||||
</configuration>
|
|
|
@ -1,4 +1,11 @@
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
================================
|
- [Deploy a Spring Boot WAR into a Tomcat Server](http://www.baeldung.com/spring-boot-war-tomcat-deploy)
|
||||||
|
- [Spring Boot Dependency Management with a Custom Parent](http://www.baeldung.com/spring-boot-dependency-management-custom-parent)
|
||||||
- [Spring Boot Console Application](http://www.baeldung.com/spring-boot-console-app)
|
- [A Custom Data Binder in Spring MVC](http://www.baeldung.com/spring-mvc-custom-data-binder)
|
||||||
|
- [Create a Fat Jar App with Spring Boot](http://www.baeldung.com/deployable-fat-jar-spring-boot)
|
||||||
|
- [Introduction to WebJars](http://www.baeldung.com/maven-webjars)
|
||||||
|
- [Intro to Spring Boot Starters](http://www.baeldung.com/spring-boot-starters)
|
||||||
|
- [A Quick Guide to Maven Wrapper](http://www.baeldung.com/maven-wrapper)
|
||||||
|
- [Shutdown a Spring Boot Application](http://www.baeldung.com/spring-boot-shutdown)
|
||||||
|
- [Spring Boot Console Application](http://www.baeldung.com/spring-boot-console-app)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.embedded;
|
package com.baeldung.compare;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.baeldung.compare;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import io.micrometer.core.instrument.Meter;
|
||||||
|
import io.micrometer.core.instrument.MeterRegistry;
|
||||||
|
import io.micrometer.core.instrument.Statistic;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class StartupEventHandler {
|
||||||
|
|
||||||
|
// logger, constructor
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(StartupEventHandler.class);
|
||||||
|
|
||||||
|
public StartupEventHandler(MeterRegistry registry) {
|
||||||
|
this.meterRegistry = registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] METRICS = {
|
||||||
|
"jvm.memory.used",
|
||||||
|
"jvm.classes.loaded",
|
||||||
|
"jvm.threads.live"};
|
||||||
|
|
||||||
|
private String METRIC_MSG_FORMAT = "Startup Metric >> {}={}";
|
||||||
|
|
||||||
|
private MeterRegistry meterRegistry;
|
||||||
|
|
||||||
|
@EventListener
|
||||||
|
public void getAndLogStartupMetrics(
|
||||||
|
ApplicationReadyEvent event) {
|
||||||
|
Arrays.asList(METRICS)
|
||||||
|
.forEach(this::getAndLogActuatorMetric);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getAndLogActuatorMetric(String metric) {
|
||||||
|
Meter meter = meterRegistry.find(metric).meter();
|
||||||
|
Map<Statistic, Double> stats = getSamples(meter);
|
||||||
|
|
||||||
|
logger.info(METRIC_MSG_FORMAT, metric, stats.get(Statistic.VALUE).longValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Statistic, Double> getSamples(Meter meter) {
|
||||||
|
Map<Statistic, Double> samples = new LinkedHashMap<>();
|
||||||
|
mergeMeasurements(samples, meter);
|
||||||
|
return samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mergeMeasurements(Map<Statistic, Double> samples, Meter meter) {
|
||||||
|
meter.measure().forEach((measurement) -> samples.merge(measurement.getStatistic(),
|
||||||
|
measurement.getValue(), mergeFunction(measurement.getStatistic())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private BiFunction<Double, Double, Double> mergeFunction(Statistic statistic) {
|
||||||
|
return Statistic.MAX.equals(statistic) ? Double::max : Double::sum;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
target/
|
/target/
|
||||||
!.mvn/wrapper/maven-wrapper.jar
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
### STS ###
|
### STS ###
|
||||||
|
@ -8,6 +8,7 @@ target/
|
||||||
.project
|
.project
|
||||||
.settings
|
.settings
|
||||||
.springBeans
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
### IntelliJ IDEA ###
|
||||||
.idea
|
.idea
|
||||||
|
@ -16,9 +17,9 @@ target/
|
||||||
*.ipr
|
*.ipr
|
||||||
|
|
||||||
### NetBeans ###
|
### NetBeans ###
|
||||||
nbproject/private/
|
/nbproject/private/
|
||||||
build/
|
/build/
|
||||||
nbbuild/
|
/nbbuild/
|
||||||
dist/
|
/dist/
|
||||||
nbdist/
|
/nbdist/
|
||||||
.nb-gradle/
|
/.nb-gradle/
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>spring-boot-vue</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>spring-boot-vue</name>
|
||||||
|
<description>Demo project for Spring Boot Vue project</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.0.2.RELEASE</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- needed to render html templates in /resources/templates -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.baeldung.springbootmvc;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class SpringBootMvcApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SpringBootMvcApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.baeldung.springbootmvc.controllers;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class MainController {
|
||||||
|
|
||||||
|
@RequestMapping(value = "/", method = RequestMethod.GET)
|
||||||
|
public String index(Model model) {
|
||||||
|
// this attribute will be available in the view index.html as a thymeleaf variable
|
||||||
|
model.addAttribute("eventName", "FIFA 2018");
|
||||||
|
// this just means render index.html from static/ area
|
||||||
|
return "index";
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
|
@ -0,0 +1,98 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<!-- Include Bootstrap -->
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
|
||||||
|
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||||
|
<!-- Optional theme -->
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
|
||||||
|
integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<h3 class="display-3">This is an example Vue.js application developed with Spring Boot</h3>
|
||||||
|
<p class="lead">This file is rendered by a Spring built-in default controller for index.html (/) using
|
||||||
|
Spring's built-in
|
||||||
|
Thymeleaf templating engine.
|
||||||
|
Although we don't need it per se, we customized the information passed to this
|
||||||
|
view from thymeleaf by adding a controller method for "/" route to demonstrate how to pass information from
|
||||||
|
Thymeleaf to this page.
|
||||||
|
The combination of template engine and frontend framework like Vue can make this a powerful approach to build
|
||||||
|
more complex applications while leveraging the benefits of a framework like Vue.js.
|
||||||
|
You can use thymeleaf features too but this project focuses mainly on using Vue.js on the
|
||||||
|
frontend as the framework and makes minimal use of Thymeleaf.
|
||||||
|
Also we don't use any routing and multiple components in this example, so what you see is technically a
|
||||||
|
Single Page Application (SPA) without any routes configured.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div id="contents-main">
|
||||||
|
<div class="lead">
|
||||||
|
<strong>Name of Event:</strong>
|
||||||
|
<span th:text="${eventName}"></span>
|
||||||
|
</div>
|
||||||
|
<div id="contents">
|
||||||
|
<!-- Since we create a Vue component pointing to id=contents,
|
||||||
|
Vue will generate a unordered list of items such
|
||||||
|
as this inside this div.
|
||||||
|
v-for will cause a loop to run over all players
|
||||||
|
as per the players array found in app.data
|
||||||
|
<ul>
|
||||||
|
<li></li>
|
||||||
|
<li></li>
|
||||||
|
</ul>
|
||||||
|
-->
|
||||||
|
<ul>
|
||||||
|
<li style="list-style-type:none" v-for="player in players">
|
||||||
|
<player-card
|
||||||
|
v-bind:player="player" v-bind:key="player.id">
|
||||||
|
</player-card>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- include Vue.js -->
|
||||||
|
<!-- we include babel js so that we can write ES6 code in the browser
|
||||||
|
for a more production like setup it is recommended to setup a build process
|
||||||
|
to transpile and minify the code (such as using webpack)
|
||||||
|
-->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
|
||||||
|
<script type="text/babel">
|
||||||
|
// player-card is now a Vue component that generates a 'card' showing a player
|
||||||
|
// It can be used
|
||||||
|
// declaratively like <player-card v-bind:player="someplayer">
|
||||||
|
Vue.component('player-card', {
|
||||||
|
props: ['player'],
|
||||||
|
template: `<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h6 class="card-title">
|
||||||
|
{{ player.name }}
|
||||||
|
</h6>
|
||||||
|
<p class="card-text">
|
||||||
|
<div>
|
||||||
|
{{ player.description }}
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
});
|
||||||
|
|
||||||
|
var app = new Vue({
|
||||||
|
el: '#contents',
|
||||||
|
data: {
|
||||||
|
players: [
|
||||||
|
{id: "1", name: "Lionel Messi", description: "Argentina's superstar"},
|
||||||
|
{id: "2", name: "Christiano Ronaldo", description: "Portugal top-ranked player"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.baeldung.springbootmvc;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest
|
||||||
|
@AutoConfigureMockMvc
|
||||||
|
public class SpringBootMvcApplicationTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this test passes, we got a page with the thymeleaf provided variable
|
||||||
|
* value for eventName
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void shouldLoadCorrectIndexPage() throws Exception {
|
||||||
|
mockMvc.perform(get("/")).andExpect(status().isOk()).
|
||||||
|
andExpect(MockMvcResultMatchers.content()
|
||||||
|
.string(containsString("FIFA 2018")));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -34,3 +34,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||||
- [Spring Boot Exit Codes](http://www.baeldung.com/spring-boot-exit-codes)
|
- [Spring Boot Exit Codes](http://www.baeldung.com/spring-boot-exit-codes)
|
||||||
- [Guide to the Favicon in Spring Boot](http://www.baeldung.com/spring-boot-favicon)
|
- [Guide to the Favicon in Spring Boot](http://www.baeldung.com/spring-boot-favicon)
|
||||||
- [Spring Shutdown Callbacks](http://www.baeldung.com/spring-shutdown-callbacks)
|
- [Spring Shutdown Callbacks](http://www.baeldung.com/spring-shutdown-callbacks)
|
||||||
|
- [Spring Boot Integration Testing with Embedded MongoDB](http://www.baeldung.com/spring-boot-embedded-mongodb)
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>parent-boot-2</artifactId>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../parent-boot-2</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>spring-data-jpa</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Application {
|
||||||
|
private static ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
applicationContext = SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package com.baeldung.repository;
|
package com.baeldung.repository;
|
||||||
|
|
||||||
import com.baeldung.domain.Article;
|
import com.baeldung.domain.Article;
|
||||||
|
import com.baeldung.repository.ArticleRepository;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
@ -0,0 +1,15 @@
|
||||||
|
# spring.datasource.x
|
||||||
|
spring.datasource.driver-class-name=org.h2.Driver
|
||||||
|
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
|
||||||
|
spring.datasource.username=sa
|
||||||
|
spring.datasource.password=sa
|
||||||
|
|
||||||
|
# hibernate.X
|
||||||
|
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||||
|
hibernate.show_sql=true
|
||||||
|
hibernate.hbm2ddl.auto=create-drop
|
||||||
|
hibernate.cache.use_second_level_cache=true
|
||||||
|
hibernate.cache.use_query_cache=true
|
||||||
|
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
|
||||||
|
|
||||||
|
spring.datasource.data=import_articles.sql
|
|
@ -32,3 +32,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||||
- [Spring Scheduling Annotations](http://www.baeldung.com/spring-scheduling-annotations)
|
- [Spring Scheduling Annotations](http://www.baeldung.com/spring-scheduling-annotations)
|
||||||
- [Spring Web Annotations](http://www.baeldung.com/spring-mvc-annotations)
|
- [Spring Web Annotations](http://www.baeldung.com/spring-mvc-annotations)
|
||||||
- [Spring Core Annotations](http://www.baeldung.com/spring-core-annotations)
|
- [Spring Core Annotations](http://www.baeldung.com/spring-core-annotations)
|
||||||
|
- [Using Spring ResponseEntity to Manipulate the HTTP Response](http://www.baeldung.com/spring-response-entity)
|
||||||
|
- [Using Spring @ResponseStatus to Set HTTP Status Code](http://www.baeldung.com/spring-response-status)
|
||||||
|
|
|
@ -24,3 +24,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||||
- [Using the Spring RestTemplate Interceptor](http://www.baeldung.com/spring-rest-template-interceptor)
|
- [Using the Spring RestTemplate Interceptor](http://www.baeldung.com/spring-rest-template-interceptor)
|
||||||
- [Configure a RestTemplate with RestTemplateBuilder](http://www.baeldung.com/spring-rest-template-builder)
|
- [Configure a RestTemplate with RestTemplateBuilder](http://www.baeldung.com/spring-rest-template-builder)
|
||||||
- [Get and Post Lists of Objects with RestTemplate](http://www.baeldung.com/spring-rest-template-list)
|
- [Get and Post Lists of Objects with RestTemplate](http://www.baeldung.com/spring-rest-template-list)
|
||||||
|
- [How to Set a Header on a Response with Spring 5](http://www.baeldung.com/spring-response-header)
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>spring-swagger-codegen</artifactId>
|
<artifactId>spring-swagger-codegen</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../spring-swagger-codegen</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>spring-swagger-codegen-app</artifactId>
|
<artifactId>spring-swagger-codegen-app</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-swagger-codegen</artifactId>
|
||||||
<version>1.5.10.RELEASE</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../spring-swagger-codegen</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<version>${spring.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -36,6 +38,7 @@
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<spring-swagger-codegen-api-client.version>0.0.1-SNAPSHOT</spring-swagger-codegen-api-client.version>
|
<spring-swagger-codegen-api-client.version>0.0.1-SNAPSHOT</spring-swagger-codegen-api-client.version>
|
||||||
|
<spring.version>1.5.10.RELEASE</spring.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,2 @@
|
||||||
|
### Relevant Articles:
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>org.baeldung</groupId>
|
||||||
|
<artifactId>spring-testing</artifactId>
|
||||||
|
<version>0.1-SNAPSHOT</version>
|
||||||
|
<name>spring-testing</name>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-java</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../parent-java</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- test scoped -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>java-hamcrest</artifactId>
|
||||||
|
<version>${hamcrest.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
<version>LATEST</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<version>LATEST</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-core</artifactId>
|
||||||
|
<version>LATEST</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context</artifactId>
|
||||||
|
<version>LATEST</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.persistence</groupId>
|
||||||
|
<artifactId>javax.persistence</artifactId>
|
||||||
|
<version>2.1.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.data</groupId>
|
||||||
|
<artifactId>spring-data-jpa</artifactId>
|
||||||
|
<version>LATEST</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>spring-testing</finalName>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<!-- testing -->
|
||||||
|
<hamcrest.version>2.0.0.0</hamcrest.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -20,7 +20,7 @@ public class MockBeanAnnotationIntegrationTest {
|
||||||
ApplicationContext context;
|
ApplicationContext context;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenCountMethodMocked_WhenCountInvokedOnBeanFromContext_ThenMockValueReturned() {
|
public void givenCountMethodMocked_WhenCountInvoked_ThenMockValueReturned() {
|
||||||
Mockito.when(mockRepository.count()).thenReturn(123L);
|
Mockito.when(mockRepository.count()).thenReturn(123L);
|
||||||
|
|
||||||
UserRepository userRepoFromContext = context.getBean(UserRepository.class);
|
UserRepository userRepoFromContext = context.getBean(UserRepository.class);
|
Loading…
Reference in New Issue