readFileInList(String filePath) {
+ File file = new File(filePath)
+ def lines = file.readLines()
+ return lines
+ }
+
+ /**
+ * reads file content in string using File.text
+ * @param filePath
+ * @return
+ */
+ String readFileString(String filePath) {
+ File file = new File(filePath)
+ String fileContent = file.text
+ return fileContent
+ }
+
+ /**
+ * reads file content in string with encoding using File.getText
+ * @param filePath
+ * @return
+ */
+ String readFileStringWithCharset(String filePath) {
+ File file = new File(filePath)
+ String utf8Content = file.getText("UTF-8")
+ return utf8Content
+ }
+
+ /**
+ * reads content of binary file and returns byte array
+ * @param filePath
+ * @return
+ */
+ byte[] readBinaryFile(String filePath) {
+ File file = new File(filePath)
+ byte[] binaryContent = file.bytes
+ return binaryContent
+ }
+
+ /**
+ * More Examples of reading a file
+ * @return
+ */
+ def moreExamples() {
+
+ //with reader with utf-8
+ new File("src/main/resources/utf8Content.html").withReader('UTF-8') { reader ->
+ def line
+ while ((line = reader.readLine())!=null) {
+ println "${line}"
+ }
+ }
+
+ //collect api
+ def list = new File("src/main/resources/fileContent.txt").collect {it}
+
+ //as operator
+ def array = new File("src/main/resources/fileContent.txt") as String[]
+
+ //eachline
+ new File("src/main/resources/fileContent.txt").eachLine { line ->
+ println line
+ }
+
+ //newInputStream with eachLine
+ def is = new File("src/main/resources/fileContent.txt").newInputStream()
+ is.eachLine {
+ println it
+ }
+ is.close()
+
+ //withInputStream
+ new File("src/main/resources/fileContent.txt").withInputStream { stream ->
+ stream.eachLine { line ->
+ println line
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy b/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy
new file mode 100644
index 0000000000..b3a0852a0b
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/strings/Concatenate.groovy
@@ -0,0 +1,43 @@
+package com.baeldung.strings;
+
+class Concatenate {
+ String first = 'Hello'
+ String last = 'Groovy'
+
+ String doSimpleConcat() {
+ return 'My name is ' + first + ' ' + last
+ }
+
+ String doConcatUsingGString() {
+ return "My name is $first $last"
+ }
+
+ String doConcatUsingGStringClosures() {
+ return "My name is ${-> first} ${-> last}"
+ }
+
+ String doConcatUsingStringConcatMethod() {
+ return 'My name is '.concat(first).concat(' ').concat(last)
+ }
+
+ String doConcatUsingLeftShiftOperator() {
+ return 'My name is ' << first << ' ' << last
+ }
+
+ String doConcatUsingArrayJoinMethod() {
+ return ['My name is', first, last].join(' ')
+ }
+
+ String doConcatUsingArrayInjectMethod() {
+ return [first,' ', last]
+ .inject(new StringBuffer('My name is '), { initial, name -> initial.append(name); return initial }).toString()
+ }
+
+ String doConcatUsingStringBuilder() {
+ return new StringBuilder().append('My name is ').append(first).append(' ').append(last)
+ }
+
+ String doConcatUsingStringBuffer() {
+ return new StringBuffer().append('My name is ').append(first).append(' ').append(last)
+ }
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy
new file mode 100644
index 0000000000..6ec5cda571
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/AnimalTrait.groovy
@@ -0,0 +1,8 @@
+package com.baeldung.traits
+
+trait AnimalTrait {
+
+ String basicBehavior() {
+ return "Animalistic!!"
+ }
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/Dog.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Dog.groovy
new file mode 100644
index 0000000000..3e0677ba18
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/Dog.groovy
@@ -0,0 +1,9 @@
+package com.baeldung.traits
+
+class Dog implements WalkingTrait, SpeakingTrait {
+
+ String speakAndWalk() {
+ WalkingTrait.super.speakAndWalk()
+ }
+
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy
new file mode 100644
index 0000000000..b3e4285476
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/Employee.groovy
@@ -0,0 +1,12 @@
+package com.baeldung.traits
+
+class Employee implements UserTrait {
+
+ String name() {
+ return 'Bob'
+ }
+
+ String lastName() {
+ return "Marley"
+ }
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy
new file mode 100644
index 0000000000..e78d59bbfd
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/Human.groovy
@@ -0,0 +1,6 @@
+package com.baeldung.traits
+
+interface Human {
+
+ String lastName()
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy
new file mode 100644
index 0000000000..f437a94bd9
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/SpeakingTrait.groovy
@@ -0,0 +1,13 @@
+package com.baeldung.traits
+
+trait SpeakingTrait {
+
+ String basicAbility() {
+ return "Speaking!!"
+ }
+
+ String speakAndWalk() {
+ return "Speak and walk!!"
+ }
+
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy
new file mode 100644
index 0000000000..3f1e694f17
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy
@@ -0,0 +1,36 @@
+package com.baeldung.traits
+
+trait UserTrait implements Human {
+
+ String sayHello() {
+ return "Hello!"
+ }
+
+ abstract String name()
+
+ String showName() {
+ return "Hello, ${name()}!"
+ }
+
+ private String greetingMessage() {
+ return 'Hello, from a private method!'
+ }
+
+ String greet() {
+ def msg = greetingMessage()
+ println msg
+ msg
+ }
+
+ def whoAmI() {
+ return this
+ }
+
+ String showLastName() {
+ return "Hello, ${lastName()}!"
+ }
+
+ String email
+ String address
+}
+
\ No newline at end of file
diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/WalkingTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/WalkingTrait.groovy
new file mode 100644
index 0000000000..66cff8809f
--- /dev/null
+++ b/core-groovy/src/main/groovy/com/baeldung/traits/WalkingTrait.groovy
@@ -0,0 +1,13 @@
+package com.baeldung.traits
+
+trait WalkingTrait {
+
+ String basicAbility() {
+ return "Walking!!"
+ }
+
+ String speakAndWalk() {
+ return "Walk and speak!!"
+ }
+
+}
\ No newline at end of file
diff --git a/core-groovy/src/main/resources/fileContent.txt b/core-groovy/src/main/resources/fileContent.txt
new file mode 100644
index 0000000000..643e4af3de
--- /dev/null
+++ b/core-groovy/src/main/resources/fileContent.txt
@@ -0,0 +1,3 @@
+Line 1 : Hello World!!!
+Line 2 : This is a file content.
+Line 3 : String content
diff --git a/core-groovy/src/main/resources/sample.png b/core-groovy/src/main/resources/sample.png
new file mode 100644
index 0000000000..7d473430b7
Binary files /dev/null and b/core-groovy/src/main/resources/sample.png differ
diff --git a/core-groovy/src/main/resources/utf8Content.html b/core-groovy/src/main/resources/utf8Content.html
new file mode 100644
index 0000000000..61ff338f6c
--- /dev/null
+++ b/core-groovy/src/main/resources/utf8Content.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ
+ᛋᚳᛖᚪᛚ᛫ᚦᛖᚪᚻ᛫ᛗᚪᚾᚾᚪ᛫ᚷᛖᚻᚹᛦᛚᚳ᛫ᛗᛁᚳᛚᚢᚾ᛫ᚻᛦᛏ᛫ᛞᚫᛚᚪᚾ
+ᚷᛁᚠ᛫ᚻᛖ᛫ᚹᛁᛚᛖ᛫ᚠᚩᚱ᛫ᛞᚱᛁᚻᛏᚾᛖ᛫ᛞᚩᛗᛖᛋ᛫ᚻᛚᛇᛏᚪᚾ
+
+
+
\ No newline at end of file
diff --git a/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy
new file mode 100644
index 0000000000..a479c265c4
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/file/ReadFileUnitTest.groovy
@@ -0,0 +1,70 @@
+package com.baeldung.file
+
+import spock.lang.Specification
+
+class ReadFileUnitTest extends Specification {
+
+ ReadFile readFile
+
+ void setup () {
+ readFile = new ReadFile()
+ }
+
+ def 'Should return number of lines in File using ReadFile.readFileLineByLine given filePath' () {
+ given:
+ def filePath = "src/main/resources/fileContent.txt"
+ when:
+ def noOfLines = readFile.readFileLineByLine(filePath)
+ then:
+ noOfLines
+ noOfLines instanceof Integer
+ assert noOfLines, 3
+ }
+
+ def 'Should return File Content in list of lines using ReadFile.readFileInList given filePath' () {
+ given:
+ def filePath = "src/main/resources/fileContent.txt"
+ when:
+ def lines = readFile.readFileInList(filePath)
+ then:
+ lines
+ lines instanceof List
+ assert lines.size(), 3
+ }
+
+ def 'Should return file content in string using ReadFile.readFileString given filePath' () {
+ given:
+ def filePath = "src/main/resources/fileContent.txt"
+ when:
+ def fileContent = readFile.readFileString(filePath)
+ then:
+ fileContent
+ fileContent instanceof String
+ fileContent.contains("""Line 1 : Hello World!!!
+Line 2 : This is a file content.
+Line 3 : String content""")
+
+ }
+
+ def 'Should return UTF-8 encoded file content in string using ReadFile.readFileStringWithCharset given filePath' () {
+ given:
+ def filePath = "src/main/resources/utf8Content.html"
+ when:
+ def encodedContent = readFile.readFileStringWithCharset(filePath)
+ then:
+ encodedContent
+ encodedContent instanceof String
+ }
+
+ def 'Should return binary file content in byte array using ReadFile.readBinaryFile given filePath' () {
+ given:
+ def filePath = "src/main/resources/sample.png"
+ when:
+ def binaryContent = readFile.readBinaryFile(filePath)
+ then:
+ binaryContent
+ binaryContent instanceof byte[]
+ binaryContent.length == 329
+ }
+
+}
\ No newline at end of file
diff --git a/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy b/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy
new file mode 100644
index 0000000000..3ef4a5d460
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/strings/ConcatenateTest.groovy
@@ -0,0 +1,101 @@
+import com.baeldung.strings.Concatenate;
+
+class ConcatenateTest extends GroovyTestCase {
+
+ void testSimpleConcat() {
+ def name = new Concatenate()
+ name.first = 'Joe';
+ name.last = 'Smith';
+ def expected = 'My name is Joe Smith'
+ assertToString(name.doSimpleConcat(), expected)
+ }
+
+ void testConcatUsingGString() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingGString(), expected)
+ }
+
+ void testConcatUsingGStringClosures() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingGStringClosures(), expected)
+ }
+
+ void testConcatUsingStringConcatMethod() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingStringConcatMethod(), expected)
+ }
+
+ void testConcatUsingLeftShiftOperator() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingLeftShiftOperator(), expected)
+ }
+
+ void testConcatUsingArrayJoinMethod() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingArrayJoinMethod(), expected)
+ }
+
+ void testConcatUsingArrayInjectMethod() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingArrayInjectMethod(), expected)
+ }
+
+ void testConcatUsingStringBuilder() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingStringBuilder(), expected)
+ }
+
+ void testConcatUsingStringBuffer() {
+ def name = new Concatenate()
+ name.first = "Joe";
+ name.last = "Smith";
+ def expected = "My name is Joe Smith"
+ assertToString(name.doConcatUsingStringBuffer(), expected)
+ }
+
+ void testConcatMultilineUsingStringConcatMethod() {
+ def name = new Concatenate()
+ name.first = '''Joe
+ Smith
+ ''';
+ name.last = 'Junior';
+ def expected = '''My name is Joe
+ Smith
+ Junior''';
+ assertToString(name.doConcatUsingStringConcatMethod(), expected)
+ }
+
+ void testGStringvsClosure(){
+ def first = "Joe";
+ def last = "Smith";
+ def eagerGString = "My name is $first $last"
+ def lazyGString = "My name is ${-> first} ${-> last}"
+
+ assert eagerGString == "My name is Joe Smith"
+ assert lazyGString == "My name is Joe Smith"
+ first = "David";
+ assert eagerGString == "My name is Joe Smith"
+ assert lazyGString == "My name is David Smith"
+ }
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy
new file mode 100644
index 0000000000..c043723d95
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/CharacterInGroovy.groovy
@@ -0,0 +1,19 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Assert
+import org.junit.Test
+
+class CharacterInGroovy {
+
+ @Test
+ void 'character'() {
+ char a = 'A' as char
+ char b = 'B' as char
+ char c = (char) 'C'
+
+ Assert.assertTrue(a instanceof Character)
+ Assert.assertTrue(b instanceof Character)
+ Assert.assertTrue(c instanceof Character)
+ }
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/DollarSlashyString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/DollarSlashyString.groovy
new file mode 100644
index 0000000000..db8ba68c8f
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/DollarSlashyString.groovy
@@ -0,0 +1,24 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Test
+
+class DollarSlashyString {
+
+ @Test
+ void 'dollar slashy string'() {
+ def name = "John"
+
+ def dollarSlashy = $/
+ Hello $name!,
+
+ I can show you $ sign or escaped dollar sign: $$
+ Both slashes works: \ or /, but we can still escape it: $/
+
+ We have to escape opening and closing delimiter:
+ - $$$/
+ - $/$$
+ /$
+
+ print(dollarSlashy)
+ }
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy
new file mode 100644
index 0000000000..a730244d0a
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/DoubleQuotedString.groovy
@@ -0,0 +1,67 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Assert
+import org.junit.Test
+
+class DoubleQuotedString {
+
+ @Test
+ void 'escape double quoted string'() {
+ def example = "Hello \"world\"!"
+
+ println(example)
+ }
+
+ @Test
+ void 'String ang GString'() {
+ def string = "example"
+ def stringWithExpression = "example${2}"
+
+ Assert.assertTrue(string instanceof String)
+ Assert.assertTrue(stringWithExpression instanceof GString)
+ Assert.assertTrue(stringWithExpression.toString() instanceof String)
+ }
+
+ @Test
+ void 'placeholder with variable'() {
+ def name = "John"
+ def helloName = "Hello $name!".toString()
+
+ Assert.assertEquals("Hello John!", helloName)
+ }
+
+ @Test
+ void 'placeholder with expression'() {
+ def result = "result is ${2 * 2}".toString()
+
+ Assert.assertEquals("result is 4", result)
+ }
+
+ @Test
+ void 'placeholder with dotted access'() {
+ def person = [name: 'John']
+
+ def myNameIs = "I'm $person.name, and you?".toString()
+
+ Assert.assertEquals("I'm John, and you?", myNameIs)
+ }
+
+ @Test
+ void 'placeholder with method call'() {
+ def name = 'John'
+
+ def result = "Uppercase name: ${name.toUpperCase()}".toString()
+
+ Assert.assertEquals("Uppercase name: JOHN", result)
+ }
+
+
+ @Test
+ void 'GString and String hashcode'() {
+ def string = "2+2 is 4"
+ def gstring = "2+2 is ${4}"
+
+ Assert.assertTrue(string.hashCode() != gstring.hashCode())
+ }
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy
new file mode 100644
index 0000000000..569991b788
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/SingleQuotedString.groovy
@@ -0,0 +1,15 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Assert
+import org.junit.Test
+
+class SingleQuotedString {
+
+ @Test
+ void 'single quoted string'() {
+ def example = 'Hello world'
+
+ Assert.assertEquals('Hello world!', 'Hello' + ' world!')
+ }
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/SlashyString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/SlashyString.groovy
new file mode 100644
index 0000000000..09ba35e17e
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/SlashyString.groovy
@@ -0,0 +1,31 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Assert
+import org.junit.Test
+
+class SlashyString {
+
+ @Test
+ void 'slashy string'() {
+ def pattern = /.*foobar.*\/hello.*/
+
+ Assert.assertTrue("I'm matching foobar /hello regexp pattern".matches(pattern))
+ }
+
+ void 'wont compile'() {
+// if ('' == //) {
+// println("I can't compile")
+// }
+ }
+
+ @Test
+ void 'interpolate and multiline'() {
+ def name = 'John'
+
+ def example = /
+ Hello $name
+ second line
+ /
+ }
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy
new file mode 100644
index 0000000000..e45f352285
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/Strings.groovy
@@ -0,0 +1,26 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Assert
+import org.junit.Test
+
+class Strings {
+
+ @Test
+ void 'string interpolation '() {
+ def name = "Kacper"
+
+ def result = "Hello ${name}!"
+
+ Assert.assertEquals("Hello Kacper!", result.toString())
+ }
+
+ @Test
+ void 'string concatenation'() {
+ def first = "first"
+ def second = "second"
+
+ def concatenation = first + second
+
+ Assert.assertEquals("firstsecond", concatenation)
+ }
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleDoubleQuotedString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleDoubleQuotedString.groovy
new file mode 100644
index 0000000000..cbbb1a4665
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleDoubleQuotedString.groovy
@@ -0,0 +1,19 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Test
+
+class TripleDoubleQuotedString {
+
+ @Test
+ void 'triple-quoted strings with interpolation'() {
+ def name = "John"
+
+ def multiLine = """
+ I'm $name.
+ "This is quotation"
+ """
+
+ println(multiLine)
+ }
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleSingleQuotedString.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleSingleQuotedString.groovy
new file mode 100644
index 0000000000..24d55b8a2a
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/stringtypes/TripleSingleQuotedString.groovy
@@ -0,0 +1,67 @@
+package groovy.com.baeldung.stringtypes
+
+import org.junit.Assert
+import org.junit.Test
+
+class TripleSingleQuotedString {
+
+ def 'formatted json'() {
+ def jsonContent = '''
+ {
+ "name": "John",
+ "age": 20,
+ "birthDate": null
+ }
+ '''
+ }
+
+ def 'triple single quoted'() {
+ def triple = '''im triple single quoted string'''
+ }
+
+ @Test
+ void 'triple single quoted with multiline string'() {
+ def triple = '''
+ firstline
+ secondline
+ '''
+
+ Assert.assertTrue(triple.startsWith("\n"))
+ }
+
+ @Test
+ void 'triple single quoted with multiline string with stripIndent() and removing newline characters'() {
+ def triple = '''\
+ firstline
+ secondline'''.stripIndent()
+
+ Assert.assertEquals("firstline\nsecondline", triple)
+ }
+
+ @Test
+ void 'triple single quoted with multiline string with last line with only whitespaces'() {
+ def triple = '''\
+ firstline
+ secondline\
+ '''.stripIndent()
+
+ println(triple)
+ }
+
+ @Test
+ void 'triple single quoted with multiline string with stripMargin(Character) and removing newline characters'() {
+ def triple = '''\
+ |firstline
+ |secondline'''.stripMargin()
+
+ println(triple)
+ }
+
+ @Test
+ void 'striple single quoted with special characters'() {
+ def specialCharacters = '''hello \'John\'. This is backslash - \\. \nSecond line starts here'''
+
+ println(specialCharacters)
+ }
+
+}
diff --git a/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy
new file mode 100644
index 0000000000..0c74a9be62
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy
@@ -0,0 +1,114 @@
+package com.baeldung.traits
+
+import spock.lang.Specification
+
+class TraitsUnitTest extends Specification {
+
+ Employee employee
+ Dog dog
+
+ void setup () {
+ employee = new Employee()
+ dog = new Dog()
+ }
+
+ def 'Should return msg string when using Employee.sayHello method provided by UserTrait' () {
+ when:
+ def msg = employee.sayHello()
+ then:
+ msg
+ msg instanceof String
+ assert msg == "Hello!"
+ }
+
+ def 'Should return displayMsg string when using Employee.showName method' () {
+ when:
+ def displayMsg = employee.showName()
+ then:
+ displayMsg
+ displayMsg instanceof String
+ assert displayMsg == "Hello, Bob!"
+ }
+
+ def 'Should return greetMsg string when using Employee.greet method' () {
+ when:
+ def greetMsg = employee.greet()
+ then:
+ greetMsg
+ greetMsg instanceof String
+ assert greetMsg == "Hello, from a private method!"
+ }
+
+ def 'Should return MissingMethodException when using Employee.greetingMessage method' () {
+ when:
+ def exception
+ try {
+ employee.greetingMessage()
+ }catch(Exception e) {
+ exception = e
+ }
+
+ then:
+ exception
+ exception instanceof groovy.lang.MissingMethodException
+ assert exception.message == "No signature of method: com.baeldung.traits.Employee.greetingMessage()"+
+ " is applicable for argument types: () values: []"
+ }
+
+ def 'Should return employee instance when using Employee.whoAmI method' () {
+ when:
+ def emp = employee.whoAmI()
+ then:
+ emp
+ emp instanceof Employee
+ assert emp.is(employee)
+ }
+
+ def 'Should display lastName when using Employee.showLastName method' () {
+ when:
+ def lastNameMsg = employee.showLastName()
+ then:
+ lastNameMsg
+ lastNameMsg instanceof String
+ assert lastNameMsg == "Hello, Marley!"
+ }
+
+ def 'Should be able to define properties of UserTrait in Employee instance' () {
+ when:
+ employee = new Employee(email: "a@e.com", address: "baeldung.com")
+ then:
+ employee
+ employee instanceof Employee
+ assert employee.email == "a@e.com"
+ assert employee.address == "baeldung.com"
+ }
+
+ def 'Should execute basicAbility method from SpeakingTrait and return msg string' () {
+ when:
+ def speakMsg = dog.basicAbility()
+ then:
+ speakMsg
+ speakMsg instanceof String
+ assert speakMsg == "Speaking!!"
+ }
+
+ def 'Should verify multiple inheritance with traits and execute overridden traits method' () {
+ when:
+ def walkSpeakMsg = dog.speakAndWalk()
+ println walkSpeakMsg
+ then:
+ walkSpeakMsg
+ walkSpeakMsg instanceof String
+ assert walkSpeakMsg == "Walk and speak!!"
+ }
+
+ def 'Should implement AnimalTrait at runtime and access basicBehavior method' () {
+ when:
+ def dogInstance = new Dog() as AnimalTrait
+ def basicBehaviorMsg = dogInstance.basicBehavior()
+ then:
+ basicBehaviorMsg
+ basicBehaviorMsg instanceof String
+ assert basicBehaviorMsg == "Animalistic!!"
+ }
+}
\ No newline at end of file
diff --git a/core-java-10/pom.xml b/core-java-10/pom.xml
index 9fcdd9a162..b15f8b5d63 100644
--- a/core-java-10/pom.xml
+++ b/core-java-10/pom.xml
@@ -3,9 +3,9 @@
4.0.0
com.baeldung
core-java-10
- jar
0.1.0-SNAPSHOT
core-java-10
+ jar
http://maven.apache.org
diff --git a/core-java-11/README.md b/core-java-11/README.md
index c8039f4bc5..3c8b94fa28 100644
--- a/core-java-11/README.md
+++ b/core-java-11/README.md
@@ -3,3 +3,4 @@
- [Java 11 Single File Source Code](https://www.baeldung.com/java-single-file-source-code)
- [Java 11 Local Variable Syntax for Lambda Parameters](https://www.baeldung.com/java-var-lambda-params)
- [Java 11 String API Additions](https://www.baeldung.com/java-11-string-api)
+- [Java 11 Nest Based Access Control](https://www.baeldung.com/java-nest-based-access-control)
diff --git a/core-java-11/pom.xml b/core-java-11/pom.xml
index 4dcab49867..a9776d8f3b 100644
--- a/core-java-11/pom.xml
+++ b/core-java-11/pom.xml
@@ -3,9 +3,9 @@
4.0.0
com.baeldung
core-java-11
- jar
0.1.0-SNAPSHOT
core-java-11
+ jar
http://maven.apache.org
diff --git a/core-java-11/src/main/java/com/baeldung/java11/httpclient/HttpClientExample.java b/core-java-11/src/main/java/com/baeldung/java11/httpclient/HttpClientExample.java
new file mode 100644
index 0000000000..fb4abd3bb6
--- /dev/null
+++ b/core-java-11/src/main/java/com/baeldung/java11/httpclient/HttpClientExample.java
@@ -0,0 +1,132 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.baeldung.java11.httpclient;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpClient.Version;
+import java.net.http.HttpRequest;
+import java.net.http.HttpRequest.BodyPublishers;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.net.http.HttpResponse.PushPromiseHandler;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class HttpClientExample {
+
+ public static void main(String[] args) throws Exception {
+ httpGetRequest();
+ httpPostRequest();
+ asynchronousGetRequest();
+ asynchronousMultipleRequests();
+ pushRequest();
+ }
+
+ public static void httpGetRequest() throws URISyntaxException, IOException, InterruptedException {
+ HttpClient client = HttpClient.newHttpClient();
+ HttpRequest request = HttpRequest.newBuilder()
+ .version(HttpClient.Version.HTTP_2)
+ .uri(URI.create("http://jsonplaceholder.typicode.com/posts/1"))
+ .headers("Accept-Enconding", "gzip, deflate")
+ .build();
+ HttpResponse response = client.send(request, BodyHandlers.ofString());
+
+ String responseBody = response.body();
+ int responseStatusCode = response.statusCode();
+
+ System.out.println("httpGetRequest: " + responseBody);
+ System.out.println("httpGetRequest status code: " + responseStatusCode);
+ }
+
+ public static void httpPostRequest() throws URISyntaxException, IOException, InterruptedException {
+ HttpClient client = HttpClient.newBuilder()
+ .version(HttpClient.Version.HTTP_2)
+ .build();
+ HttpRequest request = HttpRequest.newBuilder(new URI("http://jsonplaceholder.typicode.com/posts"))
+ .version(HttpClient.Version.HTTP_2)
+ .POST(BodyPublishers.ofString("Sample Post Request"))
+ .build();
+ HttpResponse response = client.send(request, BodyHandlers.ofString());
+ String responseBody = response.body();
+ System.out.println("httpPostRequest : " + responseBody);
+ }
+
+ public static void asynchronousGetRequest() throws URISyntaxException {
+ HttpClient client = HttpClient.newHttpClient();
+ URI httpURI = new URI("http://jsonplaceholder.typicode.com/posts/1");
+ HttpRequest request = HttpRequest.newBuilder(httpURI)
+ .version(HttpClient.Version.HTTP_2)
+ .build();
+ CompletableFuture futureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
+ .thenAccept(resp -> {
+ System.out.println("Got pushed response " + resp.uri());
+ System.out.println("Response statuscode: " + resp.statusCode());
+ System.out.println("Response body: " + resp.body());
+ });
+ System.out.println("futureResponse" + futureResponse);
+
+ }
+
+ public static void asynchronousMultipleRequests() throws URISyntaxException {
+ HttpClient client = HttpClient.newHttpClient();
+ List uris = Arrays.asList(new URI("http://jsonplaceholder.typicode.com/posts/1"), new URI("http://jsonplaceholder.typicode.com/posts/2"));
+ List requests = uris.stream()
+ .map(HttpRequest::newBuilder)
+ .map(reqBuilder -> reqBuilder.build())
+ .collect(Collectors.toList());
+ System.out.println("Got pushed response1 " + requests);
+ CompletableFuture.allOf(requests.stream()
+ .map(request -> client.sendAsync(request, BodyHandlers.ofString()))
+ .toArray(CompletableFuture>[]::new))
+ .thenAccept(System.out::println)
+ .join();
+ }
+
+ public static void pushRequest() throws URISyntaxException, InterruptedException {
+ System.out.println("Running HTTP/2 Server Push example...");
+
+ HttpClient httpClient = HttpClient.newBuilder()
+ .version(Version.HTTP_2)
+ .build();
+
+ HttpRequest pageRequest = HttpRequest.newBuilder()
+ .uri(URI.create("https://http2.golang.org/serverpush"))
+ .build();
+
+ // Interface HttpResponse.PushPromiseHandler
+ // void applyPushPromise(HttpRequest initiatingRequest, HttpRequest pushPromiseRequest, Function,CompletableFuture>> acceptor)
+ httpClient.sendAsync(pageRequest, BodyHandlers.ofString(), pushPromiseHandler())
+ .thenAccept(pageResponse -> {
+ System.out.println("Page response status code: " + pageResponse.statusCode());
+ System.out.println("Page response headers: " + pageResponse.headers());
+ String responseBody = pageResponse.body();
+ System.out.println(responseBody);
+ }).join();
+
+ Thread.sleep(1000); // waiting for full response
+ }
+
+ private static PushPromiseHandler pushPromiseHandler() {
+ return (HttpRequest initiatingRequest,
+ HttpRequest pushPromiseRequest,
+ Function,
+ CompletableFuture>> acceptor) -> {
+ acceptor.apply(BodyHandlers.ofString())
+ .thenAccept(resp -> {
+ System.out.println(" Pushed response: " + resp.uri() + ", headers: " + resp.headers());
+ });
+ System.out.println("Promise request: " + pushPromiseRequest.uri());
+ System.out.println("Promise request: " + pushPromiseRequest.headers());
+ };
+ }
+
+}
diff --git a/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientTest.java b/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientTest.java
new file mode 100644
index 0000000000..bade666636
--- /dev/null
+++ b/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientTest.java
@@ -0,0 +1,240 @@
+package com.baeldung.java11.httpclient.test;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.net.Authenticator;
+import java.net.CookieManager;
+import java.net.CookiePolicy;
+import java.net.HttpURLConnection;
+import java.net.PasswordAuthentication;
+import java.net.ProxySelector;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.Test;
+
+public class HttpClientTest {
+
+ @Test
+ public void shouldReturnSampleDataContentWhenConnectViaSystemProxy() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .headers("Content-Type", "text/plain;charset=UTF-8")
+ .POST(HttpRequest.BodyPublishers.ofString("Sample body"))
+ .build();
+
+
+ HttpResponse response = HttpClient.newBuilder()
+ .proxy(ProxySelector.getDefault())
+ .build()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.body(), containsString("Sample body"));
+ }
+
+ @Test
+ public void shouldNotFollowRedirectWhenSetToDefaultNever() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("http://stackoverflow.com"))
+ .version(HttpClient.Version.HTTP_1_1)
+ .GET()
+ .build();
+ HttpResponse response = HttpClient.newBuilder()
+ .build()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_MOVED_PERM));
+ assertThat(response.body(), containsString("https://stackoverflow.com/"));
+ }
+
+ @Test
+ public void shouldFollowRedirectWhenSetToAlways() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("http://stackoverflow.com"))
+ .version(HttpClient.Version.HTTP_1_1)
+ .GET()
+ .build();
+ HttpResponse response = HttpClient.newBuilder()
+ .followRedirects(HttpClient.Redirect.ALWAYS)
+ .build()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.request()
+ .uri()
+ .toString(), equalTo("https://stackoverflow.com/"));
+ }
+
+ @Test
+ public void shouldReturnOKStatusForAuthenticatedAccess() throws URISyntaxException, IOException, InterruptedException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/basic-auth"))
+ .GET()
+ .build();
+ HttpResponse response = HttpClient.newBuilder()
+ .authenticator(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication("postman", "password".toCharArray());
+ }
+ })
+ .build()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldSendRequestAsync() throws URISyntaxException, InterruptedException, ExecutionException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .headers("Content-Type", "text/plain;charset=UTF-8")
+ .POST(HttpRequest.BodyPublishers.ofString("Sample body"))
+ .build();
+ CompletableFuture> response = HttpClient.newBuilder()
+ .build()
+ .sendAsync(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.get()
+ .statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldUseJustTwoThreadWhenProcessingSendAsyncRequest() throws URISyntaxException, InterruptedException, ExecutionException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .GET()
+ .build();
+
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+
+ CompletableFuture> response1 = HttpClient.newBuilder()
+ .executor(executorService)
+ .build()
+ .sendAsync(request, HttpResponse.BodyHandlers.ofString());
+
+ CompletableFuture> response2 = HttpClient.newBuilder()
+ .executor(executorService)
+ .build()
+ .sendAsync(request, HttpResponse.BodyHandlers.ofString());
+
+ CompletableFuture> response3 = HttpClient.newBuilder()
+ .executor(executorService)
+ .build()
+ .sendAsync(request, HttpResponse.BodyHandlers.ofString());
+
+ CompletableFuture.allOf(response1, response2, response3)
+ .join();
+
+ assertThat(response1.get()
+ .statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response2.get()
+ .statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response3.get()
+ .statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldNotStoreCookieWhenPolicyAcceptNone() throws URISyntaxException, IOException, InterruptedException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .GET()
+ .build();
+
+ HttpClient httpClient = HttpClient.newBuilder()
+ .cookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_NONE))
+ .build();
+
+ httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertTrue(httpClient.cookieHandler()
+ .isPresent());
+ }
+
+ @Test
+ public void shouldStoreCookieWhenPolicyAcceptAll() throws URISyntaxException, IOException, InterruptedException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .GET()
+ .build();
+
+ HttpClient httpClient = HttpClient.newBuilder()
+ .cookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ALL))
+ .build();
+
+ httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertTrue(httpClient.cookieHandler()
+ .isPresent());
+ }
+
+ @Test
+ public void shouldProcessMultipleRequestViaStream() throws URISyntaxException, ExecutionException, InterruptedException {
+ List targets = Arrays.asList(new URI("https://postman-echo.com/get?foo1=bar1"), new URI("https://postman-echo.com/get?foo2=bar2"));
+
+ HttpClient client = HttpClient.newHttpClient();
+
+ List> futures = targets.stream()
+ .map(target -> client.sendAsync(HttpRequest.newBuilder(target)
+ .GET()
+ .build(), HttpResponse.BodyHandlers.ofString())
+ .thenApply(response -> response.body()))
+ .collect(Collectors.toList());
+
+ CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
+ .join();
+
+ if (futures.get(0)
+ .get()
+ .contains("foo1")) {
+ assertThat(futures.get(0)
+ .get(), containsString("bar1"));
+ assertThat(futures.get(1)
+ .get(), containsString("bar2"));
+ } else {
+ assertThat(futures.get(1)
+ .get(), containsString("bar2"));
+ assertThat(futures.get(1)
+ .get(), containsString("bar1"));
+ }
+
+ }
+
+ @Test
+ public void completeExceptionallyExample() {
+ CompletableFuture cf = CompletableFuture.completedFuture("message").thenApplyAsync(String::toUpperCase,
+ CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS));
+ CompletableFuture exceptionHandler = cf.handle((s, th) -> { return (th != null) ? "message upon cancel" : ""; });
+ cf.completeExceptionally(new RuntimeException("completed exceptionally"));
+ assertTrue("Was not completed exceptionally", cf.isCompletedExceptionally());
+ try {
+ cf.join();
+ fail("Should have thrown an exception");
+ } catch (CompletionException ex) { // just for testing
+ assertEquals("completed exceptionally", ex.getCause().getMessage());
+ }
+
+ assertEquals("message upon cancel", exceptionHandler.join());
+ }
+
+}
diff --git a/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestTest.java b/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestTest.java
new file mode 100644
index 0000000000..7d138bd8d5
--- /dev/null
+++ b/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestTest.java
@@ -0,0 +1,168 @@
+package com.baeldung.java11.httpclient.test;
+
+import static java.time.temporal.ChronoUnit.SECONDS;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.file.Paths;
+import java.security.NoSuchAlgorithmException;
+import java.time.Duration;
+
+import org.junit.Test;
+
+public class HttpRequestTest {
+
+ @Test
+ public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .GET()
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldUseHttp2WhenWebsiteUsesHttp2() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://stackoverflow.com"))
+ .version(HttpClient.Version.HTTP_2)
+ .GET()
+ .build();
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.version(), equalTo(HttpClient.Version.HTTP_2));
+ }
+
+ @Test
+ public void shouldFallbackToHttp1_1WhenWebsiteDoesNotUseHttp2() throws IOException, InterruptedException, URISyntaxException, NoSuchAlgorithmException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .version(HttpClient.Version.HTTP_2)
+ .GET()
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.version(), equalTo(HttpClient.Version.HTTP_1_1));
+ }
+
+ @Test
+ public void shouldReturnStatusOKWhenSendGetRequestWithDummyHeaders() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .headers("key1", "value1", "key2", "value2")
+ .GET()
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldReturnStatusOKWhenSendGetRequestTimeoutSet() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .timeout(Duration.of(10, SECONDS))
+ .GET()
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldReturnNoContentWhenPostWithNoBody() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .POST(HttpRequest.BodyPublishers.noBody())
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ }
+
+ @Test
+ public void shouldReturnSampleDataContentWhenPostWithBodyText() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .headers("Content-Type", "text/plain;charset=UTF-8")
+ .POST(HttpRequest.BodyPublishers.ofString("Sample request body"))
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.body(), containsString("Sample request body"));
+ }
+
+ @Test
+ public void shouldReturnSampleDataContentWhenPostWithInputStream() throws IOException, InterruptedException, URISyntaxException {
+ byte[] sampleData = "Sample request body".getBytes();
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .headers("Content-Type", "text/plain;charset=UTF-8")
+ .POST(HttpRequest.BodyPublishers.ofInputStream(() -> new ByteArrayInputStream(sampleData)))
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.body(), containsString("Sample request body"));
+ }
+
+ @Test
+ public void shouldReturnSampleDataContentWhenPostWithByteArrayProcessorStream() throws IOException, InterruptedException, URISyntaxException {
+ byte[] sampleData = "Sample request body".getBytes();
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .headers("Content-Type", "text/plain;charset=UTF-8")
+ .POST(HttpRequest.BodyPublishers.ofByteArray(sampleData))
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.body(), containsString("Sample request body"));
+ }
+
+ @Test
+ public void shouldReturnSampleDataContentWhenPostWithFileProcessorStream() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/post"))
+ .headers("Content-Type", "text/plain;charset=UTF-8")
+ .POST(HttpRequest.BodyPublishers.ofFile(Paths.get("src/test/resources/sample.txt")))
+ .build();
+
+ HttpResponse response = HttpClient.newHttpClient()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertThat(response.body(), containsString("Sample file content"));
+ }
+
+}
diff --git a/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseTest.java b/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseTest.java
new file mode 100644
index 0000000000..78d86fbf4e
--- /dev/null
+++ b/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpResponseTest.java
@@ -0,0 +1,54 @@
+package com.baeldung.java11.httpclient.test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+
+import org.junit.Test;
+
+public class HttpResponseTest {
+
+ @Test
+ public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("https://postman-echo.com/get"))
+ .version(HttpClient.Version.HTTP_2)
+ .GET()
+ .build();
+
+ HttpResponse response = HttpClient.newBuilder()
+ .followRedirects(HttpClient.Redirect.NORMAL)
+ .build()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
+ assertNotNull(response.body());
+ }
+
+ @Test
+ public void shouldResponseURIDifferentThanRequestUIRWhenRedirect() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(new URI("http://stackoverflow.com"))
+ .version(HttpClient.Version.HTTP_2)
+ .GET()
+ .build();
+ HttpResponse response = HttpClient.newBuilder()
+ .followRedirects(HttpClient.Redirect.NORMAL)
+ .build()
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ assertThat(request.uri()
+ .toString(), equalTo("http://stackoverflow.com"));
+ assertThat(response.uri()
+ .toString(), equalTo("https://stackoverflow.com/"));
+ }
+
+}
diff --git a/core-java-8/pom.xml b/core-java-8/pom.xml
index 112e8b764d..b4519a8161 100644
--- a/core-java-8/pom.xml
+++ b/core-java-8/pom.xml
@@ -4,8 +4,8 @@
com.baeldung
core-java-8
0.1.0-SNAPSHOT
- jar
core-java-8
+ jar
com.baeldung
diff --git a/core-java-8/src/main/java/com/baeldung/customannotations/Init.java b/core-java-8/src/main/java/com/baeldung/customannotations/Init.java
new file mode 100644
index 0000000000..265e7ba1d6
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/customannotations/Init.java
@@ -0,0 +1,13 @@
+package com.baeldung.customannotations;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target(METHOD)
+public @interface Init {
+
+}
diff --git a/core-java-8/src/main/java/com/baeldung/customannotations/JsonElement.java b/core-java-8/src/main/java/com/baeldung/customannotations/JsonElement.java
new file mode 100644
index 0000000000..e41a5b1e30
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/customannotations/JsonElement.java
@@ -0,0 +1,13 @@
+package com.baeldung.customannotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target({ FIELD })
+public @interface JsonElement {
+ public String key() default "";
+}
diff --git a/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializable.java b/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializable.java
new file mode 100644
index 0000000000..48eeb09a1b
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializable.java
@@ -0,0 +1,13 @@
+package com.baeldung.customannotations;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(RUNTIME)
+@Target(TYPE)
+public @interface JsonSerializable {
+
+}
diff --git a/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializationException.java b/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializationException.java
new file mode 100644
index 0000000000..f2c29855ac
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/customannotations/JsonSerializationException.java
@@ -0,0 +1,10 @@
+package com.baeldung.customannotations;
+
+public class JsonSerializationException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public JsonSerializationException(String message) {
+ super(message);
+ }
+}
diff --git a/core-java-8/src/main/java/com/baeldung/customannotations/ObjectToJsonConverter.java b/core-java-8/src/main/java/com/baeldung/customannotations/ObjectToJsonConverter.java
new file mode 100644
index 0000000000..dd126be8ed
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/customannotations/ObjectToJsonConverter.java
@@ -0,0 +1,67 @@
+package com.baeldung.customannotations;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class ObjectToJsonConverter {
+ public String convertToJson(Object object) throws JsonSerializationException {
+ try {
+
+ checkIfSerializable(object);
+ initializeObject(object);
+ return getJsonString(object);
+
+ } catch (Exception e) {
+ throw new JsonSerializationException(e.getMessage());
+ }
+ }
+
+ private void checkIfSerializable(Object object) {
+ if (Objects.isNull(object)) {
+ throw new JsonSerializationException("Can't serialize a null object");
+ }
+
+ Class> clazz = object.getClass();
+ if (!clazz.isAnnotationPresent(JsonSerializable.class)) {
+ throw new JsonSerializationException("The class " + clazz.getSimpleName() + " is not annotated with JsonSerializable");
+ }
+ }
+
+ private void initializeObject(Object object) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ Class> clazz = object.getClass();
+ for (Method method : clazz.getDeclaredMethods()) {
+ if (method.isAnnotationPresent(Init.class)) {
+ method.setAccessible(true);
+ method.invoke(object);
+ }
+ }
+ }
+
+ private String getJsonString(Object object) throws IllegalArgumentException, IllegalAccessException {
+ Class> clazz = object.getClass();
+ Map jsonElementsMap = new HashMap<>();
+ for (Field field : clazz.getDeclaredFields()) {
+ field.setAccessible(true);
+ if (field.isAnnotationPresent(JsonElement.class)) {
+ jsonElementsMap.put(getKey(field), (String) field.get(object));
+ }
+ }
+
+ String jsonString = jsonElementsMap.entrySet()
+ .stream()
+ .map(entry -> "\"" + entry.getKey() + "\":\"" + entry.getValue() + "\"")
+ .collect(Collectors.joining(","));
+ return "{" + jsonString + "}";
+ }
+
+ private String getKey(Field field) {
+ String value = field.getAnnotation(JsonElement.class)
+ .key();
+ return value.isEmpty() ? field.getName() : value;
+ }
+}
diff --git a/core-java-8/src/main/java/com/baeldung/customannotations/Person.java b/core-java-8/src/main/java/com/baeldung/customannotations/Person.java
new file mode 100644
index 0000000000..5db1a7f279
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/customannotations/Person.java
@@ -0,0 +1,66 @@
+package com.baeldung.customannotations;
+
+@JsonSerializable
+public class Person {
+ @JsonElement
+ private String firstName;
+ @JsonElement
+ private String lastName;
+ @JsonElement(key = "personAge")
+ private String age;
+
+ private String address;
+
+ public Person(String firstName, String lastName) {
+ super();
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+
+ public Person(String firstName, String lastName, String age) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.age = age;
+ }
+
+ @Init
+ private void initNames() {
+ this.firstName = this.firstName.substring(0, 1)
+ .toUpperCase() + this.firstName.substring(1);
+ this.lastName = this.lastName.substring(0, 1)
+ .toUpperCase() + this.lastName.substring(1);
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getAge() {
+ return age;
+ }
+
+ public void setAge(String age) {
+ this.age = age;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+}
diff --git a/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java b/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java
index bad1c32e4a..e742635758 100644
--- a/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java
+++ b/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsUnitTest.java
@@ -39,6 +39,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class Java8CollectorsUnitTest {
private final List givenList = Arrays.asList("a", "bb", "ccc", "dd");
+ private final List listWithDuplicates = Arrays.asList("a", "bb", "c", "d", "bb");
@Test
public void whenCollectingToList_shouldCollectToList() throws Exception {
@@ -48,12 +49,19 @@ public class Java8CollectorsUnitTest {
}
@Test
- public void whenCollectingToList_shouldCollectToSet() throws Exception {
+ public void whenCollectingToSet_shouldCollectToSet() throws Exception {
final Set result = givenList.stream().collect(toSet());
assertThat(result).containsAll(givenList);
}
+ @Test
+ public void givenContainsDuplicateElements_whenCollectingToSet_shouldAddDuplicateElementsOnlyOnce() throws Exception {
+ final Set result = listWithDuplicates.stream().collect(toSet());
+
+ assertThat(result).hasSize(4);
+ }
+
@Test
public void whenCollectingToCollection_shouldCollectToCollection() throws Exception {
final List result = givenList.stream().collect(toCollection(LinkedList::new));
@@ -77,10 +85,23 @@ public class Java8CollectorsUnitTest {
}
@Test
- public void whenCollectingToMap_shouldCollectToMapMerging() throws Exception {
- final Map result = givenList.stream().collect(toMap(Function.identity(), String::length, (i1, i2) -> i1));
+ public void whenCollectingToMapwWithDuplicates_shouldCollectToMapMergingTheIdenticalItems() throws Exception {
+ final Map result = listWithDuplicates.stream().collect(
+ toMap(
+ Function.identity(),
+ String::length,
+ (item, identicalItem) -> item
+ )
+ );
- assertThat(result).containsEntry("a", 1).containsEntry("bb", 2).containsEntry("ccc", 3).containsEntry("dd", 2);
+ assertThat(result).containsEntry("a", 1).containsEntry("bb", 2).containsEntry("c", 1).containsEntry("d", 1);
+ }
+
+ @Test
+ public void givenContainsDuplicateElements_whenCollectingToMap_shouldThrowException() throws Exception {
+ assertThatThrownBy(() -> {
+ listWithDuplicates.stream().collect(toMap(Function.identity(), String::length));
+ }).isInstanceOf(IllegalStateException.class);
}
@Test
diff --git a/core-java-8/src/test/java/com/baeldung/customannotations/JsonSerializerUnitTest.java b/core-java-8/src/test/java/com/baeldung/customannotations/JsonSerializerUnitTest.java
new file mode 100644
index 0000000000..f24b37aef7
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/customannotations/JsonSerializerUnitTest.java
@@ -0,0 +1,26 @@
+package com.baeldung.customannotations;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+public class JsonSerializerUnitTest {
+
+ @Test
+ public void givenObjectNotSerializedThenExceptionThrown() throws JsonSerializationException {
+ Object object = new Object();
+ ObjectToJsonConverter serializer = new ObjectToJsonConverter();
+ assertThrows(JsonSerializationException.class, () -> {
+ serializer.convertToJson(object);
+ });
+ }
+
+ @Test
+ public void givenObjectSerializedThenTrueReturned() throws JsonSerializationException {
+ Person person = new Person("soufiane", "cheouati", "34");
+ ObjectToJsonConverter serializer = new ObjectToJsonConverter();
+ String jsonString = serializer.convertToJson(person);
+ assertEquals("{\"personAge\":\"34\",\"firstName\":\"Soufiane\",\"lastName\":\"Cheouati\"}", jsonString);
+ }
+}
diff --git a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java
similarity index 89%
rename from core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java
rename to core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java
index ede0ef9f70..835815aecd 100644
--- a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java
+++ b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java
@@ -5,22 +5,21 @@ import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
+import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
-public class MethodReferenceExamples {
+public class MethodReferenceUnitTest {
private static void doNothingAtAll(Object... o) {
}
;
-
+
@Test
public void referenceToStaticMethod() {
List messages = Arrays.asList("Hello", "Baeldung", "readers!");
- messages.forEach((word) -> {
- System.out.println(word);
- });
- messages.forEach(System.out::println);
+ messages.forEach(word -> StringUtils.capitalize(word));
+ messages.forEach(StringUtils::capitalize);
}
@Test
@@ -63,7 +62,7 @@ public class MethodReferenceExamples {
@Test
public void limitationsAndAdditionalExamples() {
createBicyclesList().forEach(b -> System.out.printf("Bike brand is '%s' and frame size is '%d'%n", b.getBrand(), b.getFrameSize()));
- createBicyclesList().forEach((o) -> MethodReferenceExamples.doNothingAtAll(o));
+ createBicyclesList().forEach((o) -> MethodReferenceUnitTest.doNothingAtAll(o));
}
private List createBicyclesList() {
diff --git a/core-java-9/README.md b/core-java-9/README.md
index c96267dc95..d9586ba684 100644
--- a/core-java-9/README.md
+++ b/core-java-9/README.md
@@ -26,3 +26,4 @@
- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
- [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api)
- [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api)
+- [Immutable Set in Java](https://www.baeldung.com/java-immutable-set)
diff --git a/core-java-9/compile-aot.sh b/core-java-9/compile-aot.sh
new file mode 100755
index 0000000000..c3a39b0196
--- /dev/null
+++ b/core-java-9/compile-aot.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+cd src/main/java
+javac com/baeldung/java9/aot/JaotCompilation.java
+jaotc --output jaotCompilation.so com/baeldung/java9/aot/JaotCompilation.class
+
diff --git a/core-java-9/run-aot.sh b/core-java-9/run-aot.sh
new file mode 100755
index 0000000000..89fc616469
--- /dev/null
+++ b/core-java-9/run-aot.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+cd src/main/java
+java -XX:AOTLibrary=./jaotCompilation.so com/baeldung/java9/aot/JaotCompilation
\ No newline at end of file
diff --git a/core-java-9/src/main/java/com/baeldung/java9/aot/JaotCompilation.java b/core-java-9/src/main/java/com/baeldung/java9/aot/JaotCompilation.java
new file mode 100644
index 0000000000..4d8a018d6b
--- /dev/null
+++ b/core-java-9/src/main/java/com/baeldung/java9/aot/JaotCompilation.java
@@ -0,0 +1,12 @@
+package com.baeldung.java9.aot;
+
+public class JaotCompilation {
+
+ public static void main(String[] argv) {
+ System.out.println(message());
+ }
+
+ public static String message() {
+ return "The JAOT compiler says 'Hello'";
+ }
+}
\ No newline at end of file
diff --git a/core-java-arrays/README.md b/core-java-arrays/README.md
index 400dd7793c..ed8221ebe4 100644
--- a/core-java-arrays/README.md
+++ b/core-java-arrays/README.md
@@ -14,3 +14,4 @@
- [Array Operations in Java](http://www.baeldung.com/java-common-array-operations)
- [Intersection Between two Integer Arrays](https://www.baeldung.com/java-array-intersection)
- [Sorting Arrays in Java](https://www.baeldung.com/java-sorting-arrays)
+- [Convert a Float to a Byte Array in Java](https://www.baeldung.com/java-convert-float-to-byte-array)
diff --git a/core-java-arrays/pom.xml b/core-java-arrays/pom.xml
index d2d0453e87..39ac764b27 100644
--- a/core-java-arrays/pom.xml
+++ b/core-java-arrays/pom.xml
@@ -4,8 +4,8 @@
com.baeldung
core-java-arrays
0.1.0-SNAPSHOT
- jar
core-java-arrays
+ jar
com.baeldung
diff --git a/core-java-collections-list/pom.xml b/core-java-collections-list/pom.xml
index a7e711088a..737be8ee34 100644
--- a/core-java-collections-list/pom.xml
+++ b/core-java-collections-list/pom.xml
@@ -3,8 +3,8 @@
4.0.0
core-java-collections-list
0.1.0-SNAPSHOT
- jar
core-java-collections-list
+ jar
com.baeldung
@@ -40,17 +40,17 @@
net.sf.trove4j
trove4j
- 3.0.2
+ ${trove4j.version}
it.unimi.dsi
fastutil
- 8.1.0
+ ${fastutil.version}
colt
colt
- 1.2.0
+ ${colt.version}
@@ -60,5 +60,8 @@
1.7.0
3.11.1
1.16.12
+ 3.0.2
+ 8.1.0
+ 1.2.0