Merge remote-tracking branch 'upstream/master'

This commit is contained in:
amdegregorio 2019-01-20 15:06:47 -05:00
commit d381e131ea
71 changed files with 2048 additions and 307 deletions

View File

@ -0,0 +1,46 @@
package com.baeldung.algorithms.enumstatemachine;
public enum LeaveRequestState {
Submitted {
@Override
public LeaveRequestState nextState() {
System.out.println("Starting the Leave Request and sending to Team Leader for approval.");
return Escalated;
}
@Override
public String responsiblePerson() {
return "Employee";
}
},
Escalated {
@Override
public LeaveRequestState nextState() {
System.out.println("Reviewing the Leave Request and escalating to Department Manager.");
return Approved;
}
@Override
public String responsiblePerson() {
return "Team Leader";
}
},
Approved {
@Override
public LeaveRequestState nextState() {
System.out.println("Approving the Leave Request.");
return this;
}
@Override
public String responsiblePerson() {
return "Department Manager";
}
};
public abstract String responsiblePerson();
public abstract LeaveRequestState nextState();
}

View File

@ -0,0 +1,37 @@
package com.baeldung.algorithms.enumstatemachine;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class LeaveRequestStateUnitTest {
@Test
public void givenLeaveRequest_whenStateEscalated_thenResponsibleIsTeamLeader() {
LeaveRequestState state = LeaveRequestState.Escalated;
assertEquals(state.responsiblePerson(), "Team Leader");
}
@Test
public void givenLeaveRequest_whenStateApproved_thenResponsibleIsDepartmentManager() {
LeaveRequestState state = LeaveRequestState.Approved;
assertEquals(state.responsiblePerson(), "Department Manager");
}
@Test
public void givenLeaveRequest_whenNextStateIsCalled_thenStateIsChanged() {
LeaveRequestState state = LeaveRequestState.Submitted;
state = state.nextState();
assertEquals(state, LeaveRequestState.Escalated);
state = state.nextState();
assertEquals(state, LeaveRequestState.Approved);
state = state.nextState();
assertEquals(state, LeaveRequestState.Approved);
}
}

View File

