diff --git a/apache-velocity/src/main/webapp/WEB-INF/velocity.properties b/apache-velocity/src/main/webapp/WEB-INF/velocity.properties index 00e0b7e410..97b19f4cb7 100644 --- a/apache-velocity/src/main/webapp/WEB-INF/velocity.properties +++ b/apache-velocity/src/main/webapp/WEB-INF/velocity.properties @@ -1,4 +1,4 @@ resource.loader=webapp webapp.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader -webapp.resource.loader.path = . +webapp.resource.loader.path = webapp.resource.loader.cache = true \ No newline at end of file diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java b/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java index 299f74e877..5dc00dba25 100644 --- a/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java +++ b/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java @@ -6,7 +6,7 @@ public class ServiceMain { public static void main(String[] args) throws InterruptedException { ProcessHandle thisProcess = ProcessHandle.current(); - long pid = thisProcess.getPid(); + long pid = thisProcess.pid(); Optional opArgs = Optional.ofNullable(args); String procName = opArgs.map(str -> str.length > 0 ? str[0] : null).orElse(System.getProperty("sun.java.command")); diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java b/core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java new file mode 100644 index 0000000000..93abe4e185 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java @@ -0,0 +1,76 @@ +package com.baeldung.java9.language; + +import org.junit.Test; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import static org.hamcrest.Matchers.*; +import static org.hamcrest.MatcherAssert.assertThat; + +public class Java9ObjectsAPIUnitTest { + + @Test + public void givenNullObject_whenRequireNonNullElse_thenElse(){ + assertThat(Objects.requireNonNullElse(null, Collections.EMPTY_LIST), + is(Collections.EMPTY_LIST)); + } + + @Test + public void givenObject_whenRequireNonNullElse_thenObject(){ + assertThat(Objects.requireNonNullElse(List.of("item1", "item2"), + Collections.EMPTY_LIST), is(List.of("item1", "item2"))); + } + + @Test(expected = NullPointerException.class) + public void givenNull_whenRequireNonNullElse_thenException(){ + Objects.requireNonNullElse(null, null); + } + + @Test + public void givenObject_whenRequireNonNullElseGet_thenObject(){ + assertThat(Objects.requireNonNullElseGet(null, List::of), + is(List.of())); + } + + @Test + public void givenNumber_whenInvokeCheckIndex_thenNumber(){ + int length = 5; + assertThat(Objects.checkIndex(4, length), is(4)); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void givenOutOfRangeNumber_whenInvokeCheckIndex_thenException(){ + int length = 5; + Objects.checkIndex(5, length); + } + + + @Test + public void givenSubRange_whenCheckFromToIndex_thenNumber(){ + int length = 6; + assertThat(Objects.checkFromToIndex(2,length,length), is(2)); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void givenInvalidSubRange_whenCheckFromToIndex_thenException(){ + int length = 6; + Objects.checkFromToIndex(2,7,length); + } + + + @Test + public void givenSubRange_whenCheckFromIndexSize_thenNumber(){ + int length = 6; + assertThat(Objects.checkFromIndexSize(2,3,length), is(2)); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void givenInvalidSubRange_whenCheckFromIndexSize_thenException(){ + int length = 6; + Objects.checkFromIndexSize(2, 6, length); + } + + +} diff --git a/junit5/pom.xml b/junit5/pom.xml index 2316b034e9..1fa4818447 100644 --- a/junit5/pom.xml +++ b/junit5/pom.xml @@ -3,7 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.baeldung + junit5 1.0-SNAPSHOT @@ -19,9 +19,9 @@ UTF-8 1.8 - 5.0.0-M5 - 1.0.0-M5 - 4.12.0-M5 + 5.0.0-RC2 + 1.0.0-RC2 + 4.12.0-RC2 2.8.2 1.4.196 diff --git a/junit5/src/test/java/com/baeldung/param/InvalidPersonParameterResolver.java b/junit5/src/test/java/com/baeldung/param/InvalidPersonParameterResolver.java new file mode 100644 index 0000000000..67bd47a44a --- /dev/null +++ b/junit5/src/test/java/com/baeldung/param/InvalidPersonParameterResolver.java @@ -0,0 +1,50 @@ +package com.baeldung.param; + +import java.util.Random; + +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.jupiter.api.extension.ParameterResolver; + +public class InvalidPersonParameterResolver implements ParameterResolver { + + /** + * The "bad" (invalid) data for testing purposes has to go somewhere, right? + */ + public static Person[] INVALID_PERSONS = { + new Person().setId(1L).setLastName("Ad_ams").setFirstName("Jill,"), + new Person().setId(2L).setLastName(",Baker").setFirstName(""), + new Person().setId(3L).setLastName(null).setFirstName(null), + new Person().setId(4L).setLastName("Daniel&").setFirstName("{Joseph}"), + new Person().setId(5L).setLastName("").setFirstName("English, Jane"), + new Person()/* .setId(6L).setLastName("Fontana").setFirstName("Enrique") */, + // TODO: ADD MORE DATA HERE + }; + + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + Object ret = null; + // + // Return a random, valid Person object if Person.class is the type of Parameter + /// to be resolved. Otherwise return null. + if (parameterContext.getParameter().getType() == Person.class) { + ret = INVALID_PERSONS[new Random().nextInt(INVALID_PERSONS.length)]; + } + return ret; + } + + @Override + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + boolean ret = false; + // + // If the Parameter.type == Person.class, then we support it, otherwise, get outta here! + if (parameterContext.getParameter().getType() == Person.class) { + ret = true; + } + return ret; + } + +} diff --git a/junit5/src/test/java/com/baeldung/param/Person.java b/junit5/src/test/java/com/baeldung/param/Person.java new file mode 100644 index 0000000000..65333b5e56 --- /dev/null +++ b/junit5/src/test/java/com/baeldung/param/Person.java @@ -0,0 +1,43 @@ +package com.baeldung.param; + +/** + * Very simple Person entity. + * Use the Fluent-style interface to set properties. + * + * @author J Steven Perry + * + */ +public class Person { + + private Long id; + private String lastName; + private String firstName; + + public Long getId() { + return id; + } + + public Person setId(Long id) { + this.id = id; + return this; + } + + public String getLastName() { + return lastName; + } + + public Person setLastName(String lastName) { + this.lastName = lastName; + return this; + } + + public String getFirstName() { + return firstName; + } + + public Person setFirstName(String firstName) { + this.firstName = firstName; + return this; + } + +} diff --git a/junit5/src/test/java/com/baeldung/param/PersonValidator.java b/junit5/src/test/java/com/baeldung/param/PersonValidator.java new file mode 100644 index 0000000000..0219169aab --- /dev/null +++ b/junit5/src/test/java/com/baeldung/param/PersonValidator.java @@ -0,0 +1,142 @@ +package com.baeldung.param; + +import java.util.Arrays; + +/** + * Somewhat contrived validation class to illustrate unit test + * concepts. + * + * @author J Steven Perry + * + */ +public class PersonValidator { + + /** + * Contrived checked exception to illustrate one possible + * way to handle validation errors (via a checked exception). + * + * @author J Steven Perry + * + */ + public static class ValidationException extends Exception { + + /** + * + */ + private static final long serialVersionUID = -134518049431883102L; + + // Probably should implement some more constructors, but don't want + /// to tarnish the lesson... + + /** + * The one and only way to create this checked exception. + * + * @param message + * The message accompanying the exception. Should be meaningful. + */ + public ValidationException(String message) { + super(message); + + } + + } + + private static final String[] ILLEGAL_NAME_CHARACTERS = { + ",", + "_", + "{", + "}", + "!" + }; + + /** + * Validate the first name of the specified Person object. + * + * @param person + * The Person object to validate. + * + * @return - returns true if the specified Person is valid + * + * @throws ValidationException + * - this Exception is thrown if any kind of validation error occurs. + */ + public static boolean validateFirstName(Person person) throws ValidationException { + boolean ret = true; + // The validation rules go here. + // Naive: use simple ifs + if (person == null) { + throw new ValidationException("Person is null (not allowed)!"); + } + if (person.getFirstName() == null) { + throw new ValidationException("Person FirstName is null (not allowed)!"); + } + if (person.getFirstName().isEmpty()) { + throw new ValidationException("Person FirstName is an empty String (not allowed)!"); + } + if (!isStringValid(person.getFirstName(), ILLEGAL_NAME_CHARACTERS)) { + throw new ValidationException( + "Person FirstName (" + person.getFirstName() + ") may not contain any of the following characters: " + + Arrays.toString(ILLEGAL_NAME_CHARACTERS) + + "!"); + } + return ret; + } + + /** + * Validate the last name of the specified Person object. Looks the same as first + * name? Look closer. Just kidding. It's the same. But real world code can (and will) diverge. + * + * @param person + * The Person object to validate. + * + * @return - returns true if the specified Person is valid + * + * @throws ValidationException + * - this Exception is thrown if any kind of validation error occurs. + */ + public static boolean validateLastName(Person person) throws ValidationException { + boolean ret = true; + // The validation rules go here. + // Naive: use simple ifs + if (person == null) { + throw new ValidationException("Person is null (not allowed)!"); + } + if (person.getFirstName() == null) { + throw new ValidationException("Person FirstName is null (not allowed)!"); + } + if (person.getFirstName().isEmpty()) { + throw new ValidationException("Person FirstName is an empty String (not allowed)!"); + } + if (!isStringValid(person.getFirstName(), ILLEGAL_NAME_CHARACTERS)) { + throw new ValidationException( + "Person LastName (" + person.getLastName() + ") may not contain any of the following characters: " + + Arrays.toString(ILLEGAL_NAME_CHARACTERS) + + "!"); + } + return ret; + } + + /** + * Validates the specified name. If it contains any of the illegalCharacters, + * this method returns false (indicating the name is illegal). Otherwise it returns true. + * + * @param candidate + * The candidate String to validate + * + * @param illegalCharacters + * The characters the String is not allowed to have + * + * @return - boolean - true if the name is valid, false otherwise. + */ + private static boolean isStringValid(String candidate, String[] illegalCharacters) { + boolean ret = true; + for (String illegalChar : illegalCharacters) { + if (candidate.contains(illegalChar)) { + ret = false; + break; + } + } + return ret; + } + +} diff --git a/junit5/src/test/java/com/baeldung/param/PersonValidatorTest.java b/junit5/src/test/java/com/baeldung/param/PersonValidatorTest.java new file mode 100644 index 0000000000..09ab03b811 --- /dev/null +++ b/junit5/src/test/java/com/baeldung/param/PersonValidatorTest.java @@ -0,0 +1,102 @@ +package com.baeldung.param; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; + +@RunWith(JUnitPlatform.class) +@DisplayName("Testing PersonValidator") +public class PersonValidatorTest { + + /** + * Nested class, uses ExtendWith + * {@link com.baeldung.param.ValidPersonParameterResolver ValidPersonParameterResolver} + * to feed Test methods with "good" data. + */ + @Nested + @DisplayName("When using Valid data") + @ExtendWith(ValidPersonParameterResolver.class) + public class ValidData { + + /** + * Repeat the test ten times, that way we have a good shot at + * running all of the data through at least once. + * + * @param person + * A valid Person object to validate. + */ + @RepeatedTest(value = 10) + @DisplayName("All first names are valid") + public void validateFirstName(Person person) { + try { + assertTrue(PersonValidator.validateFirstName(person)); + } catch (PersonValidator.ValidationException e) { + fail("Exception not expected: " + e.getLocalizedMessage()); + } + } + + /** + * Repeat the test ten times, that way we have a good shot at + * running all of the data through at least once. + * + * @param person + * A valid Person object to validate. + */ + @RepeatedTest(value = 10) + @DisplayName("All last names are valid") + public void validateLastName(Person person) { + try { + assertTrue(PersonValidator.validateLastName(person)); + } catch (PersonValidator.ValidationException e) { + fail("Exception not expected: " + e.getLocalizedMessage()); + } + } + + } + + /** + * Nested class, uses ExtendWith + * {@link com.baeldung.param.InvalidPersonParameterResolver InvalidPersonParameterResolver} + * to feed Test methods with "bad" data. + */ + @Nested + @DisplayName("When using Invalid data") + @ExtendWith(InvalidPersonParameterResolver.class) + public class InvalidData { + + /** + * Repeat the test ten times, that way we have a good shot at + * running all of the data through at least once. + * + * @param person + * An invalid Person object to validate. + */ + @RepeatedTest(value = 10) + @DisplayName("All first names are invalid") + public void validateFirstName(Person person) { + assertThrows(PersonValidator.ValidationException.class, () -> PersonValidator.validateFirstName(person)); + } + + /** + * Repeat the test ten times, that way we have a good shot at + * running all of the data through at least once. + * + * @param person + * An invalid Person object to validate. + */ + @RepeatedTest(value = 10) + @DisplayName("All first names are invalid") + public void validateLastName(Person person) { + assertThrows(PersonValidator.ValidationException.class, () -> PersonValidator.validateLastName(person)); + } + + } + +} diff --git a/junit5/src/test/java/com/baeldung/param/ValidPersonParameterResolver.java b/junit5/src/test/java/com/baeldung/param/ValidPersonParameterResolver.java new file mode 100644 index 0000000000..abb97586eb --- /dev/null +++ b/junit5/src/test/java/com/baeldung/param/ValidPersonParameterResolver.java @@ -0,0 +1,50 @@ +package com.baeldung.param; + +import java.util.Random; + +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.jupiter.api.extension.ParameterResolver; + +public class ValidPersonParameterResolver implements ParameterResolver { + + /** + * The "good" (valid) data for testing purposes has to go somewhere, right? + */ + public static Person[] VALID_PERSONS = { + new Person().setId(1L).setLastName("Adams").setFirstName("Jill"), + new Person().setId(2L).setLastName("Baker").setFirstName("James"), + new Person().setId(3L).setLastName("Carter").setFirstName("Samanta"), + new Person().setId(4L).setLastName("Daniels").setFirstName("Joseph"), + new Person().setId(5L).setLastName("English").setFirstName("Jane"), + new Person().setId(6L).setLastName("Fontana").setFirstName("Enrique"), + // TODO: ADD MORE DATA HERE + }; + + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + Object ret = null; + // + // Return a random, valid Person object if Person.class is the type of Parameter + /// to be resolved. Otherwise return null. + if (parameterContext.getParameter().getType() == Person.class) { + ret = VALID_PERSONS[new Random().nextInt(VALID_PERSONS.length)]; + } + return ret; + } + + @Override + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + boolean ret = false; + // + // If the Parameter.type == Person.class, then we support it, otherwise, get outta here! + if (parameterContext.getParameter().getType() == Person.class) { + ret = true; + } + return ret; + } + +} diff --git a/libraries/README.md b/libraries/README.md index 0e58628118..88075af390 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -29,6 +29,8 @@ - [Introduction to Neuroph](http://www.baeldung.com/intro-to-neuroph) - [Guide to Apache Commons CircularFifoQueue](http://www.baeldung.com/commons-circular-fifo-queue) - [Quick Guide to RSS with Rome](http://www.baeldung.com/rome-rss) +- [Introduction to NoException](http://www.baeldung.com/intrduction-to-noexception) + 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. diff --git a/libraries/pom.xml b/libraries/pom.xml index 8f28a23d75..a16a4de59d 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -462,6 +462,11 @@ pcollections ${pcollections.version} + + com.machinezoo.noexception + noexception + 1.1.0 + org.eclipse.collections eclipse-collections diff --git a/libraries/src/main/java/com/baeldung/noexception/CustomExceptionHandler.java b/libraries/src/main/java/com/baeldung/noexception/CustomExceptionHandler.java new file mode 100644 index 0000000000..59e13efaa0 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/noexception/CustomExceptionHandler.java @@ -0,0 +1,24 @@ +package com.baeldung.noexception; + +import com.machinezoo.noexception.ExceptionHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CustomExceptionHandler extends ExceptionHandler { + + private Logger logger = LoggerFactory.getLogger(CustomExceptionHandler.class); + + @Override + public boolean handle(Throwable throwable) { + + if (throwable.getClass() + .isAssignableFrom(RuntimeException.class) + || throwable.getClass() + .isAssignableFrom(Error.class)) { + return false; + } else { + logger.error("Caught Exception ", throwable); + return true; + } + } +} diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/ForEachPatternTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/ForEachPatternTest.java new file mode 100644 index 0000000000..e8d93a2af6 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/ForEachPatternTest.java @@ -0,0 +1,32 @@ +package com.baeldung.eclipsecollections; + +import org.eclipse.collections.api.block.procedure.Procedure; +import org.eclipse.collections.api.tuple.Pair; +import org.eclipse.collections.impl.map.mutable.UnifiedMap; +import org.eclipse.collections.impl.tuple.Tuples; +import static org.junit.Assert.assertEquals; + +import java.util.Map; + +import org.junit.Test; + +public class ForEachPatternTest { + + @SuppressWarnings("unchecked") + @Test + public void whenInstantiateAndChangeValues_thenCorrect() { + Pair pair1 = Tuples.pair(1, "One"); + Pair pair2 = Tuples.pair(2, "Two"); + Pair pair3 = Tuples.pair(3, "Three"); + + UnifiedMap map = UnifiedMap.newMapWith(pair1, pair2, pair3); + + for (int i = 0; i < map.size(); i++) { + map.put(i + 1, "New Value"); + } + + for (int i = 0; i < map.size(); i++) { + assertEquals("New Value", map.get(i + 1)); + } + } +} diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/InjectIntoPatternTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/InjectIntoPatternTest.java new file mode 100644 index 0000000000..bcd34021b1 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/InjectIntoPatternTest.java @@ -0,0 +1,23 @@ +package com.baeldung.eclipsecollections; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.eclipse.collections.impl.factory.Lists; +import org.junit.Test; + +public class InjectIntoPatternTest { + + @Test + public void whenInjectInto_thenCorrect() { + List list = Lists.mutable.of(1, 2, 3, 4); + int result = 5; + for (int i = 0; i < list.size(); i++) { + Integer v = list.get(i); + result = result + v.intValue(); + } + + assertEquals(15, result); + } +} diff --git a/libraries/src/test/java/com/baeldung/hll/HLLUnitTest.java b/libraries/src/test/java/com/baeldung/hll/HLLUnitTest.java index 8d09c99f0f..e208add3c8 100644 --- a/libraries/src/test/java/com/baeldung/hll/HLLUnitTest.java +++ b/libraries/src/test/java/com/baeldung/hll/HLLUnitTest.java @@ -23,9 +23,9 @@ public class HLLUnitTest { //when LongStream.range(0, numberOfElements).forEach(element -> { - long hashedValue = hashFunction.newHasher().putLong(element).hash().asLong(); - hll.addRaw(hashedValue); - } + long hashedValue = hashFunction.newHasher().putLong(element).hash().asLong(); + hll.addRaw(hashedValue); + } ); //then @@ -44,15 +44,15 @@ public class HLLUnitTest { //when LongStream.range(0, numberOfElements).forEach(element -> { - long hashedValue = hashFunction.newHasher().putLong(element).hash().asLong(); - firstHll.addRaw(hashedValue); - } + long hashedValue = hashFunction.newHasher().putLong(element).hash().asLong(); + firstHll.addRaw(hashedValue); + } ); LongStream.range(numberOfElements, numberOfElements * 2).forEach(element -> { - long hashedValue = hashFunction.newHasher().putLong(element).hash().asLong(); - secondHLL.addRaw(hashedValue); - } + long hashedValue = hashFunction.newHasher().putLong(element).hash().asLong(); + secondHLL.addRaw(hashedValue); + } ); //then diff --git a/libraries/src/test/java/com/baeldung/hoverfly/HoverflyApiTest.java b/libraries/src/test/java/com/baeldung/hoverfly/HoverflyApiIntegrationTest.java similarity index 99% rename from libraries/src/test/java/com/baeldung/hoverfly/HoverflyApiTest.java rename to libraries/src/test/java/com/baeldung/hoverfly/HoverflyApiIntegrationTest.java index bdaf4d7bd9..167aef5ec6 100644 --- a/libraries/src/test/java/com/baeldung/hoverfly/HoverflyApiTest.java +++ b/libraries/src/test/java/com/baeldung/hoverfly/HoverflyApiIntegrationTest.java @@ -31,7 +31,7 @@ import org.springframework.web.client.RestTemplate; import io.specto.hoverfly.junit.core.SimulationSource; import io.specto.hoverfly.junit.rule.HoverflyRule; -public class HoverflyApiTest { +public class HoverflyApiIntegrationTest { private static final SimulationSource source = dsl( service("http://www.baeldung.com") diff --git a/libraries/src/test/java/com/baeldung/noexception/NoExceptionUnitTest.java b/libraries/src/test/java/com/baeldung/noexception/NoExceptionUnitTest.java new file mode 100644 index 0000000000..b7619202fe --- /dev/null +++ b/libraries/src/test/java/com/baeldung/noexception/NoExceptionUnitTest.java @@ -0,0 +1,62 @@ +package com.baeldung.noexception; + +import com.machinezoo.noexception.Exceptions; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NoExceptionUnitTest { + + private static Logger logger = LoggerFactory.getLogger(NoExceptionUnitTest.class); + + @Test + public void whenStdExceptionHandling_thenCatchAndLog() { + try { + System.out.println("Result is " + Integer.parseInt("foobar")); + } catch (Throwable exception) { + logger.error("Caught exception:", exception); + } + } + + @Test + public void whenDefaultNoException_thenCatchAndLog() { + Exceptions.log().run(() -> System.out.println("Result is " + Integer.parseInt("foobar"))); + } + + @Test + public void givenLogger_whenDefaultNoException_thenCatchAndLogWithClassName() { + Exceptions.log(logger).run(() -> System.out.println("Result is " + Integer.parseInt("foobar"))); + } + + @Test + public void givenLoggerAndMessage_whenDefaultNoException_thenCatchAndLogWithMessage() { + Exceptions.log(logger, "Something went wrong:").run(() -> System.out.println("Result is " + Integer.parseInt("foobar"))); + } + + @Test + public void givenDefaultValue_whenDefaultNoException_thenCatchAndLogPrintDefault() { + System.out.println("Result is " + Exceptions.log(logger, "Something went wrong:").get(() -> Integer.parseInt("foobar")).orElse(-1)); + } + + @Test(expected = Error.class) + public void givenCustomHandler_whenError_thenRethrowError() { + CustomExceptionHandler customExceptionHandler = new CustomExceptionHandler(); + customExceptionHandler.run(() -> throwError()); + } + + @Test + public void givenCustomHandler_whenException_thenCatchAndLog() { + CustomExceptionHandler customExceptionHandler = new CustomExceptionHandler(); + customExceptionHandler.run(() -> throwException()); + } + + private static void throwError() { + throw new Error("This is very bad."); + } + + private static void throwException() { + String testString = "foo"; + testString.charAt(5); + } + +} diff --git a/libraries/src/test/java/com/baeldung/pcollections/PCollectionsUnitTest.java b/libraries/src/test/java/com/baeldung/pcollections/PCollectionsUnitTest.java index 23f9abf2f3..acc7718ea8 100644 --- a/libraries/src/test/java/com/baeldung/pcollections/PCollectionsUnitTest.java +++ b/libraries/src/test/java/com/baeldung/pcollections/PCollectionsUnitTest.java @@ -1,7 +1,12 @@ package com.baeldung.pcollections; import org.junit.Test; -import org.pcollections.*; +import org.pcollections.HashPMap; +import org.pcollections.HashTreePMap; +import org.pcollections.HashTreePSet; +import org.pcollections.MapPSet; +import org.pcollections.PVector; +import org.pcollections.TreePVector; import java.util.Arrays; import java.util.HashMap; @@ -27,7 +32,7 @@ public class PCollectionsUnitTest { @Test public void givenExistingHashMap_whenFrom_thenCreateHashPMap() { - Map map = new HashMap(); + Map map = new HashMap<>(); map.put("mkey1", "mval1"); map.put("mkey2", "mval2"); @@ -41,7 +46,7 @@ public class PCollectionsUnitTest { HashPMap pmap = HashTreePMap.empty(); HashPMap pmap0 = pmap.plus("key1", "value1"); - Map map = new HashMap(); + Map map = new HashMap<>(); map.put("key2", "val2"); map.put("key3", "val3"); @@ -57,22 +62,24 @@ public class PCollectionsUnitTest { @Test public void whenTreePVectorMethods_thenPerformOperations() { - TreePVector pVector = TreePVector.empty(); + TreePVector pVector = TreePVector.empty(); + + TreePVector pV1 = pVector.plus("e1"); + TreePVector pV2 = pV1.plusAll(Arrays.asList("e2", "e3", "e4")); - TreePVector pV1 = pVector.plus("e1"); - TreePVector pV2 = pV1.plusAll(Arrays.asList("e2", "e3", "e4")); assertEquals(1, pV1.size()); assertEquals(4, pV2.size()); - TreePVector pV3 = pV2.minus("e1"); - TreePVector pV4 = pV3.minusAll(Arrays.asList("e2", "e3", "e4")); + TreePVector pV3 = pV2.minus("e1"); + TreePVector pV4 = pV3.minusAll(Arrays.asList("e2", "e3", "e4")); + assertEquals(pV3.size(), 3); assertEquals(pV4.size(), 0); - TreePVector pSub = pV2.subList(0, 2); + TreePVector pSub = pV2.subList(0, 2); assertTrue(pSub.contains("e1") && pSub.contains("e2")); - TreePVector pVW = (TreePVector) pV2.with(0, "e10"); + PVector pVW = pV2.with(0, "e10"); assertEquals(pVW.get(0), "e10"); } @@ -80,7 +87,7 @@ public class PCollectionsUnitTest { public void whenMapPSetMethods_thenPerformOperations() { MapPSet pSet = HashTreePSet.empty() - .plusAll(Arrays.asList("e1","e2","e3","e4")); + .plusAll(Arrays.asList("e1", "e2", "e3", "e4")); assertEquals(pSet.size(), 4); MapPSet pSet1 = pSet.minus("e4"); diff --git a/metrics/src/test/java/com/baeldung/metrics/servo/AtlasObserverLiveTest.java b/metrics/src/test/java/com/baeldung/metrics/servo/AtlasObserverLiveTest.java index cc2d3aa393..134c3c91cf 100644 --- a/metrics/src/test/java/com/baeldung/metrics/servo/AtlasObserverLiveTest.java +++ b/metrics/src/test/java/com/baeldung/metrics/servo/AtlasObserverLiveTest.java @@ -27,9 +27,6 @@ import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertThat; -/** - * @author aiet - */ public class AtlasObserverLiveTest { private final String atlasUri = "http://localhost:7101/api/v1"; diff --git a/metrics/src/test/java/com/baeldung/metrics/servo/MetricAnnotationTest.java b/metrics/src/test/java/com/baeldung/metrics/servo/MetricAnnotationManualTest.java similarity index 95% rename from metrics/src/test/java/com/baeldung/metrics/servo/MetricAnnotationTest.java rename to metrics/src/test/java/com/baeldung/metrics/servo/MetricAnnotationManualTest.java index 3d6a73912f..2f908531f6 100644 --- a/metrics/src/test/java/com/baeldung/metrics/servo/MetricAnnotationTest.java +++ b/metrics/src/test/java/com/baeldung/metrics/servo/MetricAnnotationManualTest.java @@ -22,10 +22,7 @@ import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; -/** - * @author aiet - */ -public class MetricAnnotationTest extends MetricTestBase { +public class MetricAnnotationManualTest extends MetricTestBase { @Monitor(name = "integerCounter", type = DataSourceType.COUNTER, description = "Total number of update operations.") private final AtomicInteger updateCount = new AtomicInteger(0); diff --git a/metrics/src/test/java/com/baeldung/metrics/servo/MetricObserverTest.java b/metrics/src/test/java/com/baeldung/metrics/servo/MetricObserverManualTest.java similarity index 86% rename from metrics/src/test/java/com/baeldung/metrics/servo/MetricObserverTest.java rename to metrics/src/test/java/com/baeldung/metrics/servo/MetricObserverManualTest.java index 14d3c2646f..3bb421b3ef 100644 --- a/metrics/src/test/java/com/baeldung/metrics/servo/MetricObserverTest.java +++ b/metrics/src/test/java/com/baeldung/metrics/servo/MetricObserverManualTest.java @@ -13,14 +13,16 @@ import java.util.List; import static com.netflix.servo.annotations.DataSourceType.GAUGE; import static java.util.concurrent.TimeUnit.SECONDS; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; -/** - * @author aiet - */ -public class MetricObserverTest extends MetricTestBase { +public class MetricObserverManualTest extends MetricTestBase { @Test public void givenMetrics_whenRegister_thenMonitored() throws InterruptedException { diff --git a/metrics/src/test/java/com/baeldung/metrics/servo/MetricPollerTest.java b/metrics/src/test/java/com/baeldung/metrics/servo/MetricPollerManualTest.java similarity index 74% rename from metrics/src/test/java/com/baeldung/metrics/servo/MetricPollerTest.java rename to metrics/src/test/java/com/baeldung/metrics/servo/MetricPollerManualTest.java index 4a9a77efde..318170fb1f 100644 --- a/metrics/src/test/java/com/baeldung/metrics/servo/MetricPollerTest.java +++ b/metrics/src/test/java/com/baeldung/metrics/servo/MetricPollerManualTest.java @@ -1,20 +1,23 @@ package com.baeldung.metrics.servo; import com.netflix.servo.Metric; -import com.netflix.servo.publish.*; +import com.netflix.servo.publish.BasicMetricFilter; +import com.netflix.servo.publish.JvmMetricPoller; +import com.netflix.servo.publish.MemoryMetricObserver; +import com.netflix.servo.publish.PollRunnable; +import com.netflix.servo.publish.PollScheduler; import org.junit.Test; import java.util.List; import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.stream.Collectors.toList; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.hasSize; import static org.junit.Assert.assertThat; -/** - * @author aiet - */ -public class MetricPollerTest { +public class MetricPollerManualTest { @Test public void givenJvmPoller_whenMonitor_thenDataCollected() throws Exception { diff --git a/metrics/src/test/java/com/baeldung/metrics/servo/MetricTestBase.java b/metrics/src/test/java/com/baeldung/metrics/servo/MetricTestBase.java index 86a9d201e8..42f3c72e97 100644 --- a/metrics/src/test/java/com/baeldung/metrics/servo/MetricTestBase.java +++ b/metrics/src/test/java/com/baeldung/metrics/servo/MetricTestBase.java @@ -1,14 +1,16 @@ package com.baeldung.metrics.servo; -import com.netflix.servo.publish.*; +import com.netflix.servo.publish.BasicMetricFilter; +import com.netflix.servo.publish.MemoryMetricObserver; +import com.netflix.servo.publish.MetricFilter; +import com.netflix.servo.publish.MonitorRegistryMetricPoller; +import com.netflix.servo.publish.PollRunnable; +import com.netflix.servo.publish.PollScheduler; import org.junit.After; import org.junit.Before; import static java.util.concurrent.TimeUnit.SECONDS; -/** - * @author aiet - */ abstract class MetricTestBase { MemoryMetricObserver observer; diff --git a/metrics/src/test/java/com/baeldung/metrics/servo/MetricTypeTest.java b/metrics/src/test/java/com/baeldung/metrics/servo/MetricTypeTest.java index 68ba23244d..99009f8d84 100644 --- a/metrics/src/test/java/com/baeldung/metrics/servo/MetricTypeTest.java +++ b/metrics/src/test/java/com/baeldung/metrics/servo/MetricTypeTest.java @@ -1,6 +1,21 @@ package com.baeldung.metrics.servo; -import com.netflix.servo.monitor.*; +import com.netflix.servo.monitor.BasicCounter; +import com.netflix.servo.monitor.BasicGauge; +import com.netflix.servo.monitor.BasicInformational; +import com.netflix.servo.monitor.BasicTimer; +import com.netflix.servo.monitor.BucketConfig; +import com.netflix.servo.monitor.BucketTimer; +import com.netflix.servo.monitor.Counter; +import com.netflix.servo.monitor.Gauge; +import com.netflix.servo.monitor.MaxGauge; +import com.netflix.servo.monitor.Monitor; +import com.netflix.servo.monitor.MonitorConfig; +import com.netflix.servo.monitor.Monitors; +import com.netflix.servo.monitor.PeakRateCounter; +import com.netflix.servo.monitor.StatsTimer; +import com.netflix.servo.monitor.StepCounter; +import com.netflix.servo.monitor.Stopwatch; import com.netflix.servo.stats.StatsConfig; import org.junit.Ignore; import org.junit.Test; @@ -9,13 +24,12 @@ import java.util.Map; import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.stream.Collectors.toMap; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasEntry; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; -/** - * Unit test for simple App. - */ public class MetricTypeTest { @Test @@ -113,7 +127,7 @@ public class MetricTypeTest { BucketTimer timer = new BucketTimer(MonitorConfig .builder("test") .build(), new BucketConfig.Builder() - .withBuckets(new long[] { 2L, 5L }) + .withBuckets(new long[]{2L, 5L}) .withTimeUnit(SECONDS) .build(), SECONDS); timer.record(3); @@ -150,7 +164,7 @@ public class MetricTypeTest { .builder("test") .build(), new StatsConfig.Builder() .withComputeFrequencyMillis(2000) - .withPercentiles(new double[] { 99.0, 95.0, 90.0 }) + .withPercentiles(new double[]{99.0, 95.0, 90.0}) .withPublishMax(true) .withPublishMin(true) .withPublishCount(true) diff --git a/noexception/README.md b/noexception/README.md new file mode 100644 index 0000000000..d840191369 --- /dev/null +++ b/noexception/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Introduction to NoException](http://www.baeldung.com/intrduction-to-noexception) diff --git a/noexception/pom.xml b/noexception/pom.xml new file mode 100644 index 0000000000..64c0591fda --- /dev/null +++ b/noexception/pom.xml @@ -0,0 +1,23 @@ + + 4.0.0 + + com.baeldung + noexception + 1.0 + noexception + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + com.machinezoo.noexception + noexception + 1.1.0 + + + diff --git a/noexception/src/main/java/com/baeldung/noexception/CustomExceptionHandler.java b/noexception/src/main/java/com/baeldung/noexception/CustomExceptionHandler.java new file mode 100644 index 0000000000..59e13efaa0 --- /dev/null +++ b/noexception/src/main/java/com/baeldung/noexception/CustomExceptionHandler.java @@ -0,0 +1,24 @@ +package com.baeldung.noexception; + +import com.machinezoo.noexception.ExceptionHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CustomExceptionHandler extends ExceptionHandler { + + private Logger logger = LoggerFactory.getLogger(CustomExceptionHandler.class); + + @Override + public boolean handle(Throwable throwable) { + + if (throwable.getClass() + .isAssignableFrom(RuntimeException.class) + || throwable.getClass() + .isAssignableFrom(Error.class)) { + return false; + } else { + logger.error("Caught Exception ", throwable); + return true; + } + } +} diff --git a/noexception/src/test/java/com/baeldung/noexception/NoExceptionUnitTest.java b/noexception/src/test/java/com/baeldung/noexception/NoExceptionUnitTest.java new file mode 100644 index 0000000000..690ea43520 --- /dev/null +++ b/noexception/src/test/java/com/baeldung/noexception/NoExceptionUnitTest.java @@ -0,0 +1,63 @@ +package com.baeldung.noexception; + +import com.machinezoo.noexception.Exceptions; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NoExceptionUnitTest { + + private static Logger logger = LoggerFactory.getLogger(NoExceptionUnitTest.class); + + @Test + public void whenStdExceptionHandling_thenCatchAndLog() { + try { + System.out.println("Result is " + Integer.parseInt("foobar")); + } catch (Throwable exception) { + logger.error("Caught exception:", exception); + } + } + + @Test + public void whenDefaultNoException_thenCatchAndLog() { + + Exceptions.log().run(() -> System.out.println("Result is " + Integer.parseInt("foobar"))); + } + + @Test + public void givenLogger_whenDefaultNoException_thenCatchAndLogWithClassName() { + System.out.println("Result is " + Exceptions.log(logger).get(() -> +Integer.parseInt("foobar")).orElse(-1)); + } + + @Test + public void givenLoggerAndMessage_whenDefaultNoException_thenCatchAndLogWithClassNameAndMessage() { + System.out.println("Result is " + Exceptions.log(logger, "Something went wrong:").get(() -> +Integer.parseInt("foobar")).orElse(-1)); + } + + @Test + public void givenDefaultValue_whenDefaultNoException_thenCatchAndLogPrintDefault() { + System.out.println("Result is " + Exceptions.log(logger, "Something went wrong:").get(() -> +Integer.parseInt("foobar")).orElse(-1)); + } + + @Test(expected = Error.class) + public void givenCustomHandler_whenError_thenRethrowError() { + CustomExceptionHandler customExceptionHandler = new CustomExceptionHandler(); + customExceptionHandler.run(() -> throwError()); + } + + @Test + public void givenCustomHandler_whenException_thenCatchAndLog() { + CustomExceptionHandler customExceptionHandler = new CustomExceptionHandler(); + customExceptionHandler.run(() -> throwException()); + } + + private static void throwError() { + throw new Error("This is very bad."); + } + + private static void throwException() { + String testString = "foo"; + testString.charAt(5); + } + +} diff --git a/pom.xml b/pom.xml index f33d63bc48..8b3df8de0d 100644 --- a/pom.xml +++ b/pom.xml @@ -106,6 +106,7 @@ mockito2 mocks mustache + noexception orika diff --git a/spring-activiti/src/test/java/com/example/activitiwithspring/ProcessEngineCreationTests.java b/spring-activiti/src/test/java/com/example/activitiwithspring/ProcessEngineCreationIntegrationTest.java similarity index 85% rename from spring-activiti/src/test/java/com/example/activitiwithspring/ProcessEngineCreationTests.java rename to spring-activiti/src/test/java/com/example/activitiwithspring/ProcessEngineCreationIntegrationTest.java index 7f07191cde..00afd14590 100644 --- a/spring-activiti/src/test/java/com/example/activitiwithspring/ProcessEngineCreationTests.java +++ b/spring-activiti/src/test/java/com/example/activitiwithspring/ProcessEngineCreationIntegrationTest.java @@ -3,11 +3,12 @@ package com.example.activitiwithspring; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngineConfiguration; import org.activiti.engine.ProcessEngines; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import org.junit.Test; -public class ProcessEngineCreationTests { +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class ProcessEngineCreationIntegrationTest { @Test public void givenXMLConfig_whenGetDefault_thenGotProcessEngine() { @@ -35,7 +36,7 @@ public class ProcessEngineCreationTests { @Test public void givenDifferentBeanNameInXMLConfig_whenGetProcessEngineConfig_thenGotResult() { ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration - .createProcessEngineConfigurationFromResource("my.activiti.cfg.xml", "myProcessEngineConfiguration"); + .createProcessEngineConfigurationFromResource("my.activiti.cfg.xml", "myProcessEngineConfiguration"); ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine(); assertNotNull(processEngine); assertEquals("baeldung", processEngine.getProcessEngineConfiguration().getJdbcUsername()); @@ -45,8 +46,8 @@ public class ProcessEngineCreationTests { public void givenNoXMLConfig_whenCreateInMemProcessEngineConfig_thenCreated() { ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration(); ProcessEngine processEngine = processEngineConfiguration - .setJdbcUrl("jdbc:h2:mem:my-own-in-mem-db;DB_CLOSE_DELAY=1000") - .buildProcessEngine(); + .setJdbcUrl("jdbc:h2:mem:my-own-in-mem-db;DB_CLOSE_DELAY=1000") + .buildProcessEngine(); assertNotNull(processEngine); assertEquals("sa", processEngine.getProcessEngineConfiguration().getJdbcUsername()); } @@ -55,9 +56,9 @@ public class ProcessEngineCreationTests { public void givenNoXMLConfig_whenCreateProcessEngineConfig_thenCreated() { ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration(); ProcessEngine processEngine = processEngineConfiguration - .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE) - .setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000") - .buildProcessEngine(); + .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE) + .setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000") + .buildProcessEngine(); assertNotNull(processEngine); assertEquals("sa", processEngine.getProcessEngineConfiguration().getJdbcUsername()); } diff --git a/spring-activiti/src/test/java/com/example/activitiwithspring/ProcessExecutionTests.java b/spring-activiti/src/test/java/com/example/activitiwithspring/ProcessExecutionIntegrationTest.java similarity index 85% rename from spring-activiti/src/test/java/com/example/activitiwithspring/ProcessExecutionTests.java rename to spring-activiti/src/test/java/com/example/activitiwithspring/ProcessExecutionIntegrationTest.java index cae28d5281..9c35ea413b 100644 --- a/spring-activiti/src/test/java/com/example/activitiwithspring/ProcessExecutionTests.java +++ b/spring-activiti/src/test/java/com/example/activitiwithspring/ProcessExecutionIntegrationTest.java @@ -1,10 +1,6 @@ package com.example.activitiwithspring; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.activiti.engine.ActivitiException; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; @@ -13,19 +9,24 @@ import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; import org.junit.Test; -public class ProcessExecutionTests { +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class ProcessExecutionIntegrationTest { @Test public void givenBPMN_whenDeployProcess_thenDeployed() { ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); repositoryService.createDeployment() - .addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml") - .deploy(); + .addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml") + .deploy(); Long count = repositoryService.createProcessDefinitionQuery().count(); assertTrue(count >= 1); } @@ -35,8 +36,8 @@ public class ProcessExecutionTests { ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); repositoryService.createDeployment() - .addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml") - .deploy(); + .addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml") + .deploy(); Map variables = new HashMap(); variables.put("employeeName", "Kermit"); @@ -45,7 +46,7 @@ public class ProcessExecutionTests { RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance = runtimeService - .startProcessInstanceByKey("vacationRequest", variables); + .startProcessInstanceByKey("vacationRequest", variables); Long count = runtimeService.createProcessInstanceQuery().count(); assertTrue(count >= 1); @@ -56,8 +57,8 @@ public class ProcessExecutionTests { ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); repositoryService.createDeployment() - .addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml") - .deploy(); + .addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml") + .deploy(); Map variables = new HashMap(); variables.put("employeeName", "Kermit"); @@ -66,7 +67,7 @@ public class ProcessExecutionTests { RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance = runtimeService - .startProcessInstanceByKey("vacationRequest", variables); + .startProcessInstanceByKey("vacationRequest", variables); TaskService taskService = processEngine.getTaskService(); List tasks = taskService.createTaskQuery().taskCandidateGroup("management").list(); @@ -87,8 +88,8 @@ public class ProcessExecutionTests { ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); repositoryService.createDeployment() - .addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml") - .deploy(); + .addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml") + .deploy(); RuntimeService runtimeService = processEngine.getRuntimeService(); repositoryService.suspendProcessDefinitionByKey("vacationRequest"); diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/CustomMultiResourcePartitioner.java b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/CustomMultiResourcePartitioner.java new file mode 100644 index 0000000000..4cae69efbd --- /dev/null +++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/CustomMultiResourcePartitioner.java @@ -0,0 +1,77 @@ +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed 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. + */ + +package org.baeldung.spring_batch_intro.partitioner; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.batch.core.partition.support.Partitioner; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; + +public class CustomMultiResourcePartitioner implements Partitioner { + + private static final String DEFAULT_KEY_NAME = "fileName"; + + private static final String PARTITION_KEY = "partition"; + + private Resource[] resources = new Resource[0]; + + private String keyName = DEFAULT_KEY_NAME; + + /** + * The resources to assign to each partition. In Spring configuration you + * can use a pattern to select multiple resources. + * @param resources the resources to use + */ + public void setResources(Resource[] resources) { + this.resources = resources; + } + + /** + * The name of the key for the file name in each {@link ExecutionContext}. + * Defaults to "fileName". + * @param keyName the value of the key + */ + public void setKeyName(String keyName) { + this.keyName = keyName; + } + + /** + * Assign the filename of each of the injected resources to an + * {@link ExecutionContext}. + * + * @see Partitioner#partition(int) + */ + @Override + public Map partition(int gridSize) { + Map map = new HashMap(gridSize); + int i = 0, k = 1; + for (Resource resource : resources) { + ExecutionContext context = new ExecutionContext(); + Assert.state(resource.exists(), "Resource does not exist: " + resource); + context.putString(keyName, resource.getFilename()); + context.putString("opFileName", "output" + k++ + ".xml"); + + map.put(PARTITION_KEY + i, context); + i++; + } + return map; + } + +} diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/SpringbatchPartitionConfig.java b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/SpringbatchPartitionConfig.java new file mode 100644 index 0000000000..fe8339a8b4 --- /dev/null +++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/SpringbatchPartitionConfig.java @@ -0,0 +1,169 @@ +package org.baeldung.spring_batch_intro.partitioner; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.text.ParseException; + +import javax.sql.DataSource; + +import org.baeldung.spring_batch_intro.model.Transaction; +import org.baeldung.spring_batch_intro.service.RecordFieldSetMapper; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; +import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.launch.support.SimpleJobLauncher; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.item.UnexpectedInputException; +import org.springframework.batch.item.file.FlatFileItemReader; +import org.springframework.batch.item.file.mapping.DefaultLineMapper; +import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; +import org.springframework.batch.item.xml.StaxEventItemWriter; +import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.core.task.TaskExecutor; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.jaxb.Jaxb2Marshaller; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.transaction.PlatformTransactionManager; + +@Configuration +@EnableBatchProcessing +public class SpringbatchPartitionConfig { + + @Autowired + ResourcePatternResolver resoursePatternResolver; + + @Autowired + private JobBuilderFactory jobs; + + @Autowired + private StepBuilderFactory steps; + + @Bean(name = "partitionerJob") + public Job partitionerJob() throws UnexpectedInputException, MalformedURLException, ParseException { + return jobs.get("partitionerJob") + .start(partitionStep()) + .build(); + } + + @Bean + public Step partitionStep() throws UnexpectedInputException, MalformedURLException, ParseException { + return steps.get("partitionStep") + .partitioner("slaveStep", partitioner()) + .step(slaveStep()) + .taskExecutor(taskExecutor()) + .build(); + } + + @Bean + public Step slaveStep() throws UnexpectedInputException, MalformedURLException, ParseException { + return steps.get("slaveStep") + . chunk(1) + .reader(itemReader(null)) + .writer(itemWriter(marshaller(), null)) + .build(); + } + + @Bean + public CustomMultiResourcePartitioner partitioner() { + CustomMultiResourcePartitioner partitioner = new CustomMultiResourcePartitioner(); + Resource[] resources; + try { + resources = resoursePatternResolver.getResources("file:src/main/resources/input/partitioner/*.csv"); + } catch (IOException e) { + throw new RuntimeException("I/O problems when resolving the input file pattern.", e); + } + partitioner.setResources(resources); + return partitioner; + } + + @Bean + @StepScope + public FlatFileItemReader itemReader(@Value("#{stepExecutionContext[fileName]}") String filename) throws UnexpectedInputException, ParseException { + FlatFileItemReader reader = new FlatFileItemReader(); + DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); + String[] tokens = { "username", "userid", "transactiondate", "amount" }; + tokenizer.setNames(tokens); + reader.setResource(new ClassPathResource("input/partitioner/" + filename)); + DefaultLineMapper lineMapper = new DefaultLineMapper(); + lineMapper.setLineTokenizer(tokenizer); + lineMapper.setFieldSetMapper(new RecordFieldSetMapper()); + reader.setLinesToSkip(1); + reader.setLineMapper(lineMapper); + return reader; + } + + @Bean(destroyMethod = "") + @StepScope + public StaxEventItemWriter itemWriter(Marshaller marshaller, @Value("#{stepExecutionContext[opFileName]}") String filename) throws MalformedURLException { + StaxEventItemWriter itemWriter = new StaxEventItemWriter<>(); + itemWriter.setMarshaller(marshaller); + itemWriter.setRootTagName("transactionRecord"); + itemWriter.setResource(new FileSystemResource("src/main/resources/output/" + filename)); + return itemWriter; + } + + @Bean + public Marshaller marshaller() { + Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); + marshaller.setClassesToBeBound(new Class[] { Transaction.class }); + return marshaller; + } + + @Bean + public TaskExecutor taskExecutor() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setMaxPoolSize(5); + taskExecutor.setCorePoolSize(5); + taskExecutor.setQueueCapacity(5); + taskExecutor.afterPropertiesSet(); + return taskExecutor; + } + + private JobRepository getJobRepository() throws Exception { + JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); + factory.setDataSource(dataSource()); + factory.setTransactionManager(getTransactionManager()); + // JobRepositoryFactoryBean's methods Throws Generic Exception, + // it would have been better to have a specific one + factory.afterPropertiesSet(); + return (JobRepository) factory.getObject(); + } + + private DataSource dataSource() { + EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); + EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.HSQL) + .addScript("classpath:org/springframework/batch/core/schema-drop-h2.sql") + .addScript("classpath:org/springframework/batch/core/schema-h2.sql") + .build(); + return db; + } + + private PlatformTransactionManager getTransactionManager() { + return new ResourcelessTransactionManager(); + } + + public JobLauncher getJobLauncher() throws Exception { + SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); + // SimpleJobLauncher's methods Throws Generic Exception, + // it would have been better to have a specific one + jobLauncher.setJobRepository(getJobRepository()); + jobLauncher.afterPropertiesSet(); + return jobLauncher; + } +} diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/SpringbatchPartitionerApp.java b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/SpringbatchPartitionerApp.java new file mode 100644 index 0000000000..1d6d922969 --- /dev/null +++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/SpringbatchPartitionerApp.java @@ -0,0 +1,28 @@ +package org.baeldung.spring_batch_intro.partitioner; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +public class SpringbatchPartitionerApp { + public static void main(final String[] args) { + // Spring Java config + final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + context.register(SpringbatchPartitionConfig.class); + context.refresh(); + + final JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher"); + final Job job = (Job) context.getBean("partitionerJob"); + System.out.println("Starting the batch job"); + try { + final JobExecution execution = jobLauncher.run(job, new JobParameters()); + System.out.println("Job Status : " + execution.getStatus()); + System.out.println("Job succeeded"); + } catch (final Exception e) { + e.printStackTrace(); + System.out.println("Job failed"); + } + } +} \ No newline at end of file diff --git a/spring-batch/src/main/resources/input/partitioner/record1.csv b/spring-batch/src/main/resources/input/partitioner/record1.csv new file mode 100644 index 0000000000..e554becb2a --- /dev/null +++ b/spring-batch/src/main/resources/input/partitioner/record1.csv @@ -0,0 +1,4 @@ +username, user_id, transaction_date, transaction_amount +devendra, 1234, 31/10/2015, 10000 +john, 2134, 3/12/2015, 12321 +robin, 2134, 2/02/2015, 23411 \ No newline at end of file diff --git a/spring-batch/src/main/resources/input/partitioner/record2.csv b/spring-batch/src/main/resources/input/partitioner/record2.csv new file mode 100644 index 0000000000..e554becb2a --- /dev/null +++ b/spring-batch/src/main/resources/input/partitioner/record2.csv @@ -0,0 +1,4 @@ +username, user_id, transaction_date, transaction_amount +devendra, 1234, 31/10/2015, 10000 +john, 2134, 3/12/2015, 12321 +robin, 2134, 2/02/2015, 23411 \ No newline at end of file diff --git a/spring-batch/src/main/resources/input/partitioner/record3.csv b/spring-batch/src/main/resources/input/partitioner/record3.csv new file mode 100644 index 0000000000..e554becb2a --- /dev/null +++ b/spring-batch/src/main/resources/input/partitioner/record3.csv @@ -0,0 +1,4 @@ +username, user_id, transaction_date, transaction_amount +devendra, 1234, 31/10/2015, 10000 +john, 2134, 3/12/2015, 12321 +robin, 2134, 2/02/2015, 23411 \ No newline at end of file diff --git a/spring-batch/src/main/resources/input/partitioner/record4.csv b/spring-batch/src/main/resources/input/partitioner/record4.csv new file mode 100644 index 0000000000..e554becb2a --- /dev/null +++ b/spring-batch/src/main/resources/input/partitioner/record4.csv @@ -0,0 +1,4 @@ +username, user_id, transaction_date, transaction_amount +devendra, 1234, 31/10/2015, 10000 +john, 2134, 3/12/2015, 12321 +robin, 2134, 2/02/2015, 23411 \ No newline at end of file diff --git a/spring-batch/src/main/resources/input/partitioner/record5.csv b/spring-batch/src/main/resources/input/partitioner/record5.csv new file mode 100644 index 0000000000..e554becb2a --- /dev/null +++ b/spring-batch/src/main/resources/input/partitioner/record5.csv @@ -0,0 +1,4 @@ +username, user_id, transaction_date, transaction_amount +devendra, 1234, 31/10/2015, 10000 +john, 2134, 3/12/2015, 12321 +robin, 2134, 2/02/2015, 23411 \ No newline at end of file diff --git a/spring-batch/src/main/resources/output/output1.xml b/spring-batch/src/main/resources/output/output1.xml new file mode 100644 index 0000000000..194b860813 --- /dev/null +++ b/spring-batch/src/main/resources/output/output1.xml @@ -0,0 +1,21 @@ + + + + 10000.0 + 2015-10-31T00:00:00+05:30 + 1234 + devendra + + + 12321.0 + 2015-12-03T00:00:00+05:30 + 2134 + john + + + 23411.0 + 2015-02-02T00:00:00+05:30 + 2134 + robin + + \ No newline at end of file diff --git a/spring-batch/src/main/resources/output/output2.xml b/spring-batch/src/main/resources/output/output2.xml new file mode 100644 index 0000000000..194b860813 --- /dev/null +++ b/spring-batch/src/main/resources/output/output2.xml @@ -0,0 +1,21 @@ + + + + 10000.0 + 2015-10-31T00:00:00+05:30 + 1234 + devendra + + + 12321.0 + 2015-12-03T00:00:00+05:30 + 2134 + john + + + 23411.0 + 2015-02-02T00:00:00+05:30 + 2134 + robin + + \ No newline at end of file diff --git a/spring-batch/src/main/resources/output/output3.xml b/spring-batch/src/main/resources/output/output3.xml new file mode 100644 index 0000000000..194b860813 --- /dev/null +++ b/spring-batch/src/main/resources/output/output3.xml @@ -0,0 +1,21 @@ + + + + 10000.0 + 2015-10-31T00:00:00+05:30 + 1234 + devendra + + + 12321.0 + 2015-12-03T00:00:00+05:30 + 2134 + john + + + 23411.0 + 2015-02-02T00:00:00+05:30 + 2134 + robin + + \ No newline at end of file diff --git a/spring-batch/src/main/resources/output/output4.xml b/spring-batch/src/main/resources/output/output4.xml new file mode 100644 index 0000000000..194b860813 --- /dev/null +++ b/spring-batch/src/main/resources/output/output4.xml @@ -0,0 +1,21 @@ + + + + 10000.0 + 2015-10-31T00:00:00+05:30 + 1234 + devendra + + + 12321.0 + 2015-12-03T00:00:00+05:30 + 2134 + john + + + 23411.0 + 2015-02-02T00:00:00+05:30 + 2134 + robin + + \ No newline at end of file diff --git a/spring-batch/src/main/resources/output/output5.xml b/spring-batch/src/main/resources/output/output5.xml new file mode 100644 index 0000000000..194b860813 --- /dev/null +++ b/spring-batch/src/main/resources/output/output5.xml @@ -0,0 +1,21 @@ + + + + 10000.0 + 2015-10-31T00:00:00+05:30 + 1234 + devendra + + + 12321.0 + 2015-12-03T00:00:00+05:30 + 2134 + john + + + 23411.0 + 2015-02-02T00:00:00+05:30 + 2134 + robin + + \ No newline at end of file diff --git a/spring-jpa/pom.xml b/spring-jpa/pom.xml index 1a1e6b3152..6a67d44b48 100644 --- a/spring-jpa/pom.xml +++ b/spring-jpa/pom.xml @@ -102,6 +102,7 @@ javax.servlet servlet-api + provided ${javax.servlet.servlet-api.version} diff --git a/spring-rest/src/main/java/org/baeldung/web/controller/redirect/RedirectController.java b/spring-rest/src/main/java/org/baeldung/web/controller/redirect/RedirectController.java index 472c0c8bf5..59868593a3 100644 --- a/spring-rest/src/main/java/org/baeldung/web/controller/redirect/RedirectController.java +++ b/spring-rest/src/main/java/org/baeldung/web/controller/redirect/RedirectController.java @@ -1,11 +1,15 @@ package org.baeldung.web.controller.redirect; +import javax.servlet.http.HttpServletRequest; + +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.View; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.view.RedirectView; @@ -49,4 +53,16 @@ public class RedirectController { model.addAttribute("redirectionAttribute", flashAttribute); return new ModelAndView("redirection", model); } + + @RequestMapping(value = "/redirectPostToPost", method = RequestMethod.POST) + public ModelAndView redirectPostToPost(HttpServletRequest request) { + request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.TEMPORARY_REDIRECT); + return new ModelAndView("redirect:/redirectedPostToPost"); + } + + @RequestMapping(value = "/redirectedPostToPost", method = RequestMethod.POST) + public ModelAndView redirectedPostToPost() { + return new ModelAndView("redirection"); + } + } \ No newline at end of file