Merge remote-tracking branch 'eugenp/master'
This commit is contained in:
commit
a295224159
|
@ -62,3 +62,5 @@ jmeter/src/main/resources/*-JMeter.csv
|
|||
**/dist
|
||||
**/tmp
|
||||
**/out-tsc
|
||||
**/nbproject/
|
||||
**/nb-configuration.xml
|
|
@ -21,3 +21,8 @@ In additional to Spring, the following technologies are in focus: `core Java`, `
|
|||
Building the project
|
||||
====================
|
||||
To do the full build, do: `mvn install -Pdefault -Dgib.enabled=false`
|
||||
|
||||
|
||||
Building a single module
|
||||
====================
|
||||
To build a specific module run the command: `mvn clean install -Dgib.enabled=false` in the module directory
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package com.baeldung.algorithms.insertionsort;
|
||||
|
||||
public class InsertionSort {
|
||||
|
||||
public static void insertionSortImperative(int[] input) {
|
||||
for (int i = 1; i < input.length; i++) {
|
||||
int key = input[i];
|
||||
int j = i - 1;
|
||||
while (j >= 0 && input[j] > key) {
|
||||
input[j + 1] = input[j];
|
||||
j = j - 1;
|
||||
}
|
||||
input[j + 1] = key;
|
||||
}
|
||||
}
|
||||
|
||||
public static void insertionSortRecursive(int[] input) {
|
||||
insertionSortRecursive(input, input.length);
|
||||
}
|
||||
|
||||
private static void insertionSortRecursive(int[] input, int i) {
|
||||
// base case
|
||||
if (i <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// sort the first i - 1 elements of the array
|
||||
insertionSortRecursive(input, i - 1);
|
||||
|
||||
// then find the correct position of the element at position i
|
||||
int key = input[i - 1];
|
||||
int j = i - 2;
|
||||
// shifting the elements from their position by 1
|
||||
while (j >= 0 && input[j] > key) {
|
||||
input[j + 1] = input[j];
|
||||
j = j - 1;
|
||||
}
|
||||
// inserting the key at the appropriate position
|
||||
input[j + 1] = key;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung.algorithms.insertionsort;
|
||||
|
||||
import com.baeldung.algorithms.insertionsort.InsertionSort;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
public class InsertionSortUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenUnsortedArray_whenInsertionSortImperative_thenSortedAsc() {
|
||||
int[] input = {6, 2, 3, 4, 5, 1};
|
||||
InsertionSort.insertionSortImperative(input);
|
||||
int[] expected = {1, 2, 3, 4, 5, 6};
|
||||
assertArrayEquals("the two arrays are not equal", expected, input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnsortedArray_whenInsertionSortRecursive_thenSortedAsc() {
|
||||
int[] input = {6, 4, 5, 2, 3, 1};
|
||||
InsertionSort.insertionSortRecursive(input);
|
||||
int[] expected = {1, 2, 3, 4, 5, 6};
|
||||
assertArrayEquals("the two arrays are not equal", expected, input);
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package com.baeldung.internationalization;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class DateTimeFormatterUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenDefaultUsLocaleAndDateTimeAndPattern_whenFormatWithDifferentLocales_thenGettingLocalizedDateTimes() {
|
||||
Locale.setDefault(Locale.US);
|
||||
LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500);
|
||||
String pattern = "dd-MMMM-yyyy HH:mm:ss.SSS";
|
||||
|
||||
DateTimeFormatter defaultTimeFormatter = DateTimeFormatter.ofPattern(pattern);
|
||||
DateTimeFormatter plTimeFormatter = DateTimeFormatter.ofPattern(pattern, new Locale("pl", "PL"));
|
||||
DateTimeFormatter deTimeFormatter = DateTimeFormatter.ofPattern(pattern).withLocale(Locale.GERMANY);
|
||||
|
||||
Assert.assertEquals("01-January-2018 10:15:50.000", defaultTimeFormatter.format(localDateTime));
|
||||
Assert.assertEquals("01-stycznia-2018 10:15:50.000", plTimeFormatter.format(localDateTime));
|
||||
Assert.assertEquals("01-Januar-2018 10:15:50.000", deTimeFormatter.format(localDateTime));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDateTimeAndTimeZone_whenFormatWithDifferentLocales_thenGettingLocalizedZonedDateTimes() {
|
||||
Locale.setDefault(Locale.US);
|
||||
LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500);
|
||||
ZoneId losAngelesTimeZone = TimeZone.getTimeZone("America/Los_Angeles").toZoneId();
|
||||
|
||||
DateTimeFormatter localizedFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
|
||||
DateTimeFormatter frLocalizedFormatter =
|
||||
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(Locale.FRANCE);
|
||||
String formattedDateTime = localizedFormatter.format(ZonedDateTime.of(localDateTime, losAngelesTimeZone));
|
||||
String frFormattedDateTime = frLocalizedFormatter.format(ZonedDateTime.of(localDateTime, losAngelesTimeZone));
|
||||
|
||||
Assert.assertEquals("Monday, January 1, 2018 10:15:50 AM PST", formattedDateTime);
|
||||
Assert.assertEquals("lundi 1 janvier 2018 10 h 15 PST", frFormattedDateTime);
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@
|
|||
- [Thread Safe LIFO Data Structure Implementations](https://www.baeldung.com/java-lifo-thread-safe)
|
||||
- [Collections.emptyList() vs. New List Instance](https://www.baeldung.com/java-collections-emptylist-new-list)
|
||||
- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
|
||||
- [Differences Between Collection.clear() and Collection.removeAll()](https://www.baeldung.com/java-collection-clear-vs-removeall)
|
||||
- [Performance of contains() in a HashSet vs ArrayList](https://www.baeldung.com/java-hashset-arraylist-contains-performance)
|
||||
- [Get the Key for a Value from a Java Map](https://www.baeldung.com/java-map-key-from-value)
|
||||
- [Time Complexity of Java Collections](https://www.baeldung.com/java-collections-complexity)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>core-java-collections</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
@ -68,15 +67,14 @@
|
|||
<artifactId>commons-exec</artifactId>
|
||||
<version>1.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>one.util</groupId>
|
||||
<artifactId>streamex</artifactId>
|
||||
<version>0.6.5</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
<properties>
|
||||
<openjdk.jmh.version>1.19</openjdk.jmh.version>
|
||||
<junit.platform.version>1.2.0</junit.platform.version>
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package com.baeldung.convertcollectiontoarraylist;
|
||||
|
||||
/**
|
||||
* This POJO is the element type of our collection. It has a deepCopy() method.
|
||||
*
|
||||
* @author chris
|
||||
*/
|
||||
public class Foo {
|
||||
|
||||
private int id;
|
||||
private String name;
|
||||
private Foo parent;
|
||||
|
||||
public Foo() {
|
||||
}
|
||||
|
||||
public Foo(int id, String name, Foo parent) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Foo getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(Foo parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Foo deepCopy() {
|
||||
return new Foo(
|
||||
this.id, this.name, this.parent != null ? this.parent.deepCopy() : null);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.baeldung.synchronizedcollections.application;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Application {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(Application.class.getName());
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
List<Integer> syncCollection = Collections.synchronizedList(Arrays.asList(1, 2, 3, 4, 5, 6));
|
||||
synchronized (syncCollection) {
|
||||
syncCollection.forEach((e) -> {LOGGER.info(e.toString());});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
package com.baeldung.convertcollectiontoarraylist;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import static java.util.stream.Collectors.toCollection;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author chris
|
||||
*/
|
||||
public class FooUnitTest {
|
||||
private static Collection<Foo> srcCollection = new HashSet<>();
|
||||
|
||||
public FooUnitTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
int i = 0;
|
||||
Foo john = new Foo(i++, "John", null);
|
||||
Foo mary = new Foo(i++, "Mary", null);
|
||||
Foo sam = new Foo(i++, "Sam", john);
|
||||
Foo alice = new Foo(i++, "Alice", john);
|
||||
Foo buffy = new Foo(i++, "Buffy", sam);
|
||||
srcCollection.add(john);
|
||||
srcCollection.add(mary);
|
||||
srcCollection.add(sam);
|
||||
srcCollection.add(alice);
|
||||
srcCollection.add(buffy);
|
||||
|
||||
// make sure the collection isn't sorted accidentally
|
||||
assertFalse("Oops: source collection is already sorted!", isSorted(srcCollection));
|
||||
}
|
||||
|
||||
/**
|
||||
* Section 3. Using the ArrayList Constructor
|
||||
*/
|
||||
@Test
|
||||
public void whenUsingConstructor_thenVerifyShallowCopy() {
|
||||
ArrayList<Foo> newList = new ArrayList<>(srcCollection);
|
||||
verifyShallowCopy(srcCollection, newList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Section 4. Using the Streams API
|
||||
*/
|
||||
@Test
|
||||
public void whenUsingStream_thenVerifyShallowCopy() {
|
||||
ArrayList<Foo> newList = srcCollection.stream().collect(toCollection(ArrayList::new));
|
||||
|
||||
verifyShallowCopy(srcCollection, newList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Section 5. Deep Copy
|
||||
*/
|
||||
@Test
|
||||
public void whenUsingDeepCopy_thenVerifyDeepCopy() {
|
||||
ArrayList<Foo> newList = srcCollection.stream()
|
||||
.map(foo -> foo.deepCopy())
|
||||
.collect(toCollection(ArrayList::new));
|
||||
|
||||
verifyDeepCopy(srcCollection, newList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Section 6. Controlling the List Order
|
||||
*/
|
||||
@Test
|
||||
public void whenUsingSortedStream_thenVerifySortOrder() {
|
||||
ArrayList<Foo> newList = srcCollection.stream()
|
||||
.sorted(Comparator.comparing(Foo::getName))
|
||||
.collect(toCollection(ArrayList::new));
|
||||
|
||||
assertTrue("ArrayList is not sorted by name", isSorted(newList));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the contents of the two collections are the same
|
||||
* @param a
|
||||
* @param b
|
||||
*/
|
||||
private void verifyShallowCopy(Collection a, Collection b) {
|
||||
assertEquals("Collections have different lengths", a.size(), b.size());
|
||||
Iterator<Foo> iterA = a.iterator();
|
||||
Iterator<Foo> iterB = b.iterator();
|
||||
while (iterA.hasNext()) {
|
||||
// use '==' to test instance identity
|
||||
assertTrue("Foo instances differ!", iterA.next() == iterB.next());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the contents of the two collections are the same
|
||||
* @param a
|
||||
* @param b
|
||||
*/
|
||||
private void verifyDeepCopy(Collection a, Collection b) {
|
||||
assertEquals("Collections have different lengths", a.size(), b.size());
|
||||
Iterator<Foo> iterA = a.iterator();
|
||||
Iterator<Foo> iterB = b.iterator();
|
||||
while (iterA.hasNext()) {
|
||||
Foo nextA = iterA.next();
|
||||
Foo nextB = iterB.next();
|
||||
// should not be same instance
|
||||
assertFalse("Foo instances are the same!", nextA == nextB);
|
||||
// but should have same content
|
||||
assertFalse("Foo instances have different content!", fooDiff(nextA, nextB));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the contents of a and b differ. Test parent recursively
|
||||
* @param a
|
||||
* @param b
|
||||
* @return False if the two items are the same
|
||||
*/
|
||||
private boolean fooDiff(Foo a, Foo b) {
|
||||
if (a != null && b != null) {
|
||||
return a.getId() != b.getId()
|
||||
|| !a.getName().equals(b.getName())
|
||||
|| fooDiff(a.getParent(), b.getParent());
|
||||
}
|
||||
return !(a == null && b == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param c collection of Foo
|
||||
* @return true if the collection is sorted by name
|
||||
*/
|
||||
private static boolean isSorted(Collection<Foo> c) {
|
||||
String prevName = null;
|
||||
for (Foo foo : c) {
|
||||
if (prevName == null || foo.getName().compareTo(prevName) > 0) {
|
||||
prevName = foo.getName();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package com.baeldung.java.map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.collections4.MultiMap;
|
||||
import org.apache.commons.collections4.MultiMapUtils;
|
||||
import org.apache.commons.collections4.MultiValuedMap;
|
||||
import org.apache.commons.collections4.map.MultiValueMap;
|
||||
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
|
||||
import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.TreeMultimap;
|
||||
|
||||
|
||||
public class KeyCheckTest {
|
||||
|
||||
@Test
|
||||
public void whenKeyIsPresent_thenContainsKeyReturnsTrue() {
|
||||
Map<String, String> map = Collections.singletonMap("key", "value");
|
||||
|
||||
assertTrue(map.containsKey("key"));
|
||||
assertFalse(map.containsKey("missing"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenKeyHasNullValue_thenGetStillWorks() {
|
||||
Map<String, String> map = Collections.singletonMap("nothing", null);
|
||||
|
||||
assertTrue(map.containsKey("nothing"));
|
||||
assertNull(map.get("nothing"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.baeldung.java.map;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class KeyCheckUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenKeyIsPresent_thenContainsKeyReturnsTrue() {
|
||||
Map<String, String> map = Collections.singletonMap("key", "value");
|
||||
|
||||
assertTrue(map.containsKey("key"));
|
||||
assertFalse(map.containsKey("missing"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenKeyHasNullValue_thenGetStillWorks() {
|
||||
Map<String, String> map = Collections.singletonMap("nothing", null);
|
||||
|
||||
assertTrue(map.containsKey("nothing"));
|
||||
assertNull(map.get("nothing"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.baeldung.synchronizedcollections.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SynchronizedCollectionUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenSynchronizedCollection_whenTwoThreadsAddElements_thenCorrectCollectionSize() throws InterruptedException {
|
||||
Collection<Integer> syncCollection = Collections.synchronizedCollection(new ArrayList<>());
|
||||
|
||||
Runnable listOperations = () -> {
|
||||
syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));
|
||||
};
|
||||
Thread thread1 = new Thread(listOperations);
|
||||
Thread thread2 = new Thread(listOperations);
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
|
||||
assertThat(syncCollection.size()).isEqualTo(12);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.baeldung.synchronizedcollections.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.junit.Test;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
public class SynchronizedListUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenSynchronizedList_whenTwoThreadsAddElements_thenCorrectListSize() throws InterruptedException {
|
||||
List<Integer> syncList = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
Runnable listOperations = () -> {
|
||||
syncList.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));
|
||||
};
|
||||
Thread thread1 = new Thread(listOperations);
|
||||
Thread thread2 = new Thread(listOperations);
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
|
||||
assertThat(syncList.size()).isEqualTo(12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenStringList_whenTwoThreadsIterateOnSynchronizedList_thenCorrectResult() throws InterruptedException {
|
||||
List<String> syncCollection = Collections.synchronizedList(Arrays.asList("a", "b", "c"));
|
||||
List<String> uppercasedCollection = new ArrayList<>();
|
||||
|
||||
Runnable listOperations = () -> {
|
||||
synchronized (syncCollection) {
|
||||
syncCollection.forEach((e) -> {
|
||||
uppercasedCollection.add(e.toUpperCase());
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Thread thread1 = new Thread(listOperations);
|
||||
Thread thread2 = new Thread(listOperations);
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
|
||||
assertThat(uppercasedCollection.get(0)).isEqualTo("A");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.baeldung.synchronizedcollections.test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.junit.Test;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
public class SynchronizedMapUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenSynchronizedMap_whenTwoThreadsAddElements_thenCorrectMapSize() throws InterruptedException {
|
||||
Map<Integer, String> syncMap = Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
Runnable mapOperations = () -> {
|
||||
syncMap.put(1, "one");
|
||||
syncMap.put(2, "two");
|
||||
syncMap.put(3, "three");
|
||||
|
||||
};
|
||||
Thread thread1 = new Thread(mapOperations);
|
||||
Thread thread2 = new Thread(mapOperations);
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
|
||||
assertThat(syncMap.size()).isEqualTo(3);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.baeldung.synchronizedcollections.test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.junit.Test;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
public class SynchronizedSetUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenSynchronizedSet_whenTwoThreadsAddElements_thenCorrectSetSize() throws InterruptedException {
|
||||
Set<Integer> syncSet = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
Runnable setOperations = () -> {syncSet.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));};
|
||||
Thread thread1 = new Thread(setOperations);
|
||||
Thread thread2 = new Thread(setOperations);
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
|
||||
assertThat(syncSet.size()).isEqualTo(6);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.baeldung.synchronizedcollections.test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SynchronizedSortedMapUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenSynchronizedSorteMap_whenTwoThreadsAddElements_thenCorrectSortedMapSize() throws InterruptedException {
|
||||
Map<Integer, String> syncSortedMap = Collections.synchronizedSortedMap(new TreeMap<>());
|
||||
|
||||
Runnable sortedMapOperations = () -> {
|
||||
syncSortedMap.put(1, "One");
|
||||
syncSortedMap.put(2, "Two");
|
||||
syncSortedMap.put(3, "Three");
|
||||
};
|
||||
Thread thread1 = new Thread(sortedMapOperations);
|
||||
Thread thread2 = new Thread(sortedMapOperations);
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
|
||||
assertThat(syncSortedMap.size()).isEqualTo(3);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.baeldung.synchronizedcollections.test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SynchronizedSortedSetUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenSynchronizedSortedSet_whenTwoThreadsAddElements_thenCorrectSortedSetSize() throws InterruptedException {
|
||||
SortedSet<Integer> syncSortedSet = Collections.synchronizedSortedSet(new TreeSet<>());
|
||||
|
||||
Runnable sortedSetOperations = () -> {syncSortedSet.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));};
|
||||
sortedSetOperations.run();
|
||||
sortedSetOperations.run();
|
||||
Thread thread1 = new Thread(sortedSetOperations);
|
||||
Thread thread2 = new Thread(sortedSetOperations);
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
|
||||
assertThat(syncSortedSet.size()).isEqualTo(6);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.baeldung.stream;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
public class OutputStreamExamples {
|
||||
|
||||
public void fileOutputStreamByteSequence(String file, String data) throws IOException {
|
||||
byte[] bytes = data.getBytes();
|
||||
try (OutputStream out = new FileOutputStream(file)) {
|
||||
out.write(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
public void fileOutputStreamByteSubSequence(String file, String data) throws IOException {
|
||||
byte[] bytes = data.getBytes();
|
||||
try (OutputStream out = new FileOutputStream(file)) {
|
||||
out.write(bytes, 6, 5);
|
||||
}
|
||||
}
|
||||
|
||||
public void fileOutputStreamByteSingle(String file, String data) throws IOException {
|
||||
byte[] bytes = data.getBytes();
|
||||
try (OutputStream out = new FileOutputStream(file)) {
|
||||
out.write(bytes[6]);
|
||||
}
|
||||
}
|
||||
|
||||
public void bufferedOutputStream(String file, String... data) throws IOException {
|
||||
try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
for (String s : data) {
|
||||
out.write(s.getBytes());
|
||||
out.write(" ".getBytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void outputStreamWriter(String file, String data) throws IOException {
|
||||
try (OutputStream out = new FileOutputStream(file); Writer writer = new OutputStreamWriter(out, "UTF-8")) {
|
||||
writer.write(data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package com.baeldung.stream;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class OutputStreamExamplesUnitTest {
|
||||
|
||||
StringBuilder filePath = new StringBuilder();
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
filePath.append("src");
|
||||
filePath.append(File.separator);
|
||||
filePath.append("test");
|
||||
filePath.append(File.separator);
|
||||
filePath.append("resources");
|
||||
filePath.append(File.separator);
|
||||
filePath.append("output_file.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOutputStream_whenWriteSingleByteCalled_thenOutputCreated() throws IOException {
|
||||
|
||||
final File file = new File(filePath.toString());
|
||||
OutputStreamExamples examples = new OutputStreamExamples();
|
||||
examples.fileOutputStreamByteSingle(filePath.toString(), "Hello World!");
|
||||
assertTrue(file.exists());
|
||||
file.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOutputStream_whenWriteByteSequenceCalled_thenOutputCreated() throws IOException {
|
||||
|
||||
final File file = new File(filePath.toString());
|
||||
OutputStreamExamples examples = new OutputStreamExamples();
|
||||
examples.fileOutputStreamByteSequence(filePath.toString(), "Hello World!");
|
||||
assertTrue(file.exists());
|
||||
file.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOutputStream_whenWriteByteSubSequenceCalled_thenOutputCreated() throws IOException {
|
||||
|
||||
final File file = new File(filePath.toString());
|
||||
OutputStreamExamples examples = new OutputStreamExamples();
|
||||
examples.fileOutputStreamByteSubSequence(filePath.toString(), "Hello World!");
|
||||
assertTrue(file.exists());
|
||||
file.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBufferedOutputStream_whenCalled_thenOutputCreated() throws IOException {
|
||||
|
||||
final File file = new File(filePath.toString());
|
||||
OutputStreamExamples examples = new OutputStreamExamples();
|
||||
examples.bufferedOutputStream(filePath.toString(), "Hello", "World!");
|
||||
assertTrue(file.exists());
|
||||
file.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOutputStreamWriter_whenCalled_thenOutputCreated() throws IOException {
|
||||
|
||||
final File file = new File(filePath.toString());
|
||||
OutputStreamExamples examples = new OutputStreamExamples();
|
||||
examples.outputStreamWriter(filePath.toString(), "Hello World!");
|
||||
assertTrue(file.exists());
|
||||
file.delete();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,14 @@
|
|||
package com.baeldung.classloader;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class CustomClassLoader extends ClassLoader {
|
||||
|
||||
|
||||
public Class getClass(String name) throws ClassNotFoundException {
|
||||
@Override
|
||||
public Class findClass(String name) throws ClassNotFoundException {
|
||||
byte[] b = loadClassFromFile(name);
|
||||
return defineClass(name, b, 0, b.length);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ public class CustomClassLoaderUnitTest {
|
|||
public void customLoader() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
|
||||
|
||||
CustomClassLoader customClassLoader = new CustomClassLoader();
|
||||
Class<?> c = customClassLoader.getClass(PrintClassLoader.class.getName());
|
||||
Class<?> c = customClassLoader.findClass(PrintClassLoader.class.getName());
|
||||
|
||||
Object ob = c.newInstance();
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.datastructures
|
||||
|
||||
/**
|
||||
* Example of how to use the {@link Node} class.
|
||||
*
|
||||
*/
|
||||
fun main(args: Array<String>) {
|
||||
val tree = Node(4)
|
||||
val keys = arrayOf(8, 15, 21, 3, 7, 2, 5, 10, 2, 3, 4, 6, 11)
|
||||
for (key in keys) {
|
||||
tree.insert(key)
|
||||
}
|
||||
val node = tree.find(4)!!
|
||||
println("Node with value ${node.key} [left = ${node.left?.key}, right = ${node.right?.key}]")
|
||||
println("Delete node with key = 3")
|
||||
node.delete(3)
|
||||
print("Tree content after the node elimination: ")
|
||||
println(tree.visit().joinToString { it.toString() })
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
package com.baeldung.datastructures
|
||||
|
||||
/**
|
||||
* An ADT for a binary search tree.
|
||||
* Note that this data type is neither immutable nor thread safe.
|
||||
*/
|
||||
class Node(
|
||||
var key: Int,
|
||||
var left: Node? = null,
|
||||
var right: Node? = null) {
|
||||
|
||||
/**
|
||||
* Return a node with given value. If no such node exists, return null.
|
||||
* @param value
|
||||
*/
|
||||
fun find(value: Int): Node? = when {
|
||||
this.key > value -> left?.find(value)
|
||||
this.key < value -> right?.find(value)
|
||||
else -> this
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a given value into the tree.
|
||||
* After insertion, the tree should contain a node with the given value.
|
||||
* If the tree already contains the given value, nothing is performed.
|
||||
* @param value
|
||||
*/
|
||||
fun insert(value: Int) {
|
||||
if (value > this.key) {
|
||||
if (this.right == null) {
|
||||
this.right = Node(value)
|
||||
} else {
|
||||
this.right?.insert(value)
|
||||
}
|
||||
} else if (value < this.key) {
|
||||
if (this.left == null) {
|
||||
this.left = Node(value)
|
||||
} else {
|
||||
this.left?.insert(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the value from the given tree. If the tree does not contain the value, the tree remains unchanged.
|
||||
* @param value
|
||||
*/
|
||||
fun delete(value: Int) {
|
||||
when {
|
||||
value > key -> scan(value, this.right, this)
|
||||
value < key -> scan(value, this.left, this)
|
||||
else -> removeNode(this, null)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the tree in the search of the given value.
|
||||
* @param value
|
||||
* @param node sub-tree that potentially might contain the sought value
|
||||
* @param parent node's parent
|
||||
*/
|
||||
private fun scan(value: Int, node: Node?, parent: Node?) {
|
||||
if (node == null) {
|
||||
System.out.println("value " + value
|
||||
+ " seems not present in the tree.")
|
||||
return
|
||||
}
|
||||
when {
|
||||
value > node.key -> scan(value, node.right, node)
|
||||
value < node.key -> scan(value, node.left, node)
|
||||
value == node.key -> removeNode(node, parent)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the node.
|
||||
*
|
||||
* Removal process depends on how many children the node has.
|
||||
*
|
||||
* @param node node that is to be removed
|
||||
* @param parent parent of the node to be removed
|
||||
*/
|
||||
private fun removeNode(node: Node, parent: Node?) {
|
||||
node.left?.let { leftChild ->
|
||||
run {
|
||||
node.right?.let {
|
||||
removeTwoChildNode(node)
|
||||
} ?: removeSingleChildNode(node, leftChild)
|
||||
}
|
||||
} ?: run {
|
||||
node.right?.let { rightChild -> removeSingleChildNode(node, rightChild) } ?: removeNoChildNode(node, parent)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the node without children.
|
||||
* @param node
|
||||
* @param parent
|
||||
*/
|
||||
private fun removeNoChildNode(node: Node, parent: Node?) {
|
||||
parent?.let { p ->
|
||||
if (node == p.left) {
|
||||
p.left = null
|
||||
} else if (node == p.right) {
|
||||
p.right = null
|
||||
}
|
||||
} ?: throw IllegalStateException(
|
||||
"Can not remove the root node without child nodes")
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a node that has two children.
|
||||
*
|
||||
* The process of elimination is to find the biggest key in the left sub-tree and replace the key of the
|
||||
* node that is to be deleted with that key.
|
||||
*/
|
||||
private fun removeTwoChildNode(node: Node) {
|
||||
val leftChild = node.left!!
|
||||
leftChild.right?.let {
|
||||
val maxParent = findParentOfMaxChild(leftChild)
|
||||
maxParent.right?.let {
|
||||
node.key = it.key
|
||||
maxParent.right = null
|
||||
} ?: throw IllegalStateException("Node with max child must have the right child!")
|
||||
|
||||
} ?: run {
|
||||
node.key = leftChild.key
|
||||
node.left = leftChild.left
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a node whose right child contains the biggest value in the given sub-tree.
|
||||
* Assume that the node n has a non-null right child.
|
||||
*
|
||||
* @param n
|
||||
*/
|
||||
private fun findParentOfMaxChild(n: Node): Node {
|
||||
return n.right?.let { r -> r.right?.let { findParentOfMaxChild(r) } ?: n }
|
||||
?: throw IllegalArgumentException("Right child must be non-null")
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a parent that has only one child.
|
||||
* Removal is effectively is just coping the data from the child parent to the parent parent.
|
||||
* @param parent Node to be deleted. Assume that it has just one child
|
||||
* @param child Assume it is a child of the parent
|
||||
*/
|
||||
private fun removeSingleChildNode(parent: Node, child: Node) {
|
||||
parent.key = child.key
|
||||
parent.left = child.left
|
||||
parent.right = child.right
|
||||
}
|
||||
|
||||
fun visit(): Array<Int> {
|
||||
val a = left?.visit() ?: emptyArray()
|
||||
val b = right?.visit() ?: emptyArray()
|
||||
return a + arrayOf(key) + b
|
||||
}
|
||||
}
|
|
@ -0,0 +1,319 @@
|
|||
package com.baeldung.datastructures
|
||||
|
||||
import org.junit.After
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class NodeTest {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test suit for finding the node by value
|
||||
* Partition the tests as follows:
|
||||
* 1. tree depth: 0, 1, > 1
|
||||
* 2. pivot depth location: not present, 0, 1, 2, > 2
|
||||
*/
|
||||
|
||||
/**
|
||||
* Find the node by value
|
||||
* 1. tree depth: 0
|
||||
* 2. pivot depth location: not present
|
||||
*/
|
||||
@Test
|
||||
fun givenDepthZero_whenPivotNotPresent_thenNull() {
|
||||
val n = Node(1)
|
||||
assertNull(n.find(2))
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the node by value
|
||||
* 1. tree depth: 0
|
||||
* 2. pivot depth location: 0
|
||||
*/
|
||||
@Test
|
||||
fun givenDepthZero_whenPivotDepthZero_thenReturnNodeItself() {
|
||||
val n = Node(1)
|
||||
assertEquals(n, n.find(1))
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the node by value
|
||||
* 1. tree depth: 1
|
||||
* 2. pivot depth location: not present
|
||||
*/
|
||||
@Test
|
||||
fun givenDepthOne_whenPivotNotPresent_thenNull() {
|
||||
val n = Node(1, Node(0))
|
||||
assertNull(n.find(2))
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the node by value
|
||||
* 1. tree depth: 1
|
||||
* 2. pivot depth location: not present
|
||||
*/
|
||||
@Test
|
||||
fun givenDepthOne_whenPivotAtDepthOne_thenSuccess() {
|
||||
val n = Node(1, Node(0))
|
||||
assertEquals(n.left, n.find(0)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenDepthTwo_whenPivotAtDepth2_then_Success() {
|
||||
val left = Node(1, Node(0), Node(2))
|
||||
val right = Node(5, Node(4), Node(6))
|
||||
val n = Node(3, left, right)
|
||||
assertEquals(left.left, n.find(0))
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test suit for inserting a value
|
||||
* Partition the test as follows:
|
||||
* 1. tree depth: 0, 1, 2, > 2
|
||||
* 2. depth to insert: 0, 1, > 1
|
||||
* 3. is duplicate: no, yes
|
||||
* 4. sub-tree: left, right
|
||||
*/
|
||||
/**
|
||||
* Test for inserting a value
|
||||
* 1. tree depth: 0
|
||||
* 2. depth to insert: 1
|
||||
* 3. is duplicate: no
|
||||
* 4. sub-tree: right
|
||||
*/
|
||||
@Test
|
||||
fun givenTreeDepthZero_whenInsertNoDuplicateToRight_thenAddNode() {
|
||||
val n = Node(1)
|
||||
n.insert(2)
|
||||
assertEquals(1, n.key)
|
||||
with(n.right!!) {
|
||||
assertEquals(2, key)
|
||||
assertNull(left)
|
||||
assertNull(right)
|
||||
}
|
||||
assertNull(n.left)
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for inserting a value
|
||||
* 1. tree depth: 0
|
||||
* 2. depth to insert: 1
|
||||
* 3. is duplicate: no
|
||||
* 4. sub-tree: right
|
||||
*/
|
||||
@Test
|
||||
fun givenTreeDepthZero_whenInsertNoDuplicateToLeft_thenSuccess() {
|
||||
val n = Node(1)
|
||||
n.insert(0)
|
||||
assertEquals(1, n.key)
|
||||
with(n.left!!) {
|
||||
assertEquals(0, key)
|
||||
assertNull(left)
|
||||
assertNull(right)
|
||||
}
|
||||
assertNull(n.right)
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for inserting a value
|
||||
* 1. tree depth: 0
|
||||
* 2. depth to insert: 1
|
||||
* 3. is duplicate: yes
|
||||
*/
|
||||
@Test
|
||||
fun givenTreeDepthZero_whenInsertDuplicate_thenSuccess() {
|
||||
val n = Node(1)
|
||||
n.insert(1)
|
||||
assertEquals(1, n.key)
|
||||
assertNull(n.right)
|
||||
assertNull(n.left)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test suit for inserting a value
|
||||
* Partition the test as follows:
|
||||
* 1. tree depth: 0, 1, 2, > 2
|
||||
* 2. depth to insert: 0, 1, > 1
|
||||
* 3. is duplicate: no, yes
|
||||
* 4. sub-tree: left, right
|
||||
*/
|
||||
/**
|
||||
* Test for inserting a value
|
||||
* 1. tree depth: 1
|
||||
* 2. depth to insert: 1
|
||||
* 3. is duplicate: no
|
||||
* 4. sub-tree: right
|
||||
*/
|
||||
@Test
|
||||
fun givenTreeDepthOne_whenInsertNoDuplicateToRight_thenSuccess() {
|
||||
val n = Node(10, Node(3))
|
||||
n.insert(15)
|
||||
assertEquals(10, n.key)
|
||||
with(n.right!!) {
|
||||
assertEquals(15, key)
|
||||
assertNull(left)
|
||||
assertNull(right)
|
||||
}
|
||||
with(n.left!!) {
|
||||
assertEquals(3, key)
|
||||
assertNull(left)
|
||||
assertNull(right)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for inserting a value
|
||||
* 1. tree depth: 1
|
||||
* 2. depth to insert: 1
|
||||
* 3. is duplicate: no
|
||||
* 4. sub-tree: left
|
||||
*/
|
||||
@Test
|
||||
fun givenTreeDepthOne_whenInsertNoDuplicateToLeft_thenAddNode() {
|
||||
val n = Node(10, null, Node(15))
|
||||
n.insert(3)
|
||||
assertEquals(10, n.key)
|
||||
with(n.right!!) {
|
||||
assertEquals(15, key)
|
||||
assertNull(left)
|
||||
assertNull(right)
|
||||
}
|
||||
with(n.left!!) {
|
||||
assertEquals(3, key)
|
||||
assertNull(left)
|
||||
assertNull(right)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for inserting a value
|
||||
* 1. tree depth: 1
|
||||
* 2. depth to insert: 1
|
||||
* 3. is duplicate: yes
|
||||
*/
|
||||
@Test
|
||||
fun givenTreeDepthOne_whenInsertDuplicate_thenNoChange() {
|
||||
val n = Node(10, null, Node(15))
|
||||
n.insert(15)
|
||||
assertEquals(10, n.key)
|
||||
with(n.right!!) {
|
||||
assertEquals(15, key)
|
||||
assertNull(left)
|
||||
assertNull(right)
|
||||
}
|
||||
assertNull(n.left)
|
||||
}
|
||||
|
||||
/**
|
||||
* Test suit for removal
|
||||
* Partition the input as follows:
|
||||
* 1. tree depth: 0, 1, 2, > 2
|
||||
* 2. value to delete: absent, present
|
||||
* 3. # child nodes: 0, 1, 2
|
||||
*/
|
||||
/**
|
||||
* Test for removal value
|
||||
* 1. tree depth: 0
|
||||
* 2. value to delete: absent
|
||||
*/
|
||||
@Test
|
||||
fun givenTreeDepthZero_whenValueAbsent_thenNoChange() {
|
||||
val n = Node(1)
|
||||
n.delete(0)
|
||||
assertEquals(1, n.key)
|
||||
assertNull(n.left)
|
||||
assertNull(n.right)
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for removal
|
||||
* 1. tree depth: 1
|
||||
* 2. value to delete: absent
|
||||
*/
|
||||
@Test
|
||||
fun givenTreeDepthOne_whenValueAbsent_thenNoChange() {
|
||||
val n = Node(1, Node(0), Node(2))
|
||||
n.delete(3)
|
||||
assertEquals(1, n.key)
|
||||
assertEquals(2, n.right!!.key)
|
||||
with(n.left!!) {
|
||||
assertEquals(0, key)
|
||||
assertNull(left)
|
||||
assertNull(right)
|
||||
}
|
||||
with(n.right!!) {
|
||||
assertNull(left)
|
||||
assertNull(right)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test suit for removal
|
||||
* 1. tree depth: 1
|
||||
* 2. value to delete: present
|
||||
* 3. # child nodes: 0
|
||||
*/
|
||||
@Test
|
||||
fun givenTreeDepthOne_whenNodeToDeleteHasNoChildren_thenChangeTree() {
|
||||
val n = Node(1, Node(0))
|
||||
n.delete(0)
|
||||
assertEquals(1, n.key)
|
||||
assertNull(n.left)
|
||||
assertNull(n.right)
|
||||
}
|
||||
|
||||
/**
|
||||
* Test suit for removal
|
||||
* 1. tree depth: 2
|
||||
* 2. value to delete: present
|
||||
* 3. # child nodes: 1
|
||||
*/
|
||||
@Test
|
||||
fun givenTreeDepthTwo_whenNodeToDeleteHasOneChild_thenChangeTree() {
|
||||
val n = Node(2, Node(0, null, Node(1)), Node(3))
|
||||
n.delete(0)
|
||||
assertEquals(2, n.key)
|
||||
with(n.right!!) {
|
||||
assertEquals(3, key)
|
||||
assertNull(left)
|
||||
assertNull(right)
|
||||
}
|
||||
with(n.left!!) {
|
||||
assertEquals(1, key)
|
||||
assertNull(left)
|
||||
assertNull(right)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenTreeDepthThree_whenNodeToDeleteHasTwoChildren_thenChangeTree() {
|
||||
val l = Node(2, Node(1), Node(5, Node(4), Node(6)))
|
||||
val r = Node(10, Node(9), Node(11))
|
||||
val n = Node(8, l, r)
|
||||
n.delete(8)
|
||||
assertEquals(6, n.key)
|
||||
with(n.left!!) {
|
||||
assertEquals(2, key)
|
||||
assertEquals(1, left!!.key)
|
||||
assertEquals(5, right!!.key)
|
||||
assertEquals(4, right!!.left!!.key)
|
||||
}
|
||||
with(n.right!!) {
|
||||
assertEquals(10, key)
|
||||
assertEquals(9, left!!.key)
|
||||
assertEquals(11, right!!.key)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
### Relevant articles
|
||||
|
||||
- [CDI Portable Extension and Flyway](https://www.baeldung.com/cdi-portable-extension)
|
|
@ -14,4 +14,5 @@
|
|||
- [Bootstrapping JPA Programmatically in Java](http://www.baeldung.com/java-bootstrap-jpa)
|
||||
- [Optimistic Locking in JPA](http://www.baeldung.com/jpa-optimistic-locking)
|
||||
- [Hibernate Entity Lifecycle](https://www.baeldung.com/hibernate-entity-lifecycle)
|
||||
- [Mapping A Hibernate Query to a Custom Class](https://www.baeldung.com/hibernate-query-to-custom-class)
|
||||
- [@JoinColumn Annotation Explained](https://www.baeldung.com/jpa-join-column)
|
||||
|
|
|
@ -4,13 +4,23 @@ import javax.persistence.Entity;
|
|||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Parameter;
|
||||
|
||||
@Entity
|
||||
public class User {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence-generator")
|
||||
@SequenceGenerator(name = "sequence-generator", sequenceName = "user_sequence", initialValue = 4)
|
||||
@GeneratedValue(generator = "sequence-generator")
|
||||
@GenericGenerator(
|
||||
name = "sequence-generator",
|
||||
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
|
||||
parameters = {
|
||||
@Parameter(name = "sequence_name", value = "user_sequence"),
|
||||
@Parameter(name = "initial_value", value = "4"),
|
||||
@Parameter(name = "increment_size", value = "1")
|
||||
}
|
||||
)
|
||||
private long userId;
|
||||
|
||||
public long getUserId() {
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
<joda-time.version>2.10</joda-time.version>
|
||||
<!-- testing -->
|
||||
<assertj.version>3.6.1</assertj.version>
|
||||
<maven.compiler.source>9</maven.compiler.source>
|
||||
<maven.compiler.target>9</maven.compiler.target>
|
||||
<maven.compiler.source>1.9</maven.compiler.source>
|
||||
<maven.compiler.target>1.9</maven.compiler.target>
|
||||
</properties>
|
||||
</project>
|
||||
|
|
|
@ -5,7 +5,9 @@ import org.junit.Test;
|
|||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Period;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
@ -27,6 +29,17 @@ public class DateDiffUnitTest {
|
|||
assertEquals(diff, 6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() {
|
||||
LocalDate now = LocalDate.now();
|
||||
LocalDate sixDaysBehind = now.minusDays(6);
|
||||
|
||||
Period period = Period.between(now, sixDaysBehind);
|
||||
int diff = period.getDays();
|
||||
|
||||
assertEquals(diff, 6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTwoDateTimesInJava8_whenDifferentiating_thenWeGetSix() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
package com.baeldung.datetime;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class DateTimeFormatterUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenDefaultUsLocaleAndDateTimeAndPattern_whenFormatWithDifferentLocales_thenGettingLocalizedDateTimes() {
|
||||
Locale.setDefault(Locale.US);
|
||||
LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500);
|
||||
String pattern = "dd-MMMM-yyyy HH:mm:ss.SSS";
|
||||
|
||||
DateTimeFormatter defaultTimeFormatter = DateTimeFormatter.ofPattern(pattern);
|
||||
DateTimeFormatter plTimeFormatter = DateTimeFormatter.ofPattern(pattern, new Locale("pl", "PL"));
|
||||
DateTimeFormatter deTimeFormatter = DateTimeFormatter.ofPattern(pattern).withLocale(Locale.GERMANY);
|
||||
|
||||
Assert.assertEquals("01-January-2018 10:15:50.000", defaultTimeFormatter.format(localDateTime));
|
||||
Assert.assertEquals("01-stycznia-2018 10:15:50.000", plTimeFormatter.format(localDateTime));
|
||||
Assert.assertEquals("01-Januar-2018 10:15:50.000", deTimeFormatter.format(localDateTime));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDateTimeAndTimeZone_whenFormatWithDifferentLocales_thenGettingLocalizedZonedDateTimes() {
|
||||
Locale.setDefault(Locale.US);
|
||||
LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500);
|
||||
ZoneId losAngelesTimeZone = TimeZone.getTimeZone("America/Los_Angeles").toZoneId();
|
||||
|
||||
DateTimeFormatter localizedFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
|
||||
DateTimeFormatter frLocalizedFormatter =
|
||||
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(Locale.FRANCE);
|
||||
String formattedDateTime = localizedFormatter.format(ZonedDateTime.of(localDateTime, losAngelesTimeZone));
|
||||
String frFormattedDateTime = frLocalizedFormatter.format(ZonedDateTime.of(localDateTime, losAngelesTimeZone));
|
||||
|
||||
Assert.assertEquals("Monday, January 1, 2018 10:15:50 AM PST", formattedDateTime);
|
||||
Assert.assertEquals("lundi 1 janvier 2018 10 h 15 PST", frFormattedDateTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPrintFormattedDate() {
|
||||
String europeanDatePattern = "dd.MM.yyyy";
|
||||
DateTimeFormatter europeanDateFormatter = DateTimeFormatter.ofPattern(europeanDatePattern);
|
||||
LocalDate summerDay = LocalDate.of(2016, 7, 31);
|
||||
Assert.assertEquals("31.07.2016", europeanDateFormatter.format(summerDay));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPrintFormattedTime24() {
|
||||
String timeColonPattern = "HH:mm:ss";
|
||||
DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern);
|
||||
LocalTime colonTime = LocalTime.of(17, 35, 50);
|
||||
Assert.assertEquals("17:35:50", timeColonFormatter.format(colonTime));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPrintFormattedTimeWithMillis() {
|
||||
String timeColonPattern = "HH:mm:ss SSS";
|
||||
DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern);
|
||||
LocalTime colonTime = LocalTime.of(17, 35, 50).plus(329, ChronoUnit.MILLIS);
|
||||
Assert.assertEquals("17:35:50 329", timeColonFormatter.format(colonTime));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPrintFormattedTimePM() {
|
||||
String timeColonPattern = "hh:mm:ss a";
|
||||
DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern);
|
||||
LocalTime colonTime = LocalTime.of(17, 35, 50);
|
||||
Assert.assertEquals("05:35:50 PM", timeColonFormatter.format(colonTime));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPrintFormattedUTCRelatedZonedDateTime() {
|
||||
String newYorkDateTimePattern = "dd.MM.yyyy HH:mm z";
|
||||
DateTimeFormatter newYorkDateFormatter = DateTimeFormatter.ofPattern(newYorkDateTimePattern);
|
||||
LocalDateTime summerDay = LocalDateTime.of(2016, 7, 31, 14, 15);
|
||||
Assert.assertEquals("31.07.2016 14:15 UTC-04:00", newYorkDateFormatter.format(ZonedDateTime.of(summerDay, ZoneId.of("UTC-4"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPrintFormattedNewYorkZonedDateTime() {
|
||||
String newYorkDateTimePattern = "dd.MM.yyyy HH:mm z";
|
||||
DateTimeFormatter newYorkDateFormatter = DateTimeFormatter.ofPattern(newYorkDateTimePattern);
|
||||
LocalDateTime summerDay = LocalDateTime.of(2016, 7, 31, 14, 15);
|
||||
Assert.assertEquals("31.07.2016 14:15 EDT", newYorkDateFormatter.format(ZonedDateTime.of(summerDay, ZoneId.of("America/New_York"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPrintStyledDate() {
|
||||
LocalDate anotherSummerDay = LocalDate.of(2016, 8, 23);
|
||||
Assert.assertEquals("Tuesday, August 23, 2016", DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(anotherSummerDay));
|
||||
Assert.assertEquals("August 23, 2016", DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).format(anotherSummerDay));
|
||||
Assert.assertEquals("Aug 23, 2016", DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).format(anotherSummerDay));
|
||||
Assert.assertEquals("8/23/16", DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).format(anotherSummerDay));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPrintStyledDateTime() {
|
||||
LocalDateTime anotherSummerDay = LocalDateTime.of(2016, 8, 23, 13, 12, 45);
|
||||
Assert.assertEquals("Tuesday, August 23, 2016 1:12:45 PM EET", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay));
|
||||
Assert.assertEquals("August 23, 2016 1:12:45 PM EET", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay));
|
||||
Assert.assertEquals("Aug 23, 2016 1:12:45 PM", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay));
|
||||
Assert.assertEquals("8/23/16 1:12 PM", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPrintFormattedDateTimeWithPredefined() {
|
||||
Assert.assertEquals("2018-03-09", DateTimeFormatter.ISO_LOCAL_DATE.format(LocalDate.of(2018, 3, 9)));
|
||||
Assert.assertEquals("2018-03-09-03:00", DateTimeFormatter.ISO_OFFSET_DATE.format(LocalDate.of(2018, 3, 9).atStartOfDay(ZoneId.of("UTC-3"))));
|
||||
Assert.assertEquals("Fri, 9 Mar 2018 00:00:00 -0300", DateTimeFormatter.RFC_1123_DATE_TIME.format(LocalDate.of(2018, 3, 9).atStartOfDay(ZoneId.of("UTC-3"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldParseDateTime() {
|
||||
Assert.assertEquals(LocalDate.of(2018, 3, 12), LocalDate.from(DateTimeFormatter.ISO_LOCAL_DATE.parse("2018-03-09")).plusDays(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldParseFormatStyleFull() {
|
||||
ZonedDateTime dateTime = ZonedDateTime.from(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).parse("Tuesday, August 23, 2016 1:12:45 PM EET"));
|
||||
Assert.assertEquals(ZonedDateTime.of(LocalDateTime.of(2016, 8, 23, 22, 12, 45), ZoneId.of("Europe/Bucharest")), dateTime.plusHours(9));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldParseDateWithCustomFormatter() {
|
||||
DateTimeFormatter europeanDateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
|
||||
Assert.assertFalse(LocalDate.from(europeanDateFormatter.parse("15.08.2014")).isLeapYear());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldParseTimeWithCustomFormatter() {
|
||||
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm:ss a");
|
||||
Assert.assertTrue(LocalTime.from(timeFormatter.parse("12:25:30 AM")).isBefore(LocalTime.NOON));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldParseZonedDateTimeWithCustomFormatter() {
|
||||
DateTimeFormatter zonedFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm z");
|
||||
Assert.assertEquals(7200, ZonedDateTime.from(zonedFormatter.parse("31.07.2016 14:15 GMT+02:00")).getOffset().getTotalSeconds());
|
||||
}
|
||||
|
||||
@Test(expected = DateTimeParseException.class)
|
||||
public void shouldExpectAnExceptionIfDateTimeStringNotMatchPattern() {
|
||||
DateTimeFormatter zonedFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm z");
|
||||
ZonedDateTime.from(zonedFormatter.parse("31.07.2016 14:15"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.baeldung.zoneddatetime;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ZonedDateTimeUnitTest {
|
||||
|
||||
private static final Logger log = Logger.getLogger(ZonedDateTimeUnitTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testZonedDateTimeToString() {
|
||||
|
||||
ZonedDateTime zonedDateTimeNow = ZonedDateTime.now(ZoneId.of("UTC"));
|
||||
ZonedDateTime zonedDateTimeOf = ZonedDateTime.of(2018, 01, 01, 0, 0, 0, 0, ZoneId.of("UTC"));
|
||||
|
||||
LocalDateTime localDateTime = LocalDateTime.now();
|
||||
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.of("UTC"));
|
||||
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy - hh:mm:ss Z");
|
||||
String formattedString = zonedDateTime.format(formatter);
|
||||
|
||||
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/dd/yyyy - hh:mm:ss z");
|
||||
String formattedString2 = zonedDateTime.format(formatter2);
|
||||
|
||||
log.info(formattedString);
|
||||
log.info(formattedString2);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZonedDateTimeFromString() {
|
||||
|
||||
ZonedDateTime zonedDateTime = ZonedDateTime.parse("2011-12-03T10:15:30+01:00", DateTimeFormatter.ISO_ZONED_DATE_TIME);
|
||||
|
||||
log.info(zonedDateTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
## Relevant articles:
|
||||
|
||||
- [Period and Duration in Java](http://www.baeldung.com/java-period-duration)
|
||||
- [Introduction to the Java 8 Date/Time API](http://www.baeldung.com/java-8-date-time-intro)
|
||||
- [Migrating to the New Java 8 Date Time API](http://www.baeldung.com/migrating-to-java-8-date-time-api)
|
|
@ -1,36 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>java-difference-date</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>java-difference-date</name>
|
||||
<description>Difference between two dates in java</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>${joda-time.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.darwinsys</groupId>
|
||||
<artifactId>hirondelle-date4j</artifactId>
|
||||
<version>${hirondelle-date4j.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<joda-time.version>2.9.9</joda-time.version>
|
||||
<hirondelle-date4j.version>1.5.1</hirondelle-date4j.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,61 +0,0 @@
|
|||
package com.baeldung;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Duration;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class DateDiffUnitTest {
|
||||
@Test
|
||||
public void givenTwoDatesBeforeJava8_whenDifferentiating_thenWeGetSix() throws ParseException {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
|
||||
Date firstDate = sdf.parse("06/24/2017");
|
||||
Date secondDate = sdf.parse("06/30/2017");
|
||||
|
||||
long diffInMillies = Math.abs(secondDate.getTime() - firstDate.getTime());
|
||||
long diff = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
|
||||
|
||||
assertEquals(diff, 6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() {
|
||||
ZonedDateTime now = ZonedDateTime.now();
|
||||
ZonedDateTime sixDaysBehind = now.minusDays(6);
|
||||
|
||||
Duration duration = Duration.between(now, sixDaysBehind);
|
||||
long diff = Math.abs(duration.toDays());
|
||||
|
||||
assertEquals(diff, 6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTwoDatesInJodaTime_whenDifferentiating_thenWeGetSix() {
|
||||
DateTime now = DateTime.now();
|
||||
DateTime sixDaysBehind = now.minusDays(6);
|
||||
|
||||
org.joda.time.Duration duration = new org.joda.time.Duration(now, sixDaysBehind);
|
||||
long diff = Math.abs(duration.getStandardDays());
|
||||
|
||||
assertEquals(diff, 6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTwoDatesInDate4j_whenDifferentiating_thenWeGetSix() {
|
||||
hirondelle.date4j.DateTime now = hirondelle.date4j.DateTime.now(TimeZone.getDefault());
|
||||
hirondelle.date4j.DateTime sixDaysBehind = now.minusDays(6);
|
||||
|
||||
long diff = Math.abs(now.numDaysFrom(sixDaysBehind));
|
||||
|
||||
assertEquals(diff, 6);
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@
|
|||
- [Compact Strings in Java 9](http://www.baeldung.com/java-9-compact-string)
|
||||
- [Java Check a String for Lowercase/Uppercase Letter, Special Character and Digit](https://www.baeldung.com/java-lowercase-uppercase-special-character-digit-regex)
|
||||
- [Convert java.util.Date to String](https://www.baeldung.com/java-util-date-to-string)
|
||||
- [Get Substring from String in Java](https://www.baeldung.com/java-substring)
|
||||
- [Converting a Stack Trace to a String in Java](https://www.baeldung.com/java-stacktrace-to-string)
|
||||
- [Sorting a String Alphabetically in Java](https://www.baeldung.com/java-sort-string-alphabetically)
|
||||
- [Remove Emojis from a Java String](https://www.baeldung.com/java-string-remove-emojis)
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
<version>${javax.el-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.web</groupId>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>javax.el</artifactId>
|
||||
<version>${javax.el.version}</version>
|
||||
</dependency>
|
||||
|
@ -63,9 +63,9 @@
|
|||
|
||||
<properties>
|
||||
<validation-api.version>2.0.1.Final</validation-api.version>
|
||||
<hibernate-validator.version>6.0.7.Final</hibernate-validator.version>
|
||||
<hibernate-validator.version>6.0.13.Final</hibernate-validator.version>
|
||||
<javax.el-api.version>3.0.0</javax.el-api.version>
|
||||
<javax.el.version>2.2.6</javax.el.version>
|
||||
<javax.el.version>3.0.0</javax.el.version>
|
||||
<org.springframework.version>5.0.2.RELEASE</org.springframework.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
<assertj.version>3.11.1</assertj.version>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
### Relevant Articles:
|
||||
- [Securing Java EE with Spring Security](http://www.baeldung.com/java-ee-spring-security)
|
|
@ -0,0 +1,102 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jee-7-security</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
<name>jee-7-security</name>
|
||||
<description>JavaEE 7 Spring Security Application</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax</groupId>
|
||||
<artifactId>javaee-api</artifactId>
|
||||
<version>${javaee_api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.faces</groupId>
|
||||
<artifactId>jsf-api</artifactId>
|
||||
<version>${com.sun.faces.jsf.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.faces</groupId>
|
||||
<artifactId>jsf-impl</artifactId>
|
||||
<version>${com.sun.faces.jsf.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>${jstl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>${javax.servlet-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet.jsp</groupId>
|
||||
<artifactId>jsp-api</artifactId>
|
||||
<version>${jsp-api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>taglibs</groupId>
|
||||
<artifactId>standard</artifactId>
|
||||
<version>${taglibs.standard.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.mvc</groupId>
|
||||
<artifactId>javax.mvc-api</artifactId>
|
||||
<version>1.0-pr</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>${org.springframework.security.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>${org.springframework.security.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-taglibs</artifactId>
|
||||
<version>${org.springframework.security.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
<configuration>
|
||||
<warSourceDirectory>src/main/webapp</warSourceDirectory>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<javaee_api.version>7.0</javaee_api.version>
|
||||
<com.sun.faces.jsf.version>2.2.14</com.sun.faces.jsf.version>
|
||||
<jsp-api.version>2.2</jsp-api.version>
|
||||
<taglibs.standard.version>1.1.2</taglibs.standard.version>
|
||||
<org.springframework.security.version>4.2.3.RELEASE</org.springframework.security.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.springSecurity;
|
||||
package com.baeldung.springsecurity;
|
||||
|
||||
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.springSecurity;
|
||||
package com.baeldung.springsecurity;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.springSecurity.controller;
|
||||
package com.baeldung.springsecurity.controller;
|
||||
|
||||
import javax.mvc.annotation.Controller;
|
||||
import javax.ws.rs.GET;
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.springSecurity.controller;
|
||||
package com.baeldung.springsecurity.controller;
|
||||
|
||||
import javax.mvc.annotation.Controller;
|
||||
import javax.ws.rs.GET;
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<faces-config
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
||||
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
|
||||
version="2.0">
|
||||
</faces-config>
|
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
<!-- The bare minimum needed for JSF 2.2 is a servlet 2.5 or later
|
||||
declaration (this uses 3.0) and the mapping for the FacesServlet.
|
||||
Setting PROJECT_STAGE to Development is highly recommended
|
||||
during initial development so that you get more helpful
|
||||
error messages. Whether you want server-side state saving
|
||||
(default) or client-side is a more complicated question:
|
||||
client-side uses more bandwidth but fewer server resources.
|
||||
Client-side also helps to avoid the dreaded view expired exceptions.
|
||||
|
||||
From JSF 2 and PrimeFaces tutorial
|
||||
at http://www.coreservlets.com/JSF-Tutorial/jsf2/
|
||||
-->
|
||||
<servlet>
|
||||
<servlet-name>Faces Servlet</servlet-name>
|
||||
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>Faces Servlet</servlet-name>
|
||||
<url-pattern>*.jsf</url-pattern>
|
||||
</servlet-mapping>
|
||||
<context-param>
|
||||
<param-name>javax.faces.PROJECT_STAGE</param-name>
|
||||
<param-value>Development</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<description>State saving method: 'client' or 'server' (default). See JSF Specification section 2.5.2</description>
|
||||
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
|
||||
<param-value>client</param-value>
|
||||
</context-param>
|
||||
<!-- If you go to http://host/project/ (with no file name), it will
|
||||
try index.jsf first, welcome.jsf next, and so forth.
|
||||
-->
|
||||
|
||||
|
||||
<!-- UNCOMMENT THE FOLLOWING SECTION FOR SPRING SECURITY XML CONFIGURATION-->
|
||||
|
||||
<!--<context-param>-->
|
||||
<!--<param-name>contextConfigLocation</param-name>-->
|
||||
<!--<param-value>-->
|
||||
<!--/WEB-INF/spring/*.xml-->
|
||||
<!--</param-value>-->
|
||||
<!--</context-param>-->
|
||||
|
||||
<!--<filter>-->
|
||||
<!--<filter-name>springSecurityFilterChain</filter-name>-->
|
||||
<!--<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>-->
|
||||
<!--</filter>-->
|
||||
|
||||
<!--<filter-mapping>-->
|
||||
<!--<filter-name>springSecurityFilterChain</filter-name>-->
|
||||
<!--<url-pattern>/*</url-pattern>-->
|
||||
<!--</filter-mapping>-->
|
||||
|
||||
<!--<listener>-->
|
||||
<!--<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>-->
|
||||
<!--</listener>-->
|
||||
|
||||
<!-- END SPRING SECURITY XML CONFIGURATION-->
|
||||
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.jsf</welcome-file>
|
||||
<welcome-file>welcome.jsf</welcome-file>
|
||||
<welcome-file>index.html</welcome-file>
|
||||
<welcome-file>index.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
</web-app>
|
|
@ -5,5 +5,3 @@
|
|||
- [Introduction to JAX-WS](http://www.baeldung.com/jax-ws)
|
||||
- [A Guide to Java EE Web-Related Annotations](http://www.baeldung.com/javaee-web-annotations)
|
||||
- [Introduction to Testing with Arquillian](http://www.baeldung.com/arquillian)
|
||||
- [Securing Java EE with Spring Security](http://www.baeldung.com/java-ee-spring-security)
|
||||
- [A Guide to Java EE Web-Related Annotations](https://www.baeldung.com/javaee-web-annotations)
|
|
@ -1,13 +0,0 @@
|
|||
package com.baeldung.springSecurity;
|
||||
|
||||
import javax.ws.rs.ApplicationPath;
|
||||
import javax.ws.rs.core.Application;
|
||||
|
||||
/**
|
||||
* Application class required by JAX-RS. If you don't want to have any
|
||||
* prefix in the URL, you can set the application path to "/".
|
||||
*/
|
||||
@ApplicationPath("/")
|
||||
public class ApplicationConfig extends Application {
|
||||
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
|
||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
<!-- The bare minimum needed for JSF 2.2 is a servlet 2.5 or later
|
||||
declaration (this uses 3.0) and the mapping for the FacesServlet.
|
||||
Setting PROJECT_STAGE to Development is highly recommended
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- [Jersey Filters and Interceptors](http://www.baeldung.com/jersey-filters-interceptors)
|
||||
- [Jersey MVC Support](https://www.baeldung.com/jersey-mvc)
|
||||
- [Bean Validation in Jersey](https://www.baeldung.com/jersey-bean-validation)
|
||||
- [Set a Response Body in JAX-RS](https://www.baeldung.com/jax-rs-response)
|
||||
|
|
|
@ -11,3 +11,4 @@
|
|||
- [Apache Ignite with Spring Data](http://www.baeldung.com/apache-ignite-spring-data)
|
||||
- [Guide to JMapper](https://www.baeldung.com/jmapper)
|
||||
- [A Guide to Apache Crunch](https://www.baeldung.com/apache-crunch)
|
||||
- [Building a Data Pipeline with Flink and Kafka](https://www.baeldung.com/kafka-flink-data-pipeline)
|
||||
|
|
|
@ -249,7 +249,32 @@
|
|||
<version>${awaitility.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>${ebean.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -378,7 +403,24 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>11.11.2</version>
|
||||
<executions>
|
||||
<!-- enhance main classes -->
|
||||
<execution>
|
||||
<id>main</id>
|
||||
<phase>process-classes</phase>
|
||||
<configuration>
|
||||
<transformArgs>debug=1</transformArgs>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>enhance</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
@ -416,6 +458,9 @@
|
|||
<jmapper.version>1.6.0.1</jmapper.version>
|
||||
<org.apache.crunch.crunch-core.version>0.15.0</org.apache.crunch.crunch-core.version>
|
||||
<org.apache.hadoop.hadoop-client>2.2.0</org.apache.hadoop.hadoop-client>
|
||||
<ebean.version>11.22.4</ebean.version>
|
||||
<slf4j.version>1.7.25</slf4j.version>
|
||||
<logback.version>1.0.1</logback.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package com.baeldung.ebean.app;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.baeldung.ebean.model.Address;
|
||||
import com.baeldung.ebean.model.Customer;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.annotation.Transactional;
|
||||
|
||||
public class App {
|
||||
|
||||
public static void main(String[] args) {
|
||||
insertAndDeleteInsideTransaction();
|
||||
crudOperations();
|
||||
queryCustomers();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public static void insertAndDeleteInsideTransaction() {
|
||||
|
||||
Customer c1 = getCustomer();
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
server.save(c1);
|
||||
Customer foundC1 = server.find(Customer.class, c1.getId());
|
||||
server.delete(foundC1);
|
||||
}
|
||||
|
||||
public static void crudOperations() {
|
||||
|
||||
Address a1 = new Address("5, Wide Street", null, "New York");
|
||||
Customer c1 = new Customer("John Wide", a1);
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
server.save(c1);
|
||||
|
||||
c1.setName("Jane Wide");
|
||||
c1.setAddress(null);
|
||||
server.save(c1);
|
||||
|
||||
Customer foundC1 = Ebean.find(Customer.class, c1.getId());
|
||||
|
||||
Ebean.delete(foundC1);
|
||||
}
|
||||
|
||||
public static void queryCustomers() {
|
||||
Address a1 = new Address("1, Big Street", null, "New York");
|
||||
Customer c1 = new Customer("Big John", a1);
|
||||
|
||||
Address a2 = new Address("2, Big Street", null, "New York");
|
||||
Customer c2 = new Customer("Big John", a2);
|
||||
|
||||
Address a3 = new Address("3, Big Street", null, "San Jose");
|
||||
Customer c3 = new Customer("Big Bob", a3);
|
||||
|
||||
Ebean.saveAll(Arrays.asList(c1, c2, c3));
|
||||
|
||||
Customer customer = Ebean.find(Customer.class)
|
||||
.select("name")
|
||||
.fetch("address", "city")
|
||||
.where()
|
||||
.eq("city", "San Jose")
|
||||
.findOne();
|
||||
|
||||
Ebean.deleteAll(Arrays.asList(c1, c2, c3));
|
||||
}
|
||||
|
||||
private static Customer getCustomer() {
|
||||
Address a1 = new Address("1, Big Street", null, "New York");
|
||||
Customer c1 = new Customer("Big John", a1);
|
||||
return c1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.baeldung.ebean.app;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.config.ServerConfig;
|
||||
|
||||
public class App2 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ServerConfig cfg = new ServerConfig();
|
||||
cfg.setDefaultServer(true);
|
||||
Properties properties = new Properties();
|
||||
properties.put("ebean.db.ddl.generate", "true");
|
||||
properties.put("ebean.db.ddl.run", "true");
|
||||
properties.put("datasource.db.username", "sa");
|
||||
properties.put("datasource.db.password", "");
|
||||
properties.put("datasource.db.databaseUrl", "jdbc:h2:mem:app2");
|
||||
properties.put("datasource.db.databaseDriver", "org.h2.Driver");
|
||||
cfg.loadFromProperties(properties);
|
||||
EbeanServer server = EbeanServerFactory.create(cfg);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.baeldung.ebean.model;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
public class Address extends BaseModel {
|
||||
|
||||
public Address(String addressLine1, String addressLine2, String city) {
|
||||
super();
|
||||
this.addressLine1 = addressLine1;
|
||||
this.addressLine2 = addressLine2;
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
private String addressLine1;
|
||||
private String addressLine2;
|
||||
private String city;
|
||||
|
||||
public String getAddressLine1() {
|
||||
return addressLine1;
|
||||
}
|
||||
|
||||
public void setAddressLine1(String addressLine1) {
|
||||
this.addressLine1 = addressLine1;
|
||||
}
|
||||
|
||||
public String getAddressLine2() {
|
||||
return addressLine2;
|
||||
}
|
||||
|
||||
public void setAddressLine2(String addressLine2) {
|
||||
this.addressLine2 = addressLine2;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Address [id=" + id + ", addressLine1=" + addressLine1 + ", addressLine2=" + addressLine2 + ", city=" + city + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.baeldung.ebean.model;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Version;
|
||||
|
||||
import io.ebean.annotation.WhenCreated;
|
||||
import io.ebean.annotation.WhenModified;
|
||||
|
||||
@MappedSuperclass
|
||||
public abstract class BaseModel {
|
||||
|
||||
@Id
|
||||
protected long id;
|
||||
|
||||
@Version
|
||||
protected long version;
|
||||
|
||||
@WhenCreated
|
||||
protected Instant createdOn;
|
||||
|
||||
@WhenModified
|
||||
protected Instant modifiedOn;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Instant getCreatedOn() {
|
||||
return createdOn;
|
||||
}
|
||||
|
||||
public void setCreatedOn(Instant createdOn) {
|
||||
this.createdOn = createdOn;
|
||||
}
|
||||
|
||||
public Instant getModifiedOn() {
|
||||
return modifiedOn;
|
||||
}
|
||||
|
||||
public void setModifiedOn(Instant modifiedOn) {
|
||||
this.modifiedOn = modifiedOn;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.baeldung.ebean.model;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
@Entity
|
||||
public class Customer extends BaseModel {
|
||||
|
||||
public Customer(String name, Address address) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
private String name;
|
||||
|
||||
@OneToOne(cascade = CascadeType.ALL)
|
||||
Address address;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(Address address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Customer [id=" + id + ", name=" + name + ", address=" + address + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
entity-packages: com.baeldung.ebean.model
|
||||
transactional-packages: com.baeldung.ebean.app
|
||||
querybean-packages: com.baeldung.ebean.app
|
|
@ -0,0 +1,7 @@
|
|||
ebean.db.ddl.generate=true
|
||||
ebean.db.ddl.run=true
|
||||
|
||||
datasource.db.username=sa
|
||||
datasource.db.password=
|
||||
datasource.db.databaseUrl=jdbc:h2:mem:customer
|
||||
datasource.db.databaseDriver=org.h2.Driver
|
|
@ -6,7 +6,9 @@
|
|||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="io.ebean.DDL" level="TRACE"/>
|
||||
<logger name="io.ebean.SQL" level="TRACE"/>
|
||||
<logger name="io.ebean.TXN" level="TRACE"/>
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>versions-maven-plugin-example</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<commons-compress-version>1.15</commons-compress-version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
<version>4.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>${commons-compress-version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>1.9.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>versions-maven-plugin</artifactId>
|
||||
<version>2.7</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>org.apache.commons:commons-collections4</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>apache.snapshots</id>
|
||||
<name>Apache Development Snapshot Repository</name>
|
||||
<url>https://repository.apache.org/content/repositories/snapshots/</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,76 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>versions-maven-plugin-example</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<commons-compress-version>1.15</commons-compress-version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
<version>4.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>${commons-compress-version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>1.9.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>versions-maven-plugin</artifactId>
|
||||
<version>2.7</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>org.apache.commons:commons-collections4</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>apache.snapshots</id>
|
||||
<name>Apache Development Snapshot Repository</name>
|
||||
<url>https://repository.apache.org/content/repositories/snapshots/</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,74 @@
|
|||
#!/bin/bash
|
||||
#function to display commands
|
||||
exe() { echo -e "\$ $@\n" ; "$@" ; }
|
||||
|
||||
TEXT_COLOR='\033[1;33m' #Yellow
|
||||
NO_COLOR='\033[0m' # No Color
|
||||
|
||||
clear
|
||||
|
||||
echo -e "======================================================================================"
|
||||
echo -e " Showcase for the BAELDUNG tutorial \"Use the latest version of a dependency in Maven\""
|
||||
echo -e " Author: Andrea Ligios"
|
||||
echo -e "======================================================================================"
|
||||
|
||||
echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
|
||||
echo -e " Resetting the demo environment (which will be altered during the run): "
|
||||
echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
|
||||
rm -f pom.xml.versionsBackup
|
||||
cp original/pom.xml pom.xml
|
||||
ls -lt pom.*
|
||||
echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
|
||||
echo -e " Checking for newer versions of the Maven dependencies:"
|
||||
echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
|
||||
exe mvn versions:display-dependency-updates
|
||||
echo
|
||||
read -p "Press enter to continue"
|
||||
|
||||
echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
|
||||
echo -e " Updating SNAPSHOT dependencies to their RELEASE version, if any:"
|
||||
echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
|
||||
exe mvn versions:use-releases
|
||||
echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
|
||||
echo -e " A backup has been created automatically:"
|
||||
echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
|
||||
ls -lt pom.*
|
||||
echo
|
||||
read -p "Press enter to continue"
|
||||
|
||||
echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
|
||||
echo -e " Updating RELEASE dependencies to their *next* RELEASE version:"
|
||||
echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
|
||||
exe mvn versions:use-next-releases
|
||||
echo
|
||||
read -p "Press enter to continue"
|
||||
|
||||
echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
|
||||
echo -e " Reverting every modification made since the beginning:"
|
||||
echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
|
||||
exe mvn versions:revert
|
||||
echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
|
||||
echo -e " The backup is gone, and the pom.xml contains the initial dependencies:"
|
||||
echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
|
||||
ls -lt pom.*
|
||||
echo
|
||||
read -p "Press enter to continue"
|
||||
|
||||
echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
|
||||
echo -e " Updating RELEASE dependencies to their *latest* RELEASE version:"
|
||||
echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
|
||||
exe mvn versions:use-latest-releases
|
||||
echo
|
||||
read -p "Press enter to continue"
|
||||
|
||||
echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
|
||||
echo -e " Committing the modifications to pom.xml:"
|
||||
echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
|
||||
exe mvn versions:commit
|
||||
echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
|
||||
echo -e " The backup is gone, and the pom.xml contains the latest dependencies:"
|
||||
echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
|
||||
ls -lt pom.*
|
||||
echo
|
||||
|
||||
echo -e "${TEXT_COLOR}\nThat's all folks!${NO_COLOR}\n"
|
55
pom.xml
55
pom.xml
|
@ -399,6 +399,7 @@
|
|||
<module>javafx</module>
|
||||
<module>jgroups</module>
|
||||
<module>jee-7</module>
|
||||
<module>jee-7-security</module>
|
||||
<module>jhipster</module>
|
||||
<module>jjwt</module>
|
||||
<module>jsf</module>
|
||||
|
@ -526,31 +527,6 @@
|
|||
<!-- <module>spring-rest</module> --> <!-- temporarily disabled -->
|
||||
<!-- <module>spring-rest-simple</module> --> <!-- temporarily disabled -->
|
||||
<module>spring-resttemplate</module>
|
||||
<module>spring-security-acl</module>
|
||||
<module>spring-security-cache-control</module>
|
||||
<module>spring-security-client/spring-security-jsp-authentication</module>
|
||||
<module>spring-security-client/spring-security-jsp-authorize</module>
|
||||
<module>spring-security-client/spring-security-jsp-config</module>
|
||||
<module>spring-security-client/spring-security-mvc</module>
|
||||
<module>spring-security-client/spring-security-thymeleaf-authentication</module>
|
||||
<module>spring-security-client/spring-security-thymeleaf-authorize</module>
|
||||
<module>spring-security-client/spring-security-thymeleaf-config</module>
|
||||
<module>spring-security-core</module>
|
||||
<module>spring-security-mvc-boot</module>
|
||||
<module>spring-security-mvc-custom</module>
|
||||
<module>spring-security-mvc-digest-auth</module>
|
||||
<module>spring-security-mvc-ldap</module>
|
||||
<module>spring-security-mvc-login</module>
|
||||
<module>spring-security-mvc-persisted-remember-me</module>
|
||||
<module>spring-security-mvc-session</module>
|
||||
<module>spring-security-mvc-socket</module>
|
||||
<module>spring-security-openid</module>
|
||||
<!--<module>spring-security-react</module> -->
|
||||
<module>spring-security-rest-basic-auth</module>
|
||||
<module>spring-security-rest-custom</module>
|
||||
<module>spring-security-rest</module>
|
||||
<module>spring-security-sso</module>
|
||||
<module>spring-security-x509</module>
|
||||
</modules>
|
||||
|
||||
</profile>
|
||||
|
@ -665,7 +641,6 @@
|
|||
<module>dubbo</module>
|
||||
<module>flyway</module>
|
||||
<!-- <module>grpc</module> --><!-- protobuf-maven-plugin filecopy failure -->
|
||||
<module>java-difference-date</module>
|
||||
<!-- <module>JGit</module> --><!-- Unit test failure -->
|
||||
<module>jni</module>
|
||||
<module>jooby</module>
|
||||
|
@ -721,6 +696,32 @@
|
|||
<!-- <module>guest\webservices\rest-server</module> --><!-- guest post on different site -->
|
||||
<!-- <module>guest\webservices\spring-rest-service</module> --><!-- guest post on different site -->
|
||||
<module>flyway-cdi-extension</module>
|
||||
|
||||
<module>spring-security-acl</module>
|
||||
<module>spring-security-cache-control</module>
|
||||
<module>spring-security-client/spring-security-jsp-authentication</module>
|
||||
<module>spring-security-client/spring-security-jsp-authorize</module>
|
||||
<module>spring-security-client/spring-security-jsp-config</module>
|
||||
<module>spring-security-client/spring-security-mvc</module>
|
||||
<module>spring-security-client/spring-security-thymeleaf-authentication</module>
|
||||
<module>spring-security-client/spring-security-thymeleaf-authorize</module>
|
||||
<module>spring-security-client/spring-security-thymeleaf-config</module>
|
||||
<module>spring-security-core</module>
|
||||
<module>spring-security-mvc-boot</module>
|
||||
<module>spring-security-mvc-custom</module>
|
||||
<module>spring-security-mvc-digest-auth</module>
|
||||
<module>spring-security-mvc-ldap</module>
|
||||
<module>spring-security-mvc-login</module>
|
||||
<module>spring-security-mvc-persisted-remember-me</module>
|
||||
<module>spring-security-mvc-session</module>
|
||||
<module>spring-security-mvc-socket</module>
|
||||
<module>spring-security-openid</module>
|
||||
<!--<module>spring-security-react</module> -->
|
||||
<module>spring-security-rest-basic-auth</module>
|
||||
<module>spring-security-rest-custom</module>
|
||||
<module>spring-security-rest</module>
|
||||
<module>spring-security-sso</module>
|
||||
<module>spring-security-x509</module>
|
||||
</modules>
|
||||
|
||||
</profile>
|
||||
|
@ -1138,7 +1139,6 @@
|
|||
<module>dubbo</module>
|
||||
<module>flyway</module>
|
||||
<!-- <module>grpc</module> --><!-- protobuf-maven-plugin filecopy failure -->
|
||||
<module>java-difference-date</module>
|
||||
<!-- <module>JGit</module> --><!-- Unit test failure -->
|
||||
<module>jni</module>
|
||||
<module>jooby</module>
|
||||
|
@ -1303,6 +1303,7 @@
|
|||
<module>javafx</module>
|
||||
<module>jgroups</module>
|
||||
<module>jee-7</module>
|
||||
<module>jee-7-security</module>
|
||||
<module>jjwt</module>
|
||||
<module>jsf</module>
|
||||
<module>json-path</module>
|
||||
|
|
|
@ -34,6 +34,12 @@
|
|||
<version>${mongodb-reactivestreams.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
<version>${projectreactor.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-test</artifactId>
|
||||
|
@ -109,6 +115,7 @@
|
|||
<spring.version>5.1.0.RELEASE</spring.version>
|
||||
<mongodb-reactivestreams.version>1.9.2</mongodb-reactivestreams.version>
|
||||
<projectreactor.version>3.2.0.RELEASE</projectreactor.version>
|
||||
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package com.baeldung.xml;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public class XMLDocumentWriter {
|
||||
|
||||
public void write(Document document, String fileName, boolean excludeDeclaration, boolean prettyPrint) {
|
||||
try(FileWriter writer = new FileWriter(new File(fileName))) {
|
||||
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||
Transformer transformer = transformerFactory.newTransformer();
|
||||
if(excludeDeclaration) {
|
||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||
}
|
||||
if(prettyPrint) {
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
|
||||
}
|
||||
DOMSource source = new DOMSource(document);
|
||||
StreamResult result = new StreamResult(writer);
|
||||
transformer.transform(source, result);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
} catch (TransformerConfigurationException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (TransformerException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.baeldung.xml;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class XMLDocumentWriterUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenXMLDocumentWhenWriteIsCalledThenXMLIsWrittenToFile() throws Exception {
|
||||
Document document = createSampleDocument();
|
||||
new XMLDocumentWriter().write(document, "company_simple.xml", false, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenXMLDocumentWhenWriteIsCalledWithPrettyPrintThenFormattedXMLIsWrittenToFile() throws Exception {
|
||||
Document document = createSampleDocument();
|
||||
new XMLDocumentWriter().write(document, "company_prettyprinted.xml", false, true);
|
||||
}
|
||||
|
||||
private Document createSampleDocument() throws ParserConfigurationException {
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
||||
Document document = documentBuilder.newDocument();
|
||||
Element companyElement = document.createElement("Company");
|
||||
document.appendChild(companyElement);
|
||||
Element departmentElement = document.createElement("Department");
|
||||
departmentElement.setAttribute("name", "Sales");
|
||||
companyElement.appendChild(departmentElement);
|
||||
Element employee1 = document.createElement("Employee");
|
||||
employee1.setAttribute("name", "John Smith");
|
||||
departmentElement.appendChild(employee1);
|
||||
Element employee2 = document.createElement("Employee");
|
||||
employee2.setAttribute("name", "Tim Dellor");
|
||||
departmentElement.appendChild(employee2);
|
||||
return document;
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() throws Exception {
|
||||
FileUtils.deleteQuietly(new File("company_simple.xml"));
|
||||
FileUtils.deleteQuietly(new File("company_prettyprinted.xml"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue