diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy new file mode 100644 index 0000000000..eb4d1f7f87 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy @@ -0,0 +1,3 @@ +package com.baeldung + +class Car implements VehicleTrait {} \ 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 index 3f1e694f17..0d395bffcd 100644 --- a/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy +++ b/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy @@ -22,7 +22,7 @@ trait UserTrait implements Human { msg } - def whoAmI() { + def self() { return this } diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy new file mode 100644 index 0000000000..f5ae8fab30 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy @@ -0,0 +1,9 @@ +package com.baeldung + +trait VehicleTrait extends WheelTrait { + + String showWheels() { + return "Num of Wheels $noOfWheels" + } + +} \ No newline at end of file diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy new file mode 100644 index 0000000000..364d5b883e --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy @@ -0,0 +1,7 @@ +package com.baeldung + +trait WheelTrait { + + int noOfWheels + +} \ No newline at end of file diff --git a/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy index 0c74a9be62..85130e8f07 100644 --- a/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy +++ b/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy @@ -57,7 +57,7 @@ class TraitsUnitTest extends Specification { def 'Should return employee instance when using Employee.whoAmI method' () { when: - def emp = employee.whoAmI() + def emp = employee.self() then: emp emp instanceof Employee diff --git a/core-java-collections-list/README.md b/core-java-collections-list/README.md index d1112047ba..3a4a7c69e8 100644 --- a/core-java-collections-list/README.md +++ b/core-java-collections-list/README.md @@ -27,3 +27,4 @@ - [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections) - [Intersection of Two Lists in Java](https://www.baeldung.com/java-lists-intersection) - [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist) +- [Determine If All Elements Are the Same in a Java List](https://www.baeldung.com/java-list-all-equal) diff --git a/gson/src/test/java/org/baeldung/gson/conversion/JsonObjectConversionsUnitTest.java b/gson/src/test/java/org/baeldung/gson/conversion/JsonObjectConversionsUnitTest.java new file mode 100644 index 0000000000..847ec1b85d --- /dev/null +++ b/gson/src/test/java/org/baeldung/gson/conversion/JsonObjectConversionsUnitTest.java @@ -0,0 +1,33 @@ +package org.baeldung.gson.conversion; + +import com.google.gson.*; +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +public class JsonObjectConversionsUnitTest { + + @Test + void whenUsingJsonParser_thenConvertToJsonObject() throws Exception { + // Example 1: Using JsonParser + String json = "{ \"name\": \"Baeldung\", \"java\": true }"; + + JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject(); + + Assert.assertTrue(jsonObject.isJsonObject()); + Assert.assertTrue(jsonObject.get("name").getAsString().equals("Baeldung")); + Assert.assertTrue(jsonObject.get("java").getAsBoolean() == true); + } + + @Test + void whenUsingGsonInstanceFromJson_thenConvertToJsonObject() throws Exception { + // Example 2: Using fromJson + String json = "{ \"name\": \"Baeldung\", \"java\": true }"; + + JsonObject convertedObject = new Gson().fromJson(json, JsonObject.class); + + Assert.assertTrue(convertedObject.isJsonObject()); + Assert.assertTrue(convertedObject.get("name").getAsString().equals("Baeldung")); + Assert.assertTrue(convertedObject.get("java").getAsBoolean() == true); + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java b/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java index 19e7d4c53c..985851f456 100644 --- a/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java @@ -1,16 +1,9 @@ package com.baeldung.jackson.dtos; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; - public class Address { - @JacksonXmlProperty(localName = "street_number") String streetNumber; - - @JacksonXmlProperty(localName = "street_name") String streetName; - - @JacksonXmlProperty(localName = "city") String city; public String getStreetNumber() { diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java b/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java index 7891595cc6..13093cdcad 100644 --- a/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java @@ -3,16 +3,13 @@ package com.baeldung.jackson.dtos; import java.util.ArrayList; import java.util.List; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @JacksonXmlRootElement(localName = "person") public final class Person { private String firstName; private String lastName; - @JacksonXmlElementWrapper(useWrapping = false) private List phoneNumbers = new ArrayList<>(); - @JacksonXmlElementWrapper(localName = "addresses") private List
address = new ArrayList<>(); public List
getAddress() { @@ -38,6 +35,7 @@ public final class Person { public void setLastName(String lastName) { this.lastName = lastName; } + public List getPhoneNumbers() { return phoneNumbers; } @@ -46,6 +44,4 @@ public final class Person { this.phoneNumbers = phoneNumbers; } - - } \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java index 039edd45bc..1d430e9758 100644 --- a/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java @@ -2,8 +2,10 @@ package com.baeldung.jackson.xml; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -56,17 +58,14 @@ public class XMLSerializeDeserializeUnitTest { @Test public void whenJavaGotFromXmlStrWithCapitalElem_thenCorrect() throws IOException { XmlMapper xmlMapper = new XmlMapper(); - SimpleBeanForCapitalizedFields value = xmlMapper. - readValue("12", - SimpleBeanForCapitalizedFields.class); + SimpleBeanForCapitalizedFields value = xmlMapper.readValue("12", SimpleBeanForCapitalizedFields.class); assertTrue(value.getX() == 1 && value.getY() == 2); } @Test public void whenJavaSerializedToXmlFileWithCapitalizedField_thenCorrect() throws IOException { XmlMapper xmlMapper = new XmlMapper(); - xmlMapper.writeValue(new File("target/simple_bean_capitalized.xml"), - new SimpleBeanForCapitalizedFields()); + xmlMapper.writeValue(new File("target/simple_bean_capitalized.xml"), new SimpleBeanForCapitalizedFields()); File file = new File("target/simple_bean_capitalized.xml"); assertNotNull(file); } @@ -74,7 +73,9 @@ public class XMLSerializeDeserializeUnitTest { @Test public void whenJavaDeserializedFromXmlFile_thenCorrect() throws IOException { XmlMapper xmlMapper = new XmlMapper(); - Person value = xmlMapper.readValue(new File("src/test/resources/person.xml"), Person.class); + + String xml = "RohanDaye99110347319911033478
1Name1City1
2Name2City2
"; + Person value = xmlMapper.readValue(xml, Person.class); assertTrue(value.getAddress() .get(0) @@ -90,33 +91,38 @@ public class XMLSerializeDeserializeUnitTest { public void whenJavaSerializedToXmlFile_thenSuccess() throws IOException { XmlMapper xmlMapper = new XmlMapper(); + String expectedXml = "RohanDaye99110347319911033478
1Name1City1
2Name2City2
"; + Person person = new Person(); person.setFirstName("Rohan"); person.setLastName("Daye"); List ph = new ArrayList<>(); - ph.add("9911778981"); - ph.add("9991111111"); + ph.add("9911034731"); + ph.add("9911033478"); person.setPhoneNumbers(ph); List
addresses = new ArrayList<>(); - + Address address1 = new Address(); address1.setStreetNumber("1"); - address1.setStreetName("streetname1"); - address1.setCity("city1"); - + address1.setStreetName("Name1"); + address1.setCity("City1"); + Address address2 = new Address(); address2.setStreetNumber("2"); - address2.setStreetName("streetname2"); - address2.setCity("city2"); - + address2.setStreetName("Name2"); + address2.setCity("City2"); + addresses.add(address1); addresses.add(address2); + person.setAddress(addresses); - xmlMapper.writeValue(new File("src/test/resources/PersonGenerated.xml"), person); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + xmlMapper.writeValue(byteArrayOutputStream, person); + assertEquals(expectedXml, byteArrayOutputStream.toString()); } private static String inputStreamToString(InputStream is) throws IOException { diff --git a/jackson/src/test/resources/PersonGenerated.xml b/jackson/src/test/resources/PersonGenerated.xml deleted file mode 100644 index 6ebadd971a..0000000000 --- a/jackson/src/test/resources/PersonGenerated.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - 9911778981 - 9991111111 - -
- 1 - streetname1 - city1 -
-
- 2 - streetname2 - city2 -
-
-
\ No newline at end of file diff --git a/jackson/src/test/resources/person.xml b/jackson/src/test/resources/person.xml deleted file mode 100644 index 39a6e859c4..0000000000 --- a/jackson/src/test/resources/person.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Rohan - Daye - 9911034731 - 9911033478 - -
- 1 - Name1 - City1 -
-
- 2 - Name2 - City2 -
-
-
\ No newline at end of file diff --git a/json/pom.xml b/json/pom.xml index 23955e5a75..7a6d57c28e 100644 --- a/json/pom.xml +++ b/json/pom.xml @@ -73,6 +73,12 @@ ${commons-collections4.version} test + + org.assertj + assertj-core + ${assertj-core.version} + test + @@ -86,6 +92,7 @@ 2.9.7 4.12 1.1.2 + 3.11.1 diff --git a/json/src/main/java/com/baeldung/jsonobject/iterate/JSONObjectIterator.java b/json/src/main/java/com/baeldung/jsonobject/iterate/JSONObjectIterator.java new file mode 100644 index 0000000000..0ff8650652 --- /dev/null +++ b/json/src/main/java/com/baeldung/jsonobject/iterate/JSONObjectIterator.java @@ -0,0 +1,50 @@ +package com.baeldung.jsonobject.iterate; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; + +public class JSONObjectIterator { + + private Map keyValuePairs; + + public JSONObjectIterator() { + keyValuePairs = new HashMap<>(); + } + + public void handleValue(String key, Object value) { + if (value instanceof JSONArray) { + handleJSONArray(key, (JSONArray) value); + } else if (value instanceof JSONObject) { + handleJSONObject((JSONObject) value); + } + keyValuePairs.put(key, value); + } + + public void handleJSONObject(JSONObject jsonObject) { + Iterator jsonObjectIterator = jsonObject.keys(); + jsonObjectIterator.forEachRemaining(key -> { + Object value = jsonObject.get(key); + handleValue(key, value); + }); + } + + public void handleJSONArray(String key, JSONArray jsonArray) { + Iterator jsonArrayIterator = jsonArray.iterator(); + jsonArrayIterator.forEachRemaining(element -> { + handleValue(key, element); + }); + } + + public Map getKeyValuePairs() { + return keyValuePairs; + } + + public void setKeyValuePairs(Map keyValuePairs) { + this.keyValuePairs = keyValuePairs; + } + +} diff --git a/json/src/test/java/com/baeldung/jsonobject/iterate/JSONObjectIteratorUnitTest.java b/json/src/test/java/com/baeldung/jsonobject/iterate/JSONObjectIteratorUnitTest.java new file mode 100644 index 0000000000..55cfdab53b --- /dev/null +++ b/json/src/test/java/com/baeldung/jsonobject/iterate/JSONObjectIteratorUnitTest.java @@ -0,0 +1,79 @@ +package com.baeldung.jsonobject.iterate; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Test; + +public class JSONObjectIteratorUnitTest { + + private JSONObjectIterator jsonObjectIterator = new JSONObjectIterator(); + + @Test + public void givenJSONObject_whenIterating_thenGetKeyValuePairs() { + JSONObject jsonObject = getJsonObject(); + + jsonObjectIterator.handleJSONObject(jsonObject); + + Map keyValuePairs = jsonObjectIterator.getKeyValuePairs(); + assertThat(keyValuePairs.get("rType")).isEqualTo("Regular"); + assertThat(keyValuePairs.get("rId")).isEqualTo("1001"); + assertThat(keyValuePairs.get("cType")).isEqualTo("Chocolate"); + assertThat(keyValuePairs.get("cId")).isEqualTo("1002"); + assertThat(keyValuePairs.get("bType")).isEqualTo("BlueBerry"); + assertThat(keyValuePairs.get("bId")).isEqualTo("1003"); + assertThat(keyValuePairs.get("name")).isEqualTo("Cake"); + assertThat(keyValuePairs.get("cakeId")).isEqualTo("0001"); + assertThat(keyValuePairs.get("type")).isEqualTo("donut"); + assertThat(keyValuePairs.get("Type")).isEqualTo("Maple"); + assertThat(keyValuePairs.get("tId")).isEqualTo("5001"); + assertThat(keyValuePairs.get("batters") + .toString()).isEqualTo("[{\"rType\":\"Regular\",\"rId\":\"1001\"},{\"cType\":\"Chocolate\",\"cId\":\"1002\"},{\"bType\":\"BlueBerry\",\"bId\":\"1003\"}]"); + assertThat(keyValuePairs.get("cakeShapes") + .toString()).isEqualTo("[\"square\",\"circle\",\"heart\"]"); + assertThat(keyValuePairs.get("topping") + .toString()).isEqualTo("{\"Type\":\"Maple\",\"tId\":\"5001\"}"); + } + + private JSONObject getJsonObject() { + JSONObject cake = new JSONObject(); + cake.put("cakeId", "0001"); + cake.put("type", "donut"); + cake.put("name", "Cake"); + + JSONArray batters = new JSONArray(); + JSONObject regular = new JSONObject(); + regular.put("rId", "1001"); + regular.put("rType", "Regular"); + batters.put(regular); + JSONObject chocolate = new JSONObject(); + chocolate.put("cId", "1002"); + chocolate.put("cType", "Chocolate"); + batters.put(chocolate); + JSONObject blueberry = new JSONObject(); + blueberry.put("bId", "1003"); + blueberry.put("bType", "BlueBerry"); + batters.put(blueberry); + + JSONArray cakeShapes = new JSONArray(); + cakeShapes.put("square"); + cakeShapes.put("circle"); + cakeShapes.put("heart"); + + cake.put("cakeShapes", cakeShapes); + + cake.put("batters", batters); + + JSONObject topping = new JSONObject(); + topping.put("tId", "5001"); + topping.put("Type", "Maple"); + + cake.put("topping", topping); + + return cake; + } + +} diff --git a/libraries/pom.xml b/libraries/pom.xml index 2b30b556d3..a9af996740 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -692,6 +692,13 @@ asciidoctor-maven-plugin 1.5.7.1 + + + org.reflections + reflections + ${reflections.version} + + @@ -909,6 +916,8 @@ 1.1.0 2.7.1 3.6 + 0.9.11 + - + \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java b/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java index 9f53f3d25b..bee947df12 100644 --- a/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java +++ b/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java @@ -6,7 +6,7 @@ import org.derive4j.Make; @Data(value = @Derive( inClass = "{ClassName}Impl", - make = {Make.lazyConstructor, Make.constructors} + make = {Make.lazyConstructor, Make.constructors, Make.getters} )) public interface LazyRequest { interface Cases{ diff --git a/libraries/src/main/java/com/baeldung/reflections/ReflectionsApp.java b/libraries/src/main/java/com/baeldung/reflections/ReflectionsApp.java new file mode 100644 index 0000000000..30da8ea837 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/reflections/ReflectionsApp.java @@ -0,0 +1,71 @@ +package com.baeldung.reflections; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.Date; +import java.util.Set; +import java.util.regex.Pattern; + +import org.reflections.Reflections; +import org.reflections.scanners.MethodAnnotationsScanner; +import org.reflections.scanners.MethodParameterScanner; +import org.reflections.scanners.ResourcesScanner; +import org.reflections.scanners.Scanner; +import org.reflections.scanners.SubTypesScanner; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; + +public class ReflectionsApp { + + public Set> getReflectionsSubTypes() { + Reflections reflections = new Reflections("org.reflections"); + Set> scannersSet = reflections.getSubTypesOf(Scanner.class); + return scannersSet; + } + + public Set> getJDKFunctinalInterfaces() { + Reflections reflections = new Reflections("java.util.function"); + Set> typesSet = reflections.getTypesAnnotatedWith(FunctionalInterface.class); + return typesSet; + } + + public Set getDateDeprecatedMethods() { + Reflections reflections = new Reflections(java.util.Date.class, new MethodAnnotationsScanner()); + Set deprecatedMethodsSet = reflections.getMethodsAnnotatedWith(Deprecated.class); + return deprecatedMethodsSet; + } + + @SuppressWarnings("rawtypes") + public Set getDateDeprecatedConstructors() { + Reflections reflections = new Reflections(java.util.Date.class, new MethodAnnotationsScanner()); + Set constructorsSet = reflections.getConstructorsAnnotatedWith(Deprecated.class); + return constructorsSet; + } + + public Set getMethodsWithDateParam() { + Reflections reflections = new Reflections(java.text.SimpleDateFormat.class, new MethodParameterScanner()); + Set methodsSet = reflections.getMethodsMatchParams(Date.class); + return methodsSet; + } + + public Set getMethodsWithVoidReturn() { + Reflections reflections = new Reflections(java.text.SimpleDateFormat.class, new MethodParameterScanner()); + Set methodsSet = reflections.getMethodsReturn(void.class); + return methodsSet; + } + + public Set getPomXmlPaths() { + Reflections reflections = new Reflections(new ResourcesScanner()); + Set resourcesSet = reflections.getResources(Pattern.compile(".*pom\\.xml")); + return resourcesSet; + } + + public Set> getReflectionsSubTypesUsingBuilder() { + Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage("org.reflections")) + .setScanners(new SubTypesScanner())); + + Set> scannersSet = reflections.getSubTypesOf(Scanner.class); + return scannersSet; + } + +} diff --git a/libraries/src/test/java/com/baeldung/reflections/ReflectionsUnitTest.java b/libraries/src/test/java/com/baeldung/reflections/ReflectionsUnitTest.java new file mode 100644 index 0000000000..9a3ef0747b --- /dev/null +++ b/libraries/src/test/java/com/baeldung/reflections/ReflectionsUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.reflections; + +import static org.junit.jupiter.api.Assertions.assertFalse; + +import org.junit.jupiter.api.Test; + +public class ReflectionsUnitTest { + + @Test + public void givenTypeThenGetAllSubTypes() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getReflectionsSubTypes() + .isEmpty()); + } + + @Test + public void givenTypeAndUsingBuilderThenGetAllSubTypes() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getReflectionsSubTypesUsingBuilder() + .isEmpty()); + } + + @Test + public void givenAnnotationThenGetAllAnnotatedMethods() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getDateDeprecatedMethods() + .isEmpty()); + } + + @Test + public void givenAnnotationThenGetAllAnnotatedConstructors() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getDateDeprecatedConstructors() + .isEmpty()); + } + + @Test + public void givenParamTypeThenGetAllMethods() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getMethodsWithDateParam() + .isEmpty()); + } + + @Test + public void givenReturnTypeThenGetAllMethods() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getMethodsWithVoidReturn() + .isEmpty()); + } +} diff --git a/maven/.gitignore b/maven/.gitignore index f843ae9109..bae0b0d7ce 100644 --- a/maven/.gitignore +++ b/maven/.gitignore @@ -1 +1,2 @@ -/output-resources \ No newline at end of file +/output-resources +/.idea/ diff --git a/maven/custom-rule/pom.xml b/maven/custom-rule/pom.xml new file mode 100644 index 0000000000..f76e0db11e --- /dev/null +++ b/maven/custom-rule/pom.xml @@ -0,0 +1,69 @@ + + + + maven + com.baeldung + 0.0.1-SNAPSHOT + + 4.0.0 + custom-rule + + + 3.0.0-M2 + 2.0.9 + + + + + + + org.apache.maven.enforcer + enforcer-api + ${api.version} + + + org.apache.maven + maven-project + ${maven.version} + + + org.apache.maven + maven-core + ${maven.version} + + + org.apache.maven + maven-artifact + ${maven.version} + + + org.apache.maven + maven-plugin-api + ${maven.version} + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-9 + + + + + + + maven-verifier-plugin + ${maven.verifier.version} + + ../input-resources/verifications.xml + false + + + + + + + + + \ No newline at end of file diff --git a/maven/custom-rule/src/main/java/com/baeldung/enforcer/MyCustomRule.java b/maven/custom-rule/src/main/java/com/baeldung/enforcer/MyCustomRule.java new file mode 100644 index 0000000000..9b72f40bf1 --- /dev/null +++ b/maven/custom-rule/src/main/java/com/baeldung/enforcer/MyCustomRule.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 PloyRef + * Created by Seun Matt + * on 19 - 2 - 2019 + */ + +package com.baeldung.enforcer; + +import org.apache.maven.enforcer.rule.api.EnforcerRule; +import org.apache.maven.enforcer.rule.api.EnforcerRuleException; +import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; + +public class MyCustomRule implements EnforcerRule { + + public void execute(EnforcerRuleHelper enforcerRuleHelper) throws EnforcerRuleException { + + try { + + String groupId = (String) enforcerRuleHelper.evaluate("${project.groupId}"); + + if (groupId == null || !groupId.startsWith("org.baeldung")) { + throw new EnforcerRuleException("Project group id does not start with org.baeldung"); + } + + } + catch (ExpressionEvaluationException ex ) { + throw new EnforcerRuleException( "Unable to lookup an expression " + ex.getLocalizedMessage(), ex ); + } + } + + public boolean isCacheable() { + return false; + } + + public boolean isResultValid(EnforcerRule enforcerRule) { + return false; + } + + public String getCacheId() { + return null; + } +} diff --git a/maven/maven-enforcer/pom.xml b/maven/maven-enforcer/pom.xml new file mode 100644 index 0000000000..d54471e66c --- /dev/null +++ b/maven/maven-enforcer/pom.xml @@ -0,0 +1,74 @@ + + + + maven + com.baeldung + 0.0.1-SNAPSHOT + + 4.0.0 + maven-enforcer + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M2 + + + + + + + + + + enforce + + enforce + + + + + + 3.0 + Invalid Maven version. It should, at least, be 3.0 + + + 1.8 + + + ui + WARN + + + cook + WARN + + + local,base + Missing active profiles + WARN + + + + + + + + + + maven-verifier-plugin + ${maven.verifier.version} + + ../input-resources/verifications.xml + false + + + + + + + \ No newline at end of file diff --git a/maven/pom.xml b/maven/pom.xml index 01fd28db74..942bf683e2 100644 --- a/maven/pom.xml +++ b/maven/pom.xml @@ -4,8 +4,12 @@ com.baeldung maven 0.0.1-SNAPSHOT - maven - war + + custom-rule + maven-enforcer + + maven + pom diff --git a/spring-5/pom.xml b/spring-5/pom.xml index 701aa3831d..6e4162fbcc 100644 --- a/spring-5/pom.xml +++ b/spring-5/pom.xml @@ -89,12 +89,6 @@ org.junit.jupiter junit-jupiter-api - - org.awaitility - awaitility - ${awaitility.version} - test - org.springframework.restdocs @@ -162,7 +156,6 @@ 4.1 ${project.build.directory}/generated-snippets 2.21.0 - 3.1.6 diff --git a/spring-boot-data/README.md b/spring-boot-data/README.md index e69de29bb2..21f7303c48 100644 --- a/spring-boot-data/README.md +++ b/spring-boot-data/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Formatting JSON Dates in Spring ](https://www.baeldung.com/spring-boot-formatting-json-dates) \ No newline at end of file diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index 3fbd21f24e..f7f7ec6598 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -6,3 +6,4 @@ Module for the articles that are part of the Spring REST E-book: 4. [Build a REST API with Spring and Java Config](http://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration) 5. [HATEOAS for a Spring REST Service](http://www.baeldung.com/rest-api-discoverability-with-spring) 6. [REST API Discoverability and HATEOAS](http://www.baeldung.com/restful-web-service-discoverability) +7. [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index 3c8c4d7486..decaccd148 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -25,16 +25,26 @@ com.fasterxml.jackson.dataformat jackson-dataformat-xml - + + + org.springframework + spring-oxm + + + com.thoughtworks.xstream + xstream + ${xstream.version} + + com.h2database h2 - + org.springframework.boot spring-boot-starter-data-jpa - - + + @@ -67,5 +77,6 @@ com.baeldung.SpringBootRestApplication 27.0.1-jre + 1.4.11.1 diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java index 9af3d07bed..f19d1c0e0b 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java @@ -8,6 +8,9 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import com.thoughtworks.xstream.annotations.XStreamAlias; + +@XStreamAlias("Foo") @Entity public class Foo implements Serializable { diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java index 80ee975e84..f581e4ec10 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java @@ -1,10 +1,49 @@ package com.baeldung.spring; +import java.util.List; + +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; +import org.springframework.oxm.xstream.XStreamMarshaller; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - @Configuration +// If we want to enable xml configurations for message-converter: +// @ImportResource("classpath:WEB-INF/api-servlet.xml") public class WebConfig implements WebMvcConfigurer { + // @Override + // public void configureMessageConverters(final List> messageConverters) { + // messageConverters.add(new MappingJackson2HttpMessageConverter()); + // messageConverters.add(createXmlHttpMessageConverter()); + // } + // + // private HttpMessageConverter createXmlHttpMessageConverter() { + // final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); + // + // final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); + // xstreamMarshaller.setAutodetectAnnotations(true); + // xmlConverter.setMarshaller(xstreamMarshaller); + // xmlConverter.setUnmarshaller(xstreamMarshaller); + // + // return xmlConverter; + // } + + // Another possibility is to create a bean which will be automatically added to the Spring Boot Autoconfigurations +// @Bean +// public HttpMessageConverter createXmlHttpMessageConverter() { +// final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); +// +// final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); +// xstreamMarshaller.setAutodetectAnnotations(true); +// xmlConverter.setMarshaller(xstreamMarshaller); +// xmlConverter.setUnmarshaller(xstreamMarshaller); +// +// return xmlConverter; +// } + } \ No newline at end of file diff --git a/spring-boot-rest/src/main/resources/WEB-INF/api-servlet.xml b/spring-boot-rest/src/main/resources/WEB-INF/api-servlet.xml new file mode 100644 index 0000000000..78e38e1448 --- /dev/null +++ b/spring-boot-rest/src/main/resources/WEB-INF/api-servlet.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json b/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json new file mode 100644 index 0000000000..5a6230bd22 --- /dev/null +++ b/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json @@ -0,0 +1,184 @@ +{ + "info": { + "_postman_id": "9989b5be-13ba-4d22-8e43-d05dbf628e58", + "name": "foo API test", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "add a foo", + "event": [ + { + "listen": "test", + "script": { + "id": "a01534dc-6fc7-4c54-ba1d-6bcf311e5836", + "exec": [ + "pm.test(\"success status\", () => pm.response.to.be.success );", + "", + "pm.test(\"name is correct\", () => ", + " pm.expect(pm.response.json().name).to.equal(\"Transformers\"));", + "", + "pm.test(\"id was assigned\", () => ", + " pm.expect(pm.response.json().id).to.be.not.null );", + "", + "pm.variables.set(\"id\", pm.response.json().id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Transformers\"\n}" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos" + ] + } + }, + "response": [] + }, + { + "name": "get a foo", + "event": [ + { + "listen": "test", + "script": { + "id": "03de440c-b483-4ab8-a11a-d0c99b349963", + "exec": [ + "pm.test(\"success status\", () => pm.response.to.be.success );", + "", + "pm.test(\"name is correct\", () => ", + " pm.expect(pm.response.json().name).to.equal(\"Transformers\"));", + "", + "pm.test(\"id is correct\", () => ", + " pm.expect(pm.response.json().id).to.equal(pm.variables.get(\"id\")) );" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "delete a foo", + "event": [ + { + "listen": "test", + "script": { + "id": "74c1bb0f-c06c-48b1-a545-459233541b14", + "exec": [ + "pm.test(\"success status\", () => pm.response.to.be.success );" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "verify delete", + "event": [ + { + "listen": "test", + "script": { + "id": "03de440c-b483-4ab8-a11a-d0c99b349963", + "exec": [ + "pm.test(\"status is 500\", () => pm.response.to.have.status(500) );", + "", + "pm.test(\"no value present\", () => ", + " pm.expect(pm.response.json().cause).to.equal(\"No value present\"));" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos", + "{{id}}" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerUnitTest.java b/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerIntegrationTest.java similarity index 98% rename from spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerUnitTest.java rename to spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerIntegrationTest.java index 0585c06a59..654e7925b9 100644 --- a/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerUnitTest.java +++ b/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerIntegrationTest.java @@ -13,7 +13,7 @@ import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = SpringBootSecurityTagLibsApplication.class) -public class HomeControllerUnitTest { +public class HomeControllerIntegrationTest { @Autowired private TestRestTemplate restTemplate; diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java new file mode 100644 index 0000000000..b77598c113 --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java @@ -0,0 +1,31 @@ +package com.baeldung.spring.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.validation.annotation.Validated; +import javax.validation.constraints.*; + +@Controller +@RequestMapping("/public/api/1") +@Validated +public class RequestAndPathVariableValidationController { + + @GetMapping("/name-for-day") + public String getNameOfDayByNumberRequestParam(@RequestParam @Min(1) @Max(7) Integer dayOfWeek) { + return dayOfWeek + ""; + } + + @GetMapping("/name-for-day/{dayOfWeek}") + public String getNameOfDayByPathVariable(@PathVariable("dayOfWeek") @Min(1) @Max(7) Integer dayOfWeek) { + return dayOfWeek + ""; + } + + @GetMapping("/valid-name") + public void validStringRequestParam(@RequestParam @NotBlank @Size(max = 10) @Pattern(regexp = "^[A-Z][a-zA-Z0-9]+$") String name) { + + } + +} diff --git a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java new file mode 100644 index 0000000000..318a15d8f7 --- /dev/null +++ b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java @@ -0,0 +1,72 @@ +package com.baeldung.spring.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.spring.ClientWebConfig; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = ClientWebConfig.class) +@WebAppConfiguration +public class RequestAndPathVariableValidationControllerIntegrationTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext webApplicationContext; + + @Before + public void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); + } + + @Test + public void getNameOfDayByNumberRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(5))) + .andExpect(status().isOk()); + } + + @Test + public void getNameOfDayByNumberRequestParam_whenGetWithRequestParamOutOfRange_thenReturn400() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(15))) + .andExpect(status().isBadRequest()); + } + + @Test + public void getNameOfDayByPathVariable_whenGetWithProperRequestParam_thenReturn200() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day/{dayOfWeek}", Integer.toString(5))).andExpect(status().isOk()); + } + + @Test + public void getNameOfDayByPathVariable_whenGetWithRequestParamOutOfRange_thenReturn400() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day/{dayOfWeek}", Integer.toString(15))) + .andExpect(status().isBadRequest()); + } + + @Test + public void validStringRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception { + mockMvc.perform(get("/public/api/1/valid-name").param("name", "John")).andExpect(status().isOk()); + } + + @Test + public void validStringRequestParam_whenGetWithTooLongRequestParam_thenReturn400() throws Exception { + mockMvc.perform(get("/public/api/1/valid-name").param("name", "asdfghjklqw")) + .andExpect(status().isBadRequest()); + } + + @Test + public void validStringRequestParam_whenGetWithLowerCaseRequestParam_thenReturn400() throws Exception { + mockMvc.perform(get("/public/api/1/valid-name").param("name", "john")).andExpect(status().isBadRequest()); + } +} diff --git a/spring-rest/README.md b/spring-rest/README.md index 4921ab012c..9a2c1fd96c 100644 --- a/spring-rest/README.md +++ b/spring-rest/README.md @@ -5,7 +5,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [Spring @RequestMapping](http://www.baeldung.com/spring-requestmapping) -- [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) - [Returning Custom Status Codes from Spring Controllers](http://www.baeldung.com/spring-mvc-controller-custom-http-status-code) - [A Guide to OkHttp](http://www.baeldung.com/guide-to-okhttp) - [Binary Data Formats in a Spring REST API](http://www.baeldung.com/spring-rest-api-with-binary-data-formats) diff --git a/spring-rest/pom.xml b/spring-rest/pom.xml index 5c88697cef..36934af101 100644 --- a/spring-rest/pom.xml +++ b/spring-rest/pom.xml @@ -52,10 +52,6 @@ org.springframework spring-webmvc - - org.springframework - spring-oxm - commons-fileupload commons-fileupload @@ -86,12 +82,6 @@ jackson-dataformat-xml - - com.thoughtworks.xstream - xstream - ${xstream.version} - - com.google.guava @@ -281,7 +271,6 @@ 1.4 3.1.0 3.5 - 1.4.9 20.0 diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java b/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java index d5209a520b..dc4fb9c695 100644 --- a/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java +++ b/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java @@ -8,8 +8,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; -import org.springframework.oxm.xstream.XStreamMarshaller; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -33,22 +31,12 @@ public class WebConfig implements WebMvcConfigurer { .dateFormat(new SimpleDateFormat("dd-MM-yyyy hh:mm")); messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build())); // messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build())); - - // messageConverters.add(createXmlHttpMessageConverter()); + // messageConverters.add(new MappingJackson2HttpMessageConverter()); // messageConverters.add(new ProtobufHttpMessageConverter()); } - private HttpMessageConverter createXmlHttpMessageConverter() { - final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); - - final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); - xmlConverter.setMarshaller(xstreamMarshaller); - xmlConverter.setUnmarshaller(xstreamMarshaller); - - return xmlConverter; - } */ } diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java b/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java index 186df8e678..de1d76ed92 100644 --- a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java +++ b/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java @@ -1,8 +1,5 @@ package com.baeldung.sampleapp.web.dto; -import com.thoughtworks.xstream.annotations.XStreamAlias; - -@XStreamAlias("Foo") public class Foo { private long id; private String name; diff --git a/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml b/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml index ddb9c91792..3d83ebf6c9 100644 --- a/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml +++ b/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml @@ -10,21 +10,11 @@ - - - diff --git a/spring-security-angular/README.md b/spring-security-angular/README.md index 80312c4bab..49cd8dd62d 100644 --- a/spring-security-angular/README.md +++ b/spring-security-angular/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Spring Security Login Page with Angular](https://www.baeldung.com/spring-security-login-angular) +- [Fixing 401s with CORS Preflights and Spring Security](https://www.baeldung.com/spring-security-cors-preflight) diff --git a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthServerConfig.java b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthServerConfig.java index 07057c3875..0835f3d721 100644 --- a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthServerConfig.java +++ b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthServerConfig.java @@ -30,7 +30,7 @@ public class AuthServerConfig extends AuthorizationServerConfigurerAdapter { .authorizedGrantTypes("authorization_code") .scopes("user_info") .autoApprove(true) - .redirectUris("http://localhost:8082/ui/login","http://localhost:8083/ui2/login","http://localhost:8082/login") + .redirectUris("http://localhost:8082/ui/login","http://localhost:8083/ui2/login","http://localhost:8082/login","http://www.example.com/") // .accessTokenValiditySeconds(3600) ; // 1 hour } diff --git a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/SecurityConfig.java index 5cebf4f4d2..2254de8e39 100644 --- a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/SecurityConfig.java +++ b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/SecurityConfig.java @@ -22,7 +22,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { .authenticated() .and() .formLogin() - .permitAll(); + .permitAll() + .and().csrf().disable(); } // @formatter:on @Override diff --git a/spring-security-sso/spring-security-sso-auth-server/src/test/java/org/baeldung/UserInfoEndpointLiveTest.java b/spring-security-sso/spring-security-sso-auth-server/src/test/java/org/baeldung/UserInfoEndpointLiveTest.java new file mode 100644 index 0000000000..ffdb1df8fe --- /dev/null +++ b/spring-security-sso/spring-security-sso-auth-server/src/test/java/org/baeldung/UserInfoEndpointLiveTest.java @@ -0,0 +1,51 @@ +package org.baeldung; +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; + +import io.restassured.RestAssured; +import io.restassured.response.Response; + +public class UserInfoEndpointLiveTest { + + @Test + public void givenAccessToken_whenAccessUserInfoEndpoint_thenSuccess() { + String accessToken = obtainAccessTokenUsingAuthorizationCodeFlow("john","123"); + Response response = RestAssured.given().header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken).get("http://localhost:8081/auth/user/me"); + + assertEquals(HttpStatus.OK.value(), response.getStatusCode()); + assertEquals("john", response.jsonPath().get("name")); + } + + private String obtainAccessTokenUsingAuthorizationCodeFlow(String username, String password) { + final String authServerUri = "http://localhost:8081/auth"; + final String redirectUrl = "http://www.example.com/"; + final String authorizeUrl = authServerUri + "/oauth/authorize?response_type=code&client_id=SampleClientId&redirect_uri=" + redirectUrl; + final String tokenUrl = authServerUri + "/oauth/token"; + + // user login + Response response = RestAssured.given().formParams("username", username, "password", password).post(authServerUri + "/login"); + final String cookieValue = response.getCookie("JSESSIONID"); + + // get authorization code + RestAssured.given().cookie("JSESSIONID", cookieValue).get(authorizeUrl); + response = RestAssured.given().cookie("JSESSIONID", cookieValue).post(authorizeUrl); + assertEquals(HttpStatus.FOUND.value(), response.getStatusCode()); + final String location = response.getHeader(HttpHeaders.LOCATION); + final String code = location.substring(location.indexOf("code=") + 5); + + // get access token + Map params = new HashMap(); + params.put("grant_type", "authorization_code"); + params.put("code", code); + params.put("client_id", "SampleClientId"); + params.put("redirect_uri", redirectUrl); + response = RestAssured.given().auth().basic("SampleClientId", "secret").formParams(params).post(tokenUrl); + return response.jsonPath().getString("access_token"); + } +} diff --git a/testing-modules/rest-testing/README.md b/testing-modules/rest-testing/README.md index ab038807bc..25e036ba5d 100644 --- a/testing-modules/rest-testing/README.md +++ b/testing-modules/rest-testing/README.md @@ -8,6 +8,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [Test a REST API with Java](http://www.baeldung.com/integration-testing-a-rest-api) - [Introduction to WireMock](http://www.baeldung.com/introduction-to-wiremock) +- [Using WireMock Scenarios](http://www.baeldung.com/using-wiremock-scenarios) - [REST API Testing with Cucumber](http://www.baeldung.com/cucumber-rest-api-testing) - [Testing a REST API with JBehave](http://www.baeldung.com/jbehave-rest-testing) - [REST API Testing with Karate](http://www.baeldung.com/karate-rest-api-testing) diff --git a/testing-modules/rest-testing/pom.xml b/testing-modules/rest-testing/pom.xml index 2b1f146f0f..c3a9477a47 100644 --- a/testing-modules/rest-testing/pom.xml +++ b/testing-modules/rest-testing/pom.xml @@ -159,7 +159,7 @@ 2.9.0 1.2.5 - 2.4.1 + 2.21.0 0.6.1 4.4.5 diff --git a/testing-modules/rest-testing/src/test/java/com/baeldung/rest/wiremock/scenario/WireMockScenarioExampleIntegrationTest.java b/testing-modules/rest-testing/src/test/java/com/baeldung/rest/wiremock/scenario/WireMockScenarioExampleIntegrationTest.java new file mode 100644 index 0000000000..946d3d717f --- /dev/null +++ b/testing-modules/rest-testing/src/test/java/com/baeldung/rest/wiremock/scenario/WireMockScenarioExampleIntegrationTest.java @@ -0,0 +1,75 @@ +package com.baeldung.rest.wiremock.scenario; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.junit.Rule; +import org.junit.Test; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.github.tomakehurst.wiremock.stubbing.Scenario; + +public class WireMockScenarioExampleIntegrationTest { + + private static final String THIRD_STATE = "third"; + private static final String SECOND_STATE = "second"; + private static final String TIP_01 = "finally block is not called when System.exit() is called in the try block"; + private static final String TIP_02 = "keep your code clean"; + private static final String TIP_03 = "use composition rather than inheritance"; + private static final String TEXT_PLAIN = "text/plain"; + + static int port = 9999; + + @Rule + public WireMockRule wireMockRule = new WireMockRule(port); + + @Test + public void changeStateOnEachCallTest() throws IOException { + createWireMockStub(Scenario.STARTED, SECOND_STATE, TIP_01); + createWireMockStub(SECOND_STATE, THIRD_STATE, TIP_02); + createWireMockStub(THIRD_STATE, Scenario.STARTED, TIP_03); + + assertEquals(TIP_01, nextTip()); + assertEquals(TIP_02, nextTip()); + assertEquals(TIP_03, nextTip()); + assertEquals(TIP_01, nextTip()); + } + + private void createWireMockStub(String currentState, String nextState, String responseBody) { + stubFor(get(urlEqualTo("/java-tip")) + .inScenario("java tips") + .whenScenarioStateIs(currentState) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", TEXT_PLAIN) + .withBody(responseBody)) + .willSetStateTo(nextState) + ); + } + + private String nextTip() throws ClientProtocolException, IOException { + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpGet request = new HttpGet(String.format("http://localhost:%s/java-tip", port)); + HttpResponse httpResponse = httpClient.execute(request); + return firstLineOfResponse(httpResponse); + } + + private static String firstLineOfResponse(HttpResponse httpResponse) throws IOException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()))) { + return reader.readLine(); + } + } + +} diff --git a/testing-modules/spring-testing/pom.xml b/testing-modules/spring-testing/pom.xml index a137bc8d33..630aed0c81 100644 --- a/testing-modules/spring-testing/pom.xml +++ b/testing-modules/spring-testing/pom.xml @@ -54,6 +54,18 @@ spring-data-jpa LATEST + + org.junit.jupiter + junit-jupiter + ${junit.jupiter.version} + test + + + org.awaitility + awaitility + ${awaitility.version} + test + @@ -70,6 +82,8 @@ 2.0.0.0 + 3.1.6 + 5.4.0 \ No newline at end of file diff --git a/spring-5/src/main/java/com/baeldung/config/ScheduledConfig.java b/testing-modules/spring-testing/src/main/java/com/baeldung/config/ScheduledConfig.java similarity index 100% rename from spring-5/src/main/java/com/baeldung/config/ScheduledConfig.java rename to testing-modules/spring-testing/src/main/java/com/baeldung/config/ScheduledConfig.java diff --git a/spring-5/src/main/java/com/baeldung/scheduled/Counter.java b/testing-modules/spring-testing/src/main/java/com/baeldung/scheduled/Counter.java similarity index 100% rename from spring-5/src/main/java/com/baeldung/scheduled/Counter.java rename to testing-modules/spring-testing/src/main/java/com/baeldung/scheduled/Counter.java diff --git a/spring-5/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java similarity index 100% rename from spring-5/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java rename to testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java diff --git a/spring-5/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java similarity index 100% rename from spring-5/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java rename to testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java