@ -26,3 +26,4 @@
- [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist)
- [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections)
- [Intersection of Two Lists in Java](https://www.baeldung.com/java-lists-intersection)
- [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist)

View File

@ -14,4 +14,5 @@
- [ExecutorService - Waiting for Threads to Finish](http://www.baeldung.com/java-executor-wait-for-threads)
- [wait and notify() Methods in Java](http://www.baeldung.com/java-wait-notify)
- [Life Cycle of a Thread in Java](http://www.baeldung.com/java-thread-lifecycle)
- [Runnable vs. Callable in Java](http://www.baeldung.com/java-runnable-callable)
- [Runnable vs. Callable in Java](http://www.baeldung.com/java-runnable-callable)
- [What is Thread-Safety and How to Achieve it](https://www.baeldung.com/java-thread-safety)

View File

@ -62,7 +62,7 @@ public class NewDirectoryUnitTest {
@Test
public void givenUnexistingNestedDirectories_whenMkdirs_thenTrue() {
File newDirectory = new File(TEMP_DIRECTORY, "new_directory");
File newDirectory = new File(System.getProperty("java.io.tmpdir") + File.separator + "new_directory");
File nestedDirectory = new File(newDirectory, "nested_directory");
assertFalse(newDirectory.exists());
assertFalse(nestedDirectory.exists());

View File

@ -1,60 +1,56 @@
package org.baeldung.java.io;
import com.google.common.io.ByteSource;
import com.google.common.io.ByteStreams;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;
import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static java.nio.channels.Channels.newChannel;
import static org.junit.Assert.assertEquals;
class InputStreamToByteBufferUnitTest {
public class InputStreamToByteBufferUnitTest {
@Test
public void givenUsingCoreClasses_whenWritingAFileIntoAByteBuffer_thenBytesLengthMustMatch() throws IOException {
File inputFile = getFile();
ByteBuffer bufferByte = ByteBuffer.allocate((int) inputFile.length());
FileInputStream in = new FileInputStream(inputFile);
in.getChannel().read(bufferByte);
public void givenUsingCoreClasses_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException {
byte[] input = new byte[] { 0, 1, 2 };
InputStream initialStream = new ByteArrayInputStream(input);
ByteBuffer byteBuffer = ByteBuffer.allocate(3);
while (initialStream.available() > 0) {
byteBuffer.put((byte) initialStream.read());
}
assertEquals(bufferByte.position(), inputFile.length());
assertEquals(byteBuffer.position(), input.length);
}
@Test
public void givenUsingCommonsIo_whenWritingAFileIntoAByteBuffer_thenBytesLengthMustMatch() throws IOException {
File inputFile = getFile();
ByteBuffer bufferByte = ByteBuffer.allocateDirect((int) inputFile.length());
ReadableByteChannel readableByteChannel = new FileInputStream(inputFile).getChannel();
IOUtils.readFully(readableByteChannel, bufferByte);
assertEquals(bufferByte.position(), inputFile.length());
}
@Test
public void givenUsingGuava_whenWritingAFileIntoAByteBuffer_thenBytesLengthMustMatch() throws IOException {
File inputFile = getFile();
FileInputStream in = new FileInputStream(inputFile);
byte[] targetArray = ByteStreams.toByteArray(in);
public void givenUsingGuava__whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException {
InputStream initialStream = ByteSource
.wrap(new byte[] { 0, 1, 2 })
.openStream();
byte[] targetArray = ByteStreams.toByteArray(initialStream);
ByteBuffer bufferByte = ByteBuffer.wrap(targetArray);
bufferByte.rewind();
while (bufferByte.hasRemaining()) {
bufferByte.get();
}
assertEquals(bufferByte.position(), inputFile.length());
assertEquals(bufferByte.position(), targetArray.length);
}
private File getFile() {
ClassLoader classLoader = new InputStreamToByteBufferUnitTest().getClass().getClassLoader();
@Test
public void givenUsingCommonsIo_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException {
byte[] input = new byte[] { 0, 1, 2 };
InputStream initialStream = new ByteArrayInputStream(input);
ByteBuffer byteBuffer = ByteBuffer.allocate(3);
ReadableByteChannel channel = newChannel(initialStream);
IOUtils.readFully(channel, byteBuffer);
String fileName = "frontenac-2257154_960_720.jpg";
return new File(classLoader.getResource(fileName).getFile());
assertEquals(byteBuffer.position(), input.length);
}
}

View File

@ -0,0 +1,61 @@
package com.baeldung.forEach
class Country(val name : String, val cities : List<City>)
class City(val name : String, val streets : List<String>)
class World {
private val streetsOfAmsterdam = listOf("Herengracht", "Prinsengracht")
private val streetsOfBerlin = listOf("Unter den Linden","Tiergarten")
private val streetsOfMaastricht = listOf("Grote Gracht", "Vrijthof")
private val countries = listOf(
Country("Netherlands", listOf(City("Maastricht", streetsOfMaastricht),
City("Amsterdam", streetsOfAmsterdam))),
Country("Germany", listOf(City("Berlin", streetsOfBerlin))))
fun allCountriesIt() {
countries.forEach { println(it.name) }
}
fun allCountriesItExplicit() {
countries.forEach { it -> println(it.name) }
}
//here we cannot refer to 'it' anymore inside the forEach
fun allCountriesExplicit() {
countries.forEach { c -> println(c.name) }
}
fun allNested() {
countries.forEach {
println(it.name)
it.cities.forEach {
println(" ${it.name}")
it.streets.forEach { println(" $it") }
}
}
}
fun allTable() {
countries.forEach { c ->
c.cities.forEach { p ->
p.streets.forEach { println("${c.name} ${p.name} $it") }
}
}
}
}
fun main(args : Array<String>) {
val world = World()
world.allCountriesExplicit()
world.allNested()
world.allTable()
}

View File

@ -0,0 +1,51 @@
package com.baeldung.voidtypes
import org.junit.jupiter.api.Test
import kotlin.test.assertNull
import kotlin.test.assertTrue
class VoidTypesUnitTest {
fun returnTypeAsVoid(): Void? {
println("Function can have Void as return type")
return null
}
fun unitReturnTypeForNonMeaningfulReturns(): Unit {
println("No meaningful return")
}
fun unitReturnTypeIsImplicit() {
println("Unit Return type is implicit")
}
fun alwaysThrowException(): Nothing {
throw IllegalArgumentException()
}
fun invokeANothingOnlyFunction() {
alwaysThrowException()
var name = "Tom"
}
@Test
fun givenJavaVoidFunction_thenMappedToKotlinUnit() {
assertTrue(System.out.println() is Unit)
}
@Test
fun givenVoidReturnType_thenReturnsNullOnly() {
assertNull(returnTypeAsVoid())
}
@Test
fun givenUnitReturnTypeDeclared_thenReturnsOfTypeUnit() {
assertTrue(unitReturnTypeForNonMeaningfulReturns() is Unit)
}
@Test
fun givenUnitReturnTypeNotDeclared_thenReturnsOfTypeUnit() {
assertTrue(unitReturnTypeIsImplicit() is Unit)
}
}

View File

@ -32,7 +32,7 @@ public class Customer {
return this.points > points;
}
public boolean hasOverThousandPoints() {
public boolean hasOverHundredPoints() {
return this.points > 100;
}

View File

@ -0,0 +1,8 @@
package com.baeldung.stream.sum;
public class ArithmeticUtils {
public static int add(int a, int b) {
return a + b;
}
}

View File

@ -0,0 +1,31 @@
package com.baeldung.stream.sum;
public class Item {
private int id;
private Integer price;
public Item(int id, Integer price) {
super();
this.id = id;
this.price = price;
}
// Standard getters and setters
public long getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
}

View File

@ -0,0 +1,59 @@
package com.baeldung.stream.sum;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class StreamSumCalculator {
public static Integer getSumUsingCustomizedAccumulator(List<Integer> integers) {
return integers.stream()
.reduce(0, ArithmeticUtils::add);
}
public static Integer getSumUsingJavaAccumulator(List<Integer> integers) {
return integers.stream()
.reduce(0, Integer::sum);
}
public static Integer getSumUsingReduce(List<Integer> integers) {
return integers.stream()
.reduce(0, (a, b) -> a + b);
}
public static Integer getSumUsingCollect(List<Integer> integers) {
return integers.stream()
.collect(Collectors.summingInt(Integer::intValue));
}
public static Integer getSumUsingSum(List<Integer> integers) {
return integers.stream()
.mapToInt(Integer::intValue)
.sum();
}
public static Integer getSumOfMapValues(Map<Object, Integer> map) {
return map.values()
.stream()
.mapToInt(Integer::valueOf)
.sum();
}
public static Integer getSumIntegersFromString(String str) {
Integer sum = Arrays.stream(str.split(" "))
.filter((s) -> s.matches("\\d+"))
.mapToInt(Integer::valueOf)
.sum();
return sum;
}
}

View File

@ -0,0 +1,38 @@
package com.baeldung.stream.sum;
import java.util.List;
import java.util.stream.Collectors;
public class StreamSumCalculatorWithObject {
public static Integer getSumUsingCustomizedAccumulator(List<Item> items) {
return items.stream()
.map(x -> x.getPrice())
.reduce(0, ArithmeticUtils::add);
}
public static Integer getSumUsingJavaAccumulator(List<Item> items) {
return items.stream()
.map(x -> x.getPrice())
.reduce(0, Integer::sum);
}
public static Integer getSumUsingReduce(List<Item> items) {
return items.stream()
.map(item -> item.getPrice())
.reduce(0, (a, b) -> a + b);
}
public static Integer getSumUsingCollect(List<Item> items) {
return items.stream()
.map(x -> x.getPrice())
.collect(Collectors.summingInt(Integer::intValue));
}
public static Integer getSumUsingSum(List<Item> items) {
return items.stream()
.mapToInt(x -> x.getPrice())
.sum();
}
}

View File

@ -0,0 +1,72 @@
package com.baeldung.stream.filter;
import org.junit.Test;
import org.junit.Before;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class StreamCountUnitTest {
private List<Customer> customers;
@Before
public void setUp() {
Customer john = new Customer("John P.", 15, "https://images.unsplash.com/photo-1543320485-d0d5a49c2b2e");
Customer sarah = new Customer("Sarah M.", 200);
Customer charles = new Customer("Charles B.", 150);
Customer mary = new Customer("Mary T.", 1, "https://images.unsplash.com/photo-1543297057-25167dfc180e");
customers = Arrays.asList(john, sarah, charles, mary);
}
@Test
public void givenListOfCustomers_whenCount_thenGetListSize() {
long count = customers
.stream()
.count();
assertThat(count).isEqualTo(4L);
}
@Test
public void givenListOfCustomers_whenFilterByPointsOver100AndCount_thenGetTwo() {
long countBigCustomers = customers
.stream()
.filter(c -> c.getPoints() > 100)
.count();
assertThat(countBigCustomers).isEqualTo(2L);
}
@Test
public void givenListOfCustomers_whenFilterByPointsAndNameAndCount_thenGetOne() {
long count = customers
.stream()
.filter(c -> c.getPoints() > 10 && c.getName().startsWith("Charles"))
.count();
assertThat(count).isEqualTo(1L);
}
@Test
public void givenListOfCustomers_whenNoneMatchesFilterAndCount_thenGetZero() {
long count = customers
.stream()
.filter(c -> c.getPoints() > 500)
.count();
assertThat(count).isEqualTo(0L);
}
@Test
public void givenListOfCustomers_whenUsingMethodOverHundredPointsAndCount_thenGetTwo() {
long count = customers
.stream()
.filter(Customer::hasOverHundredPoints)
.count();
assertThat(count).isEqualTo(2L);
}
}

View File

@ -62,7 +62,7 @@ public class StreamFilterUnitTest {
List<Customer> customersWithMoreThan100Points = customers
.stream()
.filter(Customer::hasOverThousandPoints)
.filter(Customer::hasOverHundredPoints)
.collect(Collectors.toList());
assertThat(customersWithMoreThan100Points).hasSize(2);
@ -81,7 +81,7 @@ public class StreamFilterUnitTest {
.flatMap(c -> c
.map(Stream::of)
.orElseGet(Stream::empty))
.filter(Customer::hasOverThousandPoints)
.filter(Customer::hasOverHundredPoints)
.collect(Collectors.toList());
assertThat(customersWithMoreThan100Points).hasSize(2);
@ -156,4 +156,5 @@ public class StreamFilterUnitTest {
})
.collect(Collectors.toList())).isInstanceOf(RuntimeException.class);
}
}

View File

@ -0,0 +1,136 @@
package com.baeldung.stream.sum;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
public class StreamSumUnitTest {
@Test
public void givenListOfIntegersWhenSummingUsingCustomizedAccumulatorThenCorrectValueReturned() {
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
Integer sum = StreamSumCalculator.getSumUsingCustomizedAccumulator(integers);
assertEquals(15, sum.intValue());
}
@Test
public void givenListOfIntegersWhenSummingUsingJavaAccumulatorThenCorrectValueReturned() {
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
Integer sum = StreamSumCalculator.getSumUsingJavaAccumulator(integers);
assertEquals(15, sum.intValue());
}
@Test
public void givenListOfIntegersWhenSummingUsingReduceThenCorrectValueReturned() {
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
Integer sum = StreamSumCalculator.getSumUsingReduce(integers);
assertEquals(15, sum.intValue());
}
@Test
public void givenListOfIntegersWhenSummingUsingCollectThenCorrectValueReturned() {
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
Integer sum = StreamSumCalculator.getSumUsingCollect(integers);
assertEquals(15, sum.intValue());
}
@Test
public void givenListOfIntegersWhenSummingUsingSumThenCorrectValueReturned() {
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
Integer sum = StreamSumCalculator.getSumUsingSum(integers);
assertEquals(15, sum.intValue());
}
@Test
public void givenListOfItemsWhenSummingUsingCustomizedAccumulatorThenCorrectValueReturned() {
Item item1 = new Item(1, 10);
Item item2 = new Item(2, 15);
Item item3 = new Item(3, 25);
Item item4 = new Item(4, 40);
List<Item> items = Arrays.asList(item1, item2, item3, item4);
Integer sum = StreamSumCalculatorWithObject.getSumUsingCustomizedAccumulator(items);
assertEquals(90, sum.intValue());
}
@Test
public void givenListOfItemsWhenSummingUsingJavaAccumulatorThenCorrectValueReturned() {
Item item1 = new Item(1, 10);
Item item2 = new Item(2, 15);
Item item3 = new Item(3, 25);
Item item4 = new Item(4, 40);
List<Item> items = Arrays.asList(item1, item2, item3, item4);
Integer sum = StreamSumCalculatorWithObject.getSumUsingJavaAccumulator(items);
assertEquals(90, sum.intValue());
}
@Test
public void givenListOfItemsWhenSummingUsingReduceThenCorrectValueReturned() {
Item item1 = new Item(1, 10);
Item item2 = new Item(2, 15);
Item item3 = new Item(3, 25);
Item item4 = new Item(4, 40);
List<Item> items = Arrays.asList(item1, item2, item3, item4);
Integer sum = StreamSumCalculatorWithObject.getSumUsingReduce(items);
assertEquals(90, sum.intValue());
}
@Test
public void givenListOfItemsWhenSummingUsingCollectThenCorrectValueReturned() {
Item item1 = new Item(1, 10);
Item item2 = new Item(2, 15);
Item item3 = new Item(3, 25);
Item item4 = new Item(4, 40);
List<Item> items = Arrays.asList(item1, item2, item3, item4);
Integer sum = StreamSumCalculatorWithObject.getSumUsingCollect(items);
assertEquals(90, sum.intValue());
}
@Test
public void givenListOfItemsWhenSummingUsingSumThenCorrectValueReturned() {
Item item1 = new Item(1, 10);
Item item2 = new Item(2, 15);
Item item3 = new Item(3, 25);
Item item4 = new Item(4, 40);
List<Item> items = Arrays.asList(item1, item2, item3, item4);
Integer sum = StreamSumCalculatorWithObject.getSumUsingSum(items);
assertEquals(90, sum.intValue());
}
@Test
public void givenMapWhenSummingThenCorrectValueReturned() {
Map<Object, Integer> map = new HashMap<Object, Integer>();
map.put(1, 10);
map.put(2, 15);
map.put(3, 25);
map.put(4, 40);
Integer sum = StreamSumCalculator.getSumOfMapValues(map);
assertEquals(90, sum.intValue());
}
@Test
public void givenStringWhenSummingThenCorrectValueReturned() {
String string = "Item1 10 Item2 25 Item3 30 Item4 45";
Integer sum = StreamSumCalculator.getSumIntegersFromString(string);
assertEquals(110, sum.intValue());
}
}

View File

@ -15,3 +15,4 @@
- [Intro to Apache Storm](https://www.baeldung.com/apache-storm)
- [Guide to Ebean ORM](https://www.baeldung.com/ebean-orm)
- [Introduction to Kafka Connectors](https://www.baeldung.com/kafka-connectors-guide)
- [Kafka Connect Example with MQTT and MongoDB](https://www.baeldung.com/kafka-connect-mqtt-mongodb)

View File

@ -1 +1,5 @@
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

View File

@ -675,6 +675,30 @@
<version>${mockftpserver.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-tcp</artifactId>
<version>${smack.version}</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-im</artifactId>
<version>${smack.version}</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-extensions</artifactId>
<version>${smack.version}</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-java7</artifactId>
<version>${smack.version}</version>
</dependency>
</dependencies>
<repositories>
@ -896,6 +920,7 @@
<derive4j.version>1.1.0</derive4j.version>
<mockftpserver.version>2.7.1</mockftpserver.version>
<commons-net.version>3.6</commons-net.version>
<smack.version>4.3.1</smack.version>
</properties>
</project>

View File

@ -0,0 +1,40 @@
package com.baeldung.smack;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.chat2.Chat;
import org.jivesoftware.smack.chat2.ChatManager;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jxmpp.jid.impl.JidCreate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class StanzaThread implements Runnable {
private Logger logger = LoggerFactory.getLogger(StanzaThread.class);
@Override
public void run() {
XMPPTCPConnectionConfiguration config = null;
try {
config = XMPPTCPConnectionConfiguration.builder()
.setUsernameAndPassword("baeldung2","baeldung2")
.setXmppDomain("jabb3r.org")
.setHost("jabb3r.org")
.build();
AbstractXMPPConnection connection = new XMPPTCPConnection(config);
connection.connect();
connection.login();
ChatManager chatManager = ChatManager.getInstanceFor(connection);
Chat chat = chatManager.chatWith(JidCreate.from("baeldung@jabb3r.org").asEntityBareJidOrThrow());
chat.send("Hello!");
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,85 @@
package com.baeldung.smack;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.chat2.ChatManager;
import org.jivesoftware.smack.filter.StanzaTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.jxmpp.stringprep.XmppStringprepException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
public class SmackIntegrationTest {
private static AbstractXMPPConnection connection;
private Logger logger = LoggerFactory.getLogger(SmackIntegrationTest.class);
@BeforeClass
public static void setup() throws IOException, InterruptedException, XMPPException, SmackException {
XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
.setUsernameAndPassword("baeldung","baeldung")
.setXmppDomain("jabb3r.org")
.setHost("jabb3r.org")
.build();
XMPPTCPConnectionConfiguration config2 = XMPPTCPConnectionConfiguration.builder()
.setUsernameAndPassword("baeldung2","baeldung2")
.setXmppDomain("jabb3r.org")
.setHost("jabb3r.org")
.build();
connection = new XMPPTCPConnection(config);
connection.connect();
connection.login();
}
@Test
public void whenSendMessageWithChat_thenReceiveMessage() throws XmppStringprepException, InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
ChatManager chatManager = ChatManager.getInstanceFor(connection);
final String[] expected = {null};
new StanzaThread().run();
chatManager.addIncomingListener((entityBareJid, message, chat) -> {
logger.info("Message arrived: " + message.getBody());
expected[0] = message.getBody();
latch.countDown();
});
latch.await();
Assert.assertEquals("Hello!", expected[0]);
}
@Test
public void whenSendMessage_thenReceiveMessageWithFilter() throws XmppStringprepException, InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
final String[] expected = {null};
new StanzaThread().run();
connection.addAsyncStanzaListener(stanza -> {
if (stanza instanceof Message) {
Message message = (Message) stanza;
expected[0] = message.getBody();
latch.countDown();
}
}, StanzaTypeFilter.MESSAGE);
latch.await();
Assert.assertEquals("Hello!", expected[0]);
}
}

View File

@ -76,11 +76,11 @@
<properties>
<!-- lombok: https://projectlombok.org/changelog.html -->
<lombok.version>1.16.18</lombok.version>
<lombok.version>1.18.4</lombok.version>
<!-- various -->
<hibernate-jpa-2.1-api.version>1.0.0.Final</hibernate-jpa-2.1-api.version>
<!-- delombok maven plugin -->
<delombok-maven-plugin.version>1.16.10.0</delombok-maven-plugin.version>
<delombok-maven-plugin.version>1.18.4.0</delombok-maven-plugin.version>
<assertj-core.version>3.8.0</assertj-core.version>
</properties>

View File

@ -4,8 +4,8 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>java-jpa</artifactId>
<name>java-jpa</name>
<name>java-jpa</name>
<parent>
<artifactId>parent-modules</artifactId>
<groupId>com.baeldung</groupId>
@ -24,10 +24,34 @@
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
<!--Compile time JPA API-->
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<!--Runtime JPA implementation-->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>${eclipselink.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<properties>
<hibernate.version>5.3.1.Final</hibernate.version>
<hibernate.version>5.4.0.Final</hibernate.version>
<h2.version>1.4.197</h2.version>
<eclipselink.version>2.7.4-RC1</eclipselink.version>
<postgres.version>42.2.5</postgres.version>
</properties>
</project>

View File

@ -0,0 +1,68 @@
package com.baeldung.jpa.datetime;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.*;
import java.util.Calendar;
public class DateTimeEntityRepository {
private EntityManagerFactory emf = null;
public DateTimeEntityRepository() {
emf = Persistence.createEntityManagerFactory("java8-datetime-postgresql");
}
public JPA22DateTimeEntity find(Long id) {
EntityManager entityManager = emf.createEntityManager();
JPA22DateTimeEntity dateTimeTypes = entityManager.find(JPA22DateTimeEntity.class, id);
entityManager.close();
return dateTimeTypes;
}
public void save(Long id) {
JPA22DateTimeEntity dateTimeTypes = new JPA22DateTimeEntity();
dateTimeTypes.setId(id);
//java.sql types: date/time
dateTimeTypes.setSqlTime(Time.valueOf(LocalTime.now()));
dateTimeTypes.setSqlDate(Date.valueOf(LocalDate.now()));
dateTimeTypes.setSqlTimestamp(Timestamp.valueOf(LocalDateTime.now()));
//java.util types: date/calendar
java.util.Date date = new java.util.Date();
dateTimeTypes.setUtilTime(date);
dateTimeTypes.setUtilDate(date);
dateTimeTypes.setUtilTimestamp(date);
//Calendar
Calendar calendar = Calendar.getInstance();
dateTimeTypes.setCalendarTime(calendar);
dateTimeTypes.setCalendarDate(calendar);
dateTimeTypes.setCalendarTimestamp(calendar);
//java.time types
dateTimeTypes.setLocalTime(LocalTime.now());
dateTimeTypes.setLocalDate(LocalDate.now());
dateTimeTypes.setLocalDateTime(LocalDateTime.now());
//java.time types with offset
dateTimeTypes.setOffsetTime(OffsetTime.now());
dateTimeTypes.setOffsetDateTime(OffsetDateTime.now());
EntityManager entityManager = emf.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist(dateTimeTypes);
entityManager.getTransaction().commit();
entityManager.close();
}
public void clean() {
emf.close();
}
}

View File

@ -0,0 +1,176 @@
package com.baeldung.jpa.datetime;
import javax.persistence.*;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.*;
import java.util.Calendar;
@Entity
public class JPA22DateTimeEntity {
@Id
private Long id;
//java.sql types
private Time sqlTime;
private Date sqlDate;
private Timestamp sqlTimestamp;
//java.util types
@Temporal(TemporalType.TIME)
private java.util.Date utilTime;
@Temporal(TemporalType.DATE)
private java.util.Date utilDate;
@Temporal(TemporalType.TIMESTAMP)
private java.util.Date utilTimestamp;
//Calendar
@Temporal(TemporalType.TIME)
private Calendar calendarTime;
@Temporal(TemporalType.DATE)
private Calendar calendarDate;
@Temporal(TemporalType.TIMESTAMP)
private Calendar calendarTimestamp;
// java.time types
@Column(name = "local_time", columnDefinition = "TIME")
private LocalTime localTime;
@Column(name = "local_date", columnDefinition = "DATE")
private LocalDate localDate;
@Column(name = "local_date_time", columnDefinition = "TIMESTAMP")
private LocalDateTime localDateTime;
@Column(name = "offset_time", columnDefinition = "TIME WITH TIME ZONE")
private OffsetTime offsetTime;
@Column(name = "offset_date_time", columnDefinition = "TIMESTAMP WITH TIME ZONE")
private OffsetDateTime offsetDateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Time getSqlTime() {
return sqlTime;
}
public void setSqlTime(Time sqlTime) {
this.sqlTime = sqlTime;
}
public Date getSqlDate() {
return sqlDate;
}
public void setSqlDate(Date sqlDate) {
this.sqlDate = sqlDate;
}
public Timestamp getSqlTimestamp() {
return sqlTimestamp;
}
public void setSqlTimestamp(Timestamp sqlTimestamp) {
this.sqlTimestamp = sqlTimestamp;
}
public java.util.Date getUtilTime() {
return utilTime;
}
public void setUtilTime(java.util.Date utilTime) {
this.utilTime = utilTime;
}
public java.util.Date getUtilDate() {
return utilDate;
}
public void setUtilDate(java.util.Date utilDate) {
this.utilDate = utilDate;
}
public java.util.Date getUtilTimestamp() {
return utilTimestamp;
}
public void setUtilTimestamp(java.util.Date utilTimestamp) {
this.utilTimestamp = utilTimestamp;
}
public Calendar getCalendarTime() {
return calendarTime;
}
public void setCalendarTime(Calendar calendarTime) {
this.calendarTime = calendarTime;
}
public Calendar getCalendarDate() {
return calendarDate;
}
public void setCalendarDate(Calendar calendarDate) {
this.calendarDate = calendarDate;
}
public Calendar getCalendarTimestamp() {
return calendarTimestamp;
}
public void setCalendarTimestamp(Calendar calendarTimestamp) {
this.calendarTimestamp = calendarTimestamp;
}
public LocalTime getLocalTime() {
return localTime;
}
public void setLocalTime(LocalTime localTime) {
this.localTime = localTime;
}
public LocalDate getLocalDate() {
return localDate;
}
public void setLocalDate(LocalDate localDate) {
this.localDate = localDate;
}
public LocalDateTime getLocalDateTime() {
return localDateTime;
}
public void setLocalDateTime(LocalDateTime localDateTime) {
this.localDateTime = localDateTime;
}
public OffsetTime getOffsetTime() {
return offsetTime;
}
public void setOffsetTime(OffsetTime offsetTime) {
this.offsetTime = offsetTime;
}
public OffsetDateTime getOffsetDateTime() {
return offsetDateTime;
}
public void setOffsetDateTime(OffsetDateTime offsetDateTime) {
this.offsetDateTime = offsetDateTime;
}
}

View File

@ -0,0 +1,18 @@
package com.baeldung.jpa.datetime;
public class MainApp {
public static void main(String... args) {
DateTimeEntityRepository dateTimeEntityRepository = new DateTimeEntityRepository();
//Persist
dateTimeEntityRepository.save(100L);
//Find
JPA22DateTimeEntity dateTimeEntity = dateTimeEntityRepository.find(100L);
dateTimeEntityRepository.clean();
}
}

View File

@ -2,12 +2,14 @@
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
version="2.2">
<persistence-unit name="java-jpa-scheduled-day">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.baeldung.sqlresultsetmapping.ScheduledDay</class>
<class>com.baeldung.sqlresultsetmapping.Employee</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url"
@ -24,6 +26,7 @@
<persistence-unit name="jpa-h2">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.baeldung.jpa.stringcast.Message</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test"/>
@ -39,6 +42,7 @@
<persistence-unit name="jpa-db">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.baeldung.jpa.model.Car</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/baeldung"/>
@ -66,4 +70,22 @@
</properties>
</persistence-unit>
<persistence-unit name="java8-datetime-postgresql" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.baeldung.jpa.datetime.JPA22DateTimeEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/java8-datetime2"/>
<property name="javax.persistence.jdbc.user" value="postgres"/>
<property name="javax.persistence.jdbc.password" value="postgres"/>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<!-- configure logging -->
<property name="eclipselink.logging.level" value="INFO"/>
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
</properties>
</persistence-unit>
</persistence>

View File

@ -5,3 +5,5 @@
- [Quick Guide on data.sql and schema.sql Files in Spring Boot](http://www.baeldung.com/spring-boot-data-sql-and-schema-sql)
- [Configuring a Tomcat Connection Pool in Spring Boot](https://www.baeldung.com/spring-boot-tomcat-connection-pool)
- [Hibernate Field Naming with Spring Boot](https://www.baeldung.com/hibernate-field-naming-spring-boot)
- [Integrating Spring Boot with HSQLDB](https://www.baeldung.com/spring-boot-hsqldb)

View File

@ -0,0 +1,27 @@
package com.baeldung.springbootdatasourceconfig.application;
import com.baeldung.springbootdatasourceconfig.application.entities.User;
import com.baeldung.springbootdatasourceconfig.application.repositories.UserRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public CommandLineRunner run(UserRepository userRepository) throws Exception {
return (String[] args) -> {
User user1 = new User("John", "john@domain.com");
User user2 = new User("Julie", "julie@domain.com");
userRepository.save(user1);
userRepository.save(user2);
userRepository.findAll().forEach(user -> System.out.println(user.getName()));
};
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.springbootdatasourceconfig.application.datasources;
import javax.sql.DataSource;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DataSourceBean {
@Bean
public DataSource getDataSource() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName("org.h2.Driver");
dataSourceBuilder.url("jdbc:h2:mem:test");
dataSourceBuilder.username("SA");
dataSourceBuilder.password("");
return dataSourceBuilder.build();
}
}

View File

@ -0,0 +1,46 @@
package com.baeldung.springbootdatasourceconfig.application.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private String email;
public User(){}
public User(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" + "id=" + id + ", name=" + name + ", email=" + email + '}';
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.springbootdatasourceconfig.application.repositories;
import com.baeldung.springbootdatasourceconfig.application.entities.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends CrudRepository<User, Long> {}

View File

@ -0,0 +1,28 @@
package com.baeldung.springbootdatasourceconfig.tests;
import com.baeldung.springbootdatasourceconfig.application.entities.User;
import com.baeldung.springbootdatasourceconfig.application.repositories.UserRepository;
import java.util.List;
import java.util.Optional;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@DataJpaTest
public class UserRepositoryIntegrationTest {
@Autowired
private UserRepository userRepository;
@Test
public void whenCalledSave_thenCorrectNumberOfUsers() {
userRepository.save(new User("Bob", "bob@domain.com"));
List<User> users = (List<User>) userRepository.findAll();
assertThat(users.size()).isEqualTo(1);
}
}

View File

@ -1,3 +1,4 @@
Module for the articles that are part of the Spring REST E-book:
1. [Bootstrap a Web Application with Spring 5](https://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration)
2. [Error Handling for REST with Spring](http://www.baeldung.com/exception-handling-for-rest-with-spring)

View File

@ -20,12 +20,30 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>${htmlunit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
@ -39,5 +57,6 @@
<properties>
<start-class>com.baeldung.SpringBootRestApplication</start-class>
<htmlunit.version>2.32</htmlunit.version>
</properties>
</project>

View File

@ -1,4 +1,4 @@
package com.baeldung;
package com.baeldung.web;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

View File

@ -0,0 +1,23 @@
package com.baeldung.web.config;
import java.util.Map;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;
@Component
public class MyCustomErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);
errorAttributes.put("locale", webRequest.getLocale()
.toString());
errorAttributes.remove("error");
errorAttributes.put("cause", errorAttributes.get("message"));
errorAttributes.remove("message");
errorAttributes.put("status", String.valueOf(errorAttributes.get("status")));
return errorAttributes;
}
}

View File

@ -0,0 +1,31 @@
package com.baeldung.web.config;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
@Component
public class MyErrorController extends BasicErrorController {
public MyErrorController(ErrorAttributes errorAttributes) {
super(errorAttributes, new ErrorProperties());
}
@RequestMapping(produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<Map<String, Object>> xmlError(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.APPLICATION_XML));
body.put("xmlkey", "the XML response is different!");
HttpStatus status = getStatus(request);
return new ResponseEntity<>(body, status);
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.web.controller;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FaultyRestController {
@GetMapping("/exception")
public ResponseEntity<Void> requestWithException() {
throw new RuntimeException("Error in the faulty controller!");
}
}

View File

@ -0,0 +1,85 @@
package com.baeldung.web.error;
import javax.persistence.EntityNotFoundException;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import com.baeldung.web.exception.MyResourceNotFoundException;
@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
public RestResponseEntityExceptionHandler() {
super();
}
// API
// 400
@ExceptionHandler({ ConstraintViolationException.class })
public ResponseEntity<Object> handleBadRequest(final ConstraintViolationException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}
@ExceptionHandler({ DataIntegrityViolationException.class })
public ResponseEntity<Object> handleBadRequest(final DataIntegrityViolationException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(final HttpMessageNotReadableException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
// ex.getCause() instanceof JsonMappingException, JsonParseException // for additional information later on
return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
}
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
}
// 404
@ExceptionHandler(value = { EntityNotFoundException.class, MyResourceNotFoundException.class })
protected ResponseEntity<Object> handleNotFound(final RuntimeException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
}
// 409
@ExceptionHandler({ InvalidDataAccessApiUsageException.class, DataAccessException.class })
protected ResponseEntity<Object> handleConflict(final RuntimeException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
}
// 412
// 500
@ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class })
/*500*/public ResponseEntity<Object> handleInternal(final RuntimeException ex, final WebRequest request) {
logger.error("500 Status Code", ex);
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.web.exception;
public final class MyResourceNotFoundException extends RuntimeException {
public MyResourceNotFoundException() {
super();
}
public MyResourceNotFoundException(final String message, final Throwable cause) {
super(message, cause);
}
public MyResourceNotFoundException(final String message) {
super(message);
}
public MyResourceNotFoundException(final Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,3 @@
### Spring Boot default error handling configurations
#server.error.whitelabel.enabled=false
#server.error.include-stacktrace=always

View File

@ -1,4 +1,4 @@
package com.baeldung.spring.boot.rest;
package com.baeldung.web;
import org.junit.Test;
import org.junit.runner.RunWith;

View File

@ -0,0 +1,65 @@
package com.baeldung.web.error;
import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isA;
import static org.hamcrest.Matchers.not;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class ErrorHandlingLiveTest {
private static final String BASE_URL = "http://localhost:8080";
private static final String EXCEPTION_ENDPOINT = "/exception";
private static final String ERROR_RESPONSE_KEY_PATH = "error";
private static final String XML_RESPONSE_KEY_PATH = "xmlkey";
private static final String LOCALE_RESPONSE_KEY_PATH = "locale";
private static final String CAUSE_RESPONSE_KEY_PATH = "cause";
private static final String RESPONSE_XML_ROOT = "Map";
private static final String XML_RESPONSE_KEY_XML_PATH = RESPONSE_XML_ROOT + "." + XML_RESPONSE_KEY_PATH;
private static final String LOCALE_RESPONSE_KEY_XML_PATH = RESPONSE_XML_ROOT + "." + LOCALE_RESPONSE_KEY_PATH;
private static final String CAUSE_RESPONSE_KEY_XML_PATH = RESPONSE_XML_ROOT + "." + CAUSE_RESPONSE_KEY_PATH;
private static final String CAUSE_RESPONSE_VALUE = "Error in the faulty controller!";
private static final String XML_RESPONSE_VALUE = "the XML response is different!";
@Test
public void whenRequestingFaultyEndpointAsJson_thenReceiveDefaultResponseWithConfiguredAttrs() {
given().header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.get(EXCEPTION_ENDPOINT)
.then()
.body("$", hasKey(LOCALE_RESPONSE_KEY_PATH))
.body(CAUSE_RESPONSE_KEY_PATH, is(CAUSE_RESPONSE_VALUE))
.body("$", not(hasKey(ERROR_RESPONSE_KEY_PATH)))
.body("$", not(hasKey(XML_RESPONSE_KEY_PATH)));
}
@Test
public void whenRequestingFaultyEndpointAsXml_thenReceiveXmlResponseWithConfiguredAttrs() {
given().header(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_VALUE)
.get(EXCEPTION_ENDPOINT)
.then()
.body(LOCALE_RESPONSE_KEY_XML_PATH, isA(String.class))
.body(CAUSE_RESPONSE_KEY_XML_PATH, is(CAUSE_RESPONSE_VALUE))
.body(RESPONSE_XML_ROOT, not(hasKey(ERROR_RESPONSE_KEY_PATH)))
.body(XML_RESPONSE_KEY_XML_PATH, is(XML_RESPONSE_VALUE));
}
@Test
public void whenRequestingFaultyEndpointAsHtml_thenReceiveWhitelabelPageResponse() throws Exception {
try (WebClient webClient = new WebClient()) {
webClient.getOptions()
.setThrowExceptionOnFailingStatusCode(false);
HtmlPage page = webClient.getPage(BASE_URL + EXCEPTION_ENDPOINT);
assertThat(page.getBody()
.asText()).contains("Whitelabel Error Page");
}
}
}

View File

@ -64,22 +64,22 @@ public class DbConfig {
@Configuration
@Profile("h2")
@PropertySource("persistence-h2.properties")
@PropertySource("classpath:persistence-h2.properties")
class H2Config {}
@Configuration
@Profile("hsqldb")
@PropertySource("persistence-hsqldb.properties")
@PropertySource("classpath:persistence-hsqldb.properties")
class HsqldbConfig {}
@Configuration
@Profile("derby")
@PropertySource("persistence-derby.properties")
@PropertySource("classpath:persistence-derby.properties")
class DerbyConfig {}
@Configuration
@Profile("sqlite")
@PropertySource("persistence-sqlite.properties")
@PropertySource("classpath:persistence-sqlite.properties")
class SqliteConfig {}

View File

@ -0,0 +1,37 @@
package com.baeldung.models;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Subject {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private String name;
public Subject() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.repositories;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RestResource;
import com.baeldung.models.Subject;
public interface SubjectRepository extends PagingAndSortingRepository<Subject, Long> {
@RestResource(path = "nameContains")
public Page<Subject> findByNameContaining(@Param("name") String name, Pageable p);
}

View File

View File

@ -18,7 +18,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
- [Metrics for your Spring REST API](http://www.baeldung.com/spring-rest-api-metrics)
- [Bootstrap a Web Application with Spring 4](http://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration)
- [Build a REST API with Spring and Java Config](http://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration)
- [Error Handling for REST with Spring](http://www.baeldung.com/exception-handling-for-rest-with-spring)
- [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic)

View File

@ -212,23 +212,6 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
</plugin>
<!-- Because we are using custom surefire configs in live profile hence need to disable all other in default profile -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkCount>3</forkCount>
<reuseForks>true</reuseForks>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>**/*IntTest.java</exclude>
<exclude>**/*LongRunningUnitTest.java</exclude>
<exclude>**/*ManualTest.java</exclude>
<exclude>**/*LiveTest.java</exclude>
<exclude>**/*TestSuite.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
@ -274,32 +257,6 @@
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>**/*IntTest.java</exclude>
</excludes>
<includes>
<include>**/*LiveTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>

View File

@ -1,17 +1,9 @@
package org.baeldung.web.error;
import javax.persistence.EntityNotFoundException;
import org.baeldung.web.exception.MyResourceNotFoundException;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
@ -24,61 +16,10 @@ public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionH
super();
}
// API
// 400
@ExceptionHandler({ ConstraintViolationException.class })
public ResponseEntity<Object> handleBadRequest(final ConstraintViolationException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}
@ExceptionHandler({ DataIntegrityViolationException.class })
public ResponseEntity<Object> handleBadRequest(final DataIntegrityViolationException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(final HttpMessageNotReadableException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
// ex.getCause() instanceof JsonMappingException, JsonParseException // for additional information later on
return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
}
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
}
// 404
@ExceptionHandler(value = { EntityNotFoundException.class, MyResourceNotFoundException.class })
@ExceptionHandler(value = { MyResourceNotFoundException.class })
protected ResponseEntity<Object> handleNotFound(final RuntimeException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
}
// 409
@ExceptionHandler({ InvalidDataAccessApiUsageException.class, DataAccessException.class })
protected ResponseEntity<Object> handleConflict(final RuntimeException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
}
// 412
// 500
@ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class })
/*500*/public ResponseEntity<Object> handleInternal(final RuntimeException ex, final WebRequest request) {
logger.error("500 Status Code", ex);
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
}
}

View File

@ -1,7 +1,7 @@
package org.baeldung;
import org.baeldung.persistence.PersistenceTestSuite;
import org.baeldung.web.LiveTestSuite;
import org.baeldung.web.LiveTestSuiteLiveTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@ -9,8 +9,8 @@ import org.junit.runners.Suite;
@Suite.SuiteClasses({
// @formatter:off
PersistenceTestSuite.class
,LiveTestSuite.class
,LiveTestSuiteLiveTest.class
}) //
public class TestSuite {
public class TestSuiteLiveTest {
}

View File

@ -10,6 +10,6 @@ import org.junit.runners.Suite;
,FooLiveTest.class
,FooPageableLiveTest.class
}) //
public class LiveTestSuite {
public class LiveTestSuiteLiveTest {
}

View File

@ -21,6 +21,11 @@
<artifactId>junit-platform-engine</artifactId>
<version>${junit.platform.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.jupiter.version}</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>

View File

@ -0,0 +1,19 @@
package com.baeldung.parameterized;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import java.util.stream.Stream;
class BlankStringsArgumentsProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.of(
Arguments.of((String) null),
Arguments.of(""),
Arguments.of(" ")
);
}
}

View File

@ -0,0 +1,50 @@
package com.baeldung.parameterized;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.EnumSource;
import java.time.Month;
import java.util.EnumSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
class EnumsUnitTest {
@ParameterizedTest
@EnumSource(Month.class)
void getValueForAMonth_IsAlwaysBetweenOneAndTwelve(Month month) {
int monthNumber = month.getValue();
assertTrue(monthNumber >= 1 && monthNumber <= 12);
}
@ParameterizedTest(name = "{index} {0} is 30 days long")
@EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"})
void someMonths_Are30DaysLong(Month month) {
final boolean isALeapYear = false;
assertEquals(30, month.length(isALeapYear));
}
@ParameterizedTest
@EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER", "FEBRUARY"}, mode = EnumSource.Mode.EXCLUDE)
void exceptFourMonths_OthersAre31DaysLong(Month month) {
final boolean isALeapYear = false;
assertEquals(31, month.length(isALeapYear));
}
@ParameterizedTest
@EnumSource(value = Month.class, names = ".+BER", mode = EnumSource.Mode.MATCH_ANY)
void fourMonths_AreEndingWithBer(Month month) {
EnumSet<Month> months = EnumSet.of(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER, Month.DECEMBER);
assertTrue(months.contains(month));
}
@ParameterizedTest
@CsvSource({"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"})
void someMonths_Are30DaysLongCsv(Month month) {
final boolean isALeapYear = false;
assertEquals(30, month.length(isALeapYear));
}
}

View File

@ -0,0 +1,18 @@
package com.baeldung.parameterized;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.converter.ConvertWith;
import org.junit.jupiter.params.provider.CsvSource;
import java.time.LocalDate;
import static org.junit.jupiter.api.Assertions.assertEquals;
class LocalDateUnitTest {
@ParameterizedTest
@CsvSource({"2018/12/25,2018", "2019/02/11,2019"})
void getYear_ShouldWorkAsExpected(@ConvertWith(SlashyDateConverter.class) LocalDate date, int expected) {
assertEquals(expected, date.getYear());
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.parameterized;
public class Numbers {
public static boolean isOdd(int number) {
return number % 2 != 0;
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.parameterized;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertTrue;
class NumbersUnitTest {
@ParameterizedTest
@ValueSource(ints = {1, 3, 5, -3, 15, Integer.MAX_VALUE})
void isOdd_ShouldReturnTrueForOddNumbers(int number) {
assertTrue(Numbers.isOdd(number));
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.parameterized;
class Person {
private final String firstName;
private final String middleName;
private final String lastName;
public Person(String firstName, String middleName, String lastName) {
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
}
public String fullName() {
if (middleName == null || middleName.trim().isEmpty()) return String.format("%s %s", firstName, lastName);
return String.format("%s %s %s", firstName, middleName, lastName);
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.parameterized;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.params.aggregator.ArgumentsAccessor;
import org.junit.jupiter.params.aggregator.ArgumentsAggregationException;
import org.junit.jupiter.params.aggregator.ArgumentsAggregator;
class PersonAggregator implements ArgumentsAggregator {
@Override
public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context)
throws ArgumentsAggregationException {
return new Person(accessor.getString(1), accessor.getString(2), accessor.getString(3));
}
}

View File

@ -0,0 +1,31 @@
package com.baeldung.parameterized;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.aggregator.AggregateWith;
import org.junit.jupiter.params.aggregator.ArgumentsAccessor;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
class PersonUnitTest {
@ParameterizedTest
@CsvSource({"Isaac,,Newton, Isaac Newton", "Charles,Robert,Darwin,Charles Robert Darwin"})
void fullName_ShouldGenerateTheExpectedFullName(ArgumentsAccessor argumentsAccessor) {
String firstName = argumentsAccessor.getString(0);
String middleName = (String) argumentsAccessor.get(1);
String lastName = argumentsAccessor.get(2, String.class);
String expectedFullName = argumentsAccessor.getString(3);
Person person = new Person(firstName, middleName, lastName);
assertEquals(expectedFullName, person.fullName());
}
@ParameterizedTest
@CsvSource({"Isaac Newton,Isaac,,Newton", "Charles Robert Darwin,Charles,Robert,Darwin"})
void fullName_ShouldGenerateTheExpectedFullName(String expectedFullName,
@AggregateWith(PersonAggregator.class) Person person) {
assertEquals(expectedFullName, person.fullName());
}
}

View File

@ -0,0 +1,27 @@
package com.baeldung.parameterized;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.params.converter.ArgumentConversionException;
import org.junit.jupiter.params.converter.ArgumentConverter;
import java.time.LocalDate;
class SlashyDateConverter implements ArgumentConverter {
@Override
public Object convert(Object source, ParameterContext context) throws ArgumentConversionException {
if (!(source instanceof String))
throw new IllegalArgumentException("The argument should be a string: " + source);
try {
String[] parts = ((String) source).split("/");
int year = Integer.parseInt(parts[0]);
int month = Integer.parseInt(parts[1]);
int day = Integer.parseInt(parts[2]);
return LocalDate.of(year, month, day);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to convert", e);
}
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.parameterized;
import java.util.stream.Stream;
public class StringParams {
static Stream<String> blankStrings() {
return Stream.of(null, "", " ");
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.parameterized;
class Strings {
static boolean isBlank(String input) {
return input == null || input.trim().isEmpty();
}
}

View File

@ -0,0 +1,108 @@
package com.baeldung.parameterized;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
class StringsUnitTest {
static Stream<Arguments> arguments = Stream.of(
Arguments.of(null, true), // null strings should be considered blank
Arguments.of("", true),
Arguments.of(" ", true),
Arguments.of("not blank", false)
);
@ParameterizedTest
@VariableSource("arguments")
void isBlank_ShouldReturnTrueForNullOrBlankStringsVariableSource(String input, boolean expected) {
assertEquals(expected, Strings.isBlank(input));
}
@ParameterizedTest
@ValueSource(strings = {"", " "})
void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input) {
assertTrue(Strings.isBlank(input));
}
@ParameterizedTest
@MethodSource("provideStringsForIsBlank")
void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input, boolean expected) {
assertEquals(expected, Strings.isBlank(input));
}
@ParameterizedTest
@MethodSource // Please note method name is not provided
void isBlank_ShouldReturnTrueForNullOrBlankStringsOneArgument(String input) {
assertTrue(Strings.isBlank(input));
}
@ParameterizedTest
@MethodSource("com.baeldung.parameterized.StringParams#blankStrings")
void isBlank_ShouldReturnTrueForNullOrBlankStringsExternalSource(String input) {
assertTrue(Strings.isBlank(input));
}
@ParameterizedTest
@ArgumentsSource(BlankStringsArgumentsProvider.class)
void isBlank_ShouldReturnTrueForNullOrBlankStringsArgProvider(String input) {
assertTrue(Strings.isBlank(input));
}
private static Stream<String> isBlank_ShouldReturnTrueForNullOrBlankStringsOneArgument() {
return Stream.of(null, "", " ");
}
@ParameterizedTest
@MethodSource("provideStringsForIsBlankList")
void isBlank_ShouldReturnTrueForNullOrBlankStringsList(String input, boolean expected) {
assertEquals(expected, Strings.isBlank(input));
}
@ParameterizedTest
@CsvSource({"test,TEST", "tEst,TEST", "Java,JAVA"}) // Passing a CSV pair per test execution
void toUpperCase_ShouldGenerateTheExpectedUppercaseValue(String input, String expected) {
String actualValue = input.toUpperCase();
assertEquals(expected, actualValue);
}
@ParameterizedTest
@CsvSource(value = {"test:test", "tEst:test", "Java:java"}, delimiter =':') // Using : as the column separator.
void toLowerCase_ShouldGenerateTheExpectedLowercaseValue(String input, String expected) {
String actualValue = input.toLowerCase();
assertEquals(expected, actualValue);
}
@ParameterizedTest
@CsvFileSource(resources = "/data.csv", numLinesToSkip = 1)
void toUpperCase_ShouldGenerateTheExpectedUppercaseValueCSVFile(String input, String expected) {
String actualValue = input.toUpperCase();
assertEquals(expected, actualValue);
}
private static Stream<Arguments> provideStringsForIsBlank() {
return Stream.of(
Arguments.of(null, true), // null strings should be considered blank
Arguments.of("", true),
Arguments.of(" ", true),
Arguments.of("not blank", false)
);
}
private static List<Arguments> provideStringsForIsBlankList() {
return Arrays.asList(
Arguments.of(null, true), // null strings should be considered blank
Arguments.of("", true),
Arguments.of(" ", true),
Arguments.of("not blank", false)
);
}
}

View File

@ -0,0 +1,45 @@
package com.baeldung.parameterized;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.support.AnnotationConsumer;
import java.lang.reflect.Field;
import java.util.stream.Stream;
class VariableArgumentsProvider implements ArgumentsProvider, AnnotationConsumer<VariableSource> {
private String variableName;
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return context.getTestClass()
.map(this::getField)
.map(this::getValue)
.orElseThrow(() -> new IllegalArgumentException("Failed to load test arguments"));
}
@Override
public void accept(VariableSource variableSource) {
variableName = variableSource.value();
}
private Field getField(Class<?> clazz) {
try {
return clazz.getDeclaredField(variableName);
} catch (Exception e) {
return null;
}
}
@SuppressWarnings("unchecked")
private Stream<Arguments> getValue(Field field) {
Object value = null;
try {
value = field.get(null);
} catch (Exception ignored) {}
return value == null ? null : (Stream<Arguments>) value;
}
}

View File

@ -0,0 +1,19 @@
package com.baeldung.parameterized;
import org.junit.jupiter.params.provider.ArgumentsSource;
import java.lang.annotation.*;
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@ArgumentsSource(VariableArgumentsProvider.class)
public @interface VariableSource {
/**
* Represents the name of the static variable to load the test arguments from.
*
* @return Static variable name.
*/
String value();
}

View File

@ -0,0 +1,4 @@
input,expected
test,TEST
tEst,TEST
Java,JAVA
1 input expected
2 test TEST
3 tEst TEST
4 Java JAVA

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.0 r1840935">
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.1-SNAPSHOT.20181219">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
@ -25,80 +25,116 @@
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<LoopController guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">true</boolProp>
<stringProp name="LoopController.loops">1</stringProp>
</LoopController>
<hashTree>
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
<collectionProp name="HeaderManager.headers">
<elementProp name="" elementType="Header">
<stringProp name="Header.name">Content-Type</stringProp>
<stringProp name="Header.value">application/json</stringProp>
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
<collectionProp name="HeaderManager.headers">
<elementProp name="" elementType="Header">
<stringProp name="Header.name">Content-Type</stringProp>
<stringProp name="Header.value">application/json</stringProp>
</elementProp>
</collectionProp>
</HeaderManager>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Transaction" enabled="true">
<boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
<elementProp name="HTTPsampler.Arguments" elementType="Arguments">
<collectionProp name="Arguments.arguments">
<elementProp name="" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">false</boolProp>
<stringProp name="Argument.value">{&quot;customerRewardsId&quot;:null,&quot;customerId&quot;:${random},&quot;transactionDate&quot;:null}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</HeaderManager>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/transactions/add</stringProp>
<stringProp name="HTTPSampler.method">POST</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree>
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="Transaction Id Extractor" enabled="true">
<stringProp name="JSONPostProcessor.referenceNames">txnId</stringProp>
<stringProp name="JSONPostProcessor.jsonPathExprs">$.id</stringProp>
<stringProp name="JSONPostProcessor.match_numbers">1</stringProp>
<stringProp name="Sample.scope">all</stringProp>
<stringProp name="JSONPostProcessor.defaultValues">foo</stringProp>
</JSONPostProcessor>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Transaction" enabled="true">
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="Transaction Date Extractor" enabled="true">
<stringProp name="JSONPostProcessor.referenceNames">txnDate</stringProp>
<stringProp name="JSONPostProcessor.jsonPathExprs">$.transactionDate</stringProp>
<stringProp name="JSONPostProcessor.match_numbers">1</stringProp>
<stringProp name="JSONPostProcessor.defaultValues">Never</stringProp>
</JSONPostProcessor>
<hashTree/>
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="Customer Id Extractor" enabled="true">
<stringProp name="JSONPostProcessor.referenceNames">custId</stringProp>
<stringProp name="JSONPostProcessor.jsonPathExprs">$.customerId</stringProp>
<stringProp name="JSONPostProcessor.match_numbers">1</stringProp>
<stringProp name="Sample.scope">all</stringProp>
<stringProp name="JSONPostProcessor.defaultValues">bob</stringProp>
</JSONPostProcessor>
<hashTree/>
</hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Find Reward Account" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/rewards/find/${custId}</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree>
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="JSON Extractor" enabled="true">
<stringProp name="JSONPostProcessor.referenceNames">rwdId</stringProp>
<stringProp name="JSONPostProcessor.jsonPathExprs">$.id</stringProp>
<stringProp name="JSONPostProcessor.match_numbers">1</stringProp>
<stringProp name="JSONPostProcessor.defaultValues">0</stringProp>
<stringProp name="Sample.scope">all</stringProp>
</JSONPostProcessor>
<hashTree/>
</hashTree>
<IfController guiclass="IfControllerPanel" testclass="IfController" testname="If Reward Account Does Not Exist" enabled="true">
<stringProp name="IfController.condition">${__jexl3(${rwdId} == 0,)}</stringProp>
<boolProp name="IfController.evaluateAll">true</boolProp>
<boolProp name="IfController.useExpression">true</boolProp>
</IfController>
<hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Reward" enabled="true">
<boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
<elementProp name="HTTPsampler.Arguments" elementType="Arguments">
<collectionProp name="Arguments.arguments">
<elementProp name="" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">false</boolProp>
<stringProp name="Argument.value">{&quot;customerRewardsId&quot;:null,&quot;customerId&quot;:${random},&quot;transactionDate&quot;:null}</stringProp>
<stringProp name="Argument.value">{&quot;customerId&quot;:${custId}}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/transactions/add</stringProp>
<stringProp name="HTTPSampler.method">POST</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree>
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="Transaction Id Extractor" enabled="true">
<stringProp name="JSONPostProcessor.referenceNames">txnId</stringProp>
<stringProp name="JSONPostProcessor.jsonPathExprs">$.id</stringProp>
<stringProp name="JSONPostProcessor.match_numbers">1</stringProp>
<stringProp name="Sample.scope">all</stringProp>
<stringProp name="JSONPostProcessor.defaultValues">foo</stringProp>
</JSONPostProcessor>
<hashTree/>
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="Transaction Date Extractor" enabled="true">
<stringProp name="JSONPostProcessor.referenceNames">txnDate</stringProp>
<stringProp name="JSONPostProcessor.jsonPathExprs">$.transactionDate</stringProp>
<stringProp name="JSONPostProcessor.match_numbers">1</stringProp>
<stringProp name="JSONPostProcessor.defaultValues">Never</stringProp>
</JSONPostProcessor>
<hashTree/>
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="Customer Id Extractor" enabled="true">
<stringProp name="JSONPostProcessor.referenceNames">custId</stringProp>
<stringProp name="JSONPostProcessor.jsonPathExprs">$.customerId</stringProp>
<stringProp name="JSONPostProcessor.match_numbers">1</stringProp>
<stringProp name="Sample.scope">all</stringProp>
<stringProp name="JSONPostProcessor.defaultValues">bob</stringProp>
</JSONPostProcessor>
<hashTree/>
</hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Find Reward Account" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/rewards/find/${custId}</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<stringProp name="HTTPSampler.path">/rewards/add</stringProp>
<stringProp name="HTTPSampler.method">POST</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
@ -112,98 +148,57 @@
<stringProp name="JSONPostProcessor.referenceNames">rwdId</stringProp>
<stringProp name="JSONPostProcessor.jsonPathExprs">$.id</stringProp>
<stringProp name="JSONPostProcessor.match_numbers">1</stringProp>
<stringProp name="JSONPostProcessor.defaultValues">0</stringProp>
<stringProp name="JSONPostProcessor.defaultValues">bar</stringProp>
<stringProp name="Sample.scope">all</stringProp>
</JSONPostProcessor>
<hashTree/>
</hashTree>
<IfController guiclass="IfControllerPanel" testclass="IfController" testname="If Reward Account Does Not Exist" enabled="true">
<stringProp name="IfController.condition">${rwdId} == 0</stringProp>
<boolProp name="IfController.evaluateAll">true</boolProp>
</IfController>
<hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Add Reward" enabled="true">
<boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
<elementProp name="HTTPsampler.Arguments" elementType="Arguments">
<collectionProp name="Arguments.arguments">
<elementProp name="" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">false</boolProp>
<stringProp name="Argument.value">{&quot;customerId&quot;:${custId}}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/rewards/add</stringProp>
<stringProp name="HTTPSampler.method">POST</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree>
<JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="JSON Extractor" enabled="true">
<stringProp name="JSONPostProcessor.referenceNames">rwdId</stringProp>
<stringProp name="JSONPostProcessor.jsonPathExprs">$.id</stringProp>
<stringProp name="JSONPostProcessor.match_numbers">1</stringProp>
<stringProp name="JSONPostProcessor.defaultValues">bar</stringProp>
<stringProp name="Sample.scope">all</stringProp>
</JSONPostProcessor>
<hashTree/>
</hashTree>
</hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Transaction" enabled="true">
<boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
<elementProp name="HTTPsampler.Arguments" elementType="Arguments">
<collectionProp name="Arguments.arguments">
<elementProp name="" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">false</boolProp>
<stringProp name="Argument.value">{&quot;id&quot;:${txnId},&quot;customerRewardsId&quot;:${rwdId},&quot;customerId&quot;:${custId},&quot;transactionDate&quot;:&quot;${txnDate}&quot;}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/transactions/add</stringProp>
<stringProp name="HTTPSampler.method">POST</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Find All Transactions" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/transactions/findAll/${rwdId}</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree/>
</hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Update Transaction" enabled="true">
<boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
<elementProp name="HTTPsampler.Arguments" elementType="Arguments">
<collectionProp name="Arguments.arguments">
<elementProp name="" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">false</boolProp>
<stringProp name="Argument.value">{&quot;id&quot;:${txnId},&quot;customerRewardsId&quot;:${rwdId},&quot;customerId&quot;:${custId},&quot;transactionDate&quot;:&quot;${txnDate}&quot;}</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/transactions/add</stringProp>
<stringProp name="HTTPSampler.method">POST</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Find All Transactions" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8080</stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/transactions/findAll/${rwdId}</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree/>
<RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable" enabled="true">
<stringProp name="maximumValue">10000</stringProp>
<stringProp name="minimumValue">1</stringProp>
@ -213,7 +208,7 @@
<stringProp name="variableName">random</stringProp>
</RandomVariableConfig>
<hashTree/>
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="false">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>