Merge remote-tracking branch 'upstream/master' into JAVA-3570
This commit is contained in:
commit
962e8839d6
|
@ -51,7 +51,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>${hibernate.version}</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
|
|
|
@ -10,3 +10,4 @@ This module contains articles about Java 14.
|
|||
- [Helpful NullPointerExceptions in Java 14](https://www.baeldung.com/java-14-nullpointerexception)
|
||||
- [Foreign Memory Access API in Java 14](https://www.baeldung.com/java-foreign-memory-access)
|
||||
- [Java 14 Record Keyword](https://www.baeldung.com/java-record-keyword)
|
||||
- [Java 14 – New Features](https://www.baeldung.com/java-14-new-features)
|
||||
|
|
|
@ -6,4 +6,5 @@ This module contains articles about Map data structures in Java.
|
|||
- [Java TreeMap vs HashMap](https://www.baeldung.com/java-treemap-vs-hashmap)
|
||||
- [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps)
|
||||
- [The Map.computeIfAbsent() Method](https://www.baeldung.com/java-map-computeifabsent)
|
||||
- [Collections.synchronizedMap vs. ConcurrentHashMap](https://www.baeldung.com/java-synchronizedmap-vs-concurrenthashmap)
|
||||
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-2)
|
||||
|
|
|
@ -15,7 +15,11 @@
|
|||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-core</artifactId>
|
||||
<version>${jmh-core.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package com.baeldung.map.concurrenthashmap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Threads;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
|
||||
@Fork(5)
|
||||
@Threads(10)
|
||||
@Warmup(iterations = 5)
|
||||
@State(Scope.Benchmark)
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
public class MapPerformanceComparison {
|
||||
|
||||
private int TEST_NO_ITEMS;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
org.openjdk.jmh.Main.main(args);
|
||||
}
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
TEST_NO_ITEMS = 1000;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void randomReadAndWriteSynchronizedMap() {
|
||||
Map<String, Integer> map = Collections.synchronizedMap(new HashMap<String, Integer>());
|
||||
performReadAndWriteTest(map);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void randomReadAndWriteConcurrentHashMap() {
|
||||
Map<String, Integer> map = new ConcurrentHashMap<>();
|
||||
performReadAndWriteTest(map);
|
||||
}
|
||||
|
||||
private void performReadAndWriteTest(final Map<String, Integer> map) {
|
||||
for (int i = 0; i < TEST_NO_ITEMS; i++) {
|
||||
Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS);
|
||||
map.get(String.valueOf(randNumber));
|
||||
map.put(String.valueOf(randNumber), randNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void randomWriteSynchronizedMap() {
|
||||
Map<String, Integer> map = Collections.synchronizedMap(new HashMap<String, Integer>());
|
||||
performWriteTest(map);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void randomWriteConcurrentHashMap() {
|
||||
Map<String, Integer> map = new ConcurrentHashMap<>();
|
||||
performWriteTest(map);
|
||||
}
|
||||
|
||||
private void performWriteTest(final Map<String, Integer> map) {
|
||||
for (int i = 0; i < TEST_NO_ITEMS; i++) {
|
||||
Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS);
|
||||
map.put(String.valueOf(randNumber), randNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void randomReadSynchronizedMap() {
|
||||
Map<String, Integer> map = Collections.synchronizedMap(new HashMap<String, Integer>());
|
||||
performReadTest(map);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void randomReadConcurrentHashMap() {
|
||||
Map<String, Integer> map = new ConcurrentHashMap<>();
|
||||
performReadTest(map);
|
||||
}
|
||||
|
||||
private void performReadTest(final Map<String, Integer> map) {
|
||||
for (int i = 0; i < TEST_NO_ITEMS; i++) {
|
||||
Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS);
|
||||
map.get(String.valueOf(randNumber));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.baeldung.map.concurrenthashmap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ConcurrentModificationErrorUnitTest {
|
||||
|
||||
@Test(expected = ConcurrentModificationException.class)
|
||||
public void whenRemoveAndAddOnHashMap_thenConcurrentModificationError() {
|
||||
Map<Integer, String> map = new HashMap<>();
|
||||
map.put(1, "baeldung");
|
||||
map.put(2, "HashMap");
|
||||
Map<Integer, String> synchronizedMap = Collections.synchronizedMap(map);
|
||||
Iterator<Entry<Integer, String>> iterator = synchronizedMap.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
synchronizedMap.put(3, "Modification");
|
||||
iterator.next();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = ConcurrentModificationException.class)
|
||||
public void whenRemoveAndAddOnTreeMap_thenConcurrentModificationError() {
|
||||
Map<Integer, String> map = new TreeMap<>();
|
||||
map.put(1, "baeldung");
|
||||
map.put(2, "HashMap");
|
||||
Map<Integer, String> synchronizedMap = Collections.synchronizedMap(map);
|
||||
Iterator<Entry<Integer, String>> iterator = synchronizedMap.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
synchronizedMap.put(3, "Modification");
|
||||
iterator.next();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = ConcurrentModificationException.class)
|
||||
public void whenRemoveAndAddOnLinkedHashMap_thenConcurrentModificationError() {
|
||||
Map<Integer, String> map = new LinkedHashMap<>();
|
||||
map.put(1, "baeldung");
|
||||
map.put(2, "HashMap");
|
||||
Map<Integer, String> synchronizedMap = Collections.synchronizedMap(map);
|
||||
Iterator<Entry<Integer, String>> iterator = synchronizedMap.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
synchronizedMap.put(3, "Modification");
|
||||
iterator.next();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenRemoveAndAddOnConcurrentHashMap_thenNoError() {
|
||||
Map<Integer, String> map = new ConcurrentHashMap<>();
|
||||
map.put(1, "baeldung");
|
||||
map.put(2, "HashMap");
|
||||
Iterator<Entry<Integer, String>> iterator = map.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
map.put(3, "Modification");
|
||||
iterator.next();
|
||||
}
|
||||
|
||||
Assert.assertEquals(3, map.size());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package com.baeldung.map.concurrenthashmap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class NullAllowInMapUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenHashMapBackedSynchronizedMap_whenNullAsKey_thenNoError() {
|
||||
Map<String, Integer> map = Collections
|
||||
.synchronizedMap(new HashMap<String, Integer>());
|
||||
map.put(null, 1);
|
||||
Assert.assertTrue(map.get(null).equals(1));
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void givenTreeMapBackedSynchronizedMap_whenNullAsKey_thenException() {
|
||||
Map<String, Integer> map = Collections.synchronizedMap(new TreeMap<String, Integer>());
|
||||
map.put(null, 1);
|
||||
Assert.assertTrue(map.get(null).equals(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLinkedHashMapBackedSynchronizedMap_whenNullAsKey_thenNoError() {
|
||||
Map<String, Integer> map = Collections
|
||||
.synchronizedMap(new LinkedHashMap<String, Integer>());
|
||||
map.put(null, 1);
|
||||
Assert.assertTrue(map.get(null).equals(1));
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void givenConcurrentHasMap_whenNullAsKey_thenException() {
|
||||
Map<String, Integer> map = new ConcurrentHashMap<>();
|
||||
map.put(null, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHashMapBackedSynchronizedMap_whenNullAsValue_thenNoError() {
|
||||
Map<String, Integer> map = Collections.synchronizedMap(new HashMap<String, Integer>());
|
||||
map.put("1", null);
|
||||
Assert.assertNull(map.get("1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTreeMapBackedSynchronizedMap_whenNullAsValue_thenNoError() {
|
||||
Map<String, Integer> map = Collections.synchronizedMap(new TreeMap<String, Integer>());
|
||||
map.put("1", null);
|
||||
Assert.assertNull(map.get("1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLinkedHashMapBackedSynchronizedMap_whenNullAsValue_thenNoError() {
|
||||
Map<String, Integer> map = Collections
|
||||
.synchronizedMap(new LinkedHashMap<String, Integer>());
|
||||
map.put("1", null);
|
||||
Assert.assertNull(map.get("1"));
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void givenConcurrentHasMap_whenNullAsValue_thenException() {
|
||||
Map<String, Integer> map = new ConcurrentHashMap<>();
|
||||
map.put("1", null);
|
||||
}
|
||||
|
||||
}
|
|
@ -31,7 +31,7 @@
|
|||
<!-- JPA Persistence Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>${hibernate.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
<!-- persistence -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>${hibernate.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>${hibernate.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
36
pom.xml
36
pom.xml
|
@ -606,9 +606,6 @@
|
|||
<module>spring-5-reactive-client</module>
|
||||
<module>spring-5-reactive-oauth</module>
|
||||
<module>spring-5-reactive-security</module>
|
||||
<module>spring-5-security</module>
|
||||
<module>spring-5-security-cognito</module>
|
||||
<module>spring-5-security-oauth</module>
|
||||
<module>spring-5-webflux</module>
|
||||
|
||||
<module>spring-activiti</module>
|
||||
|
@ -658,16 +655,9 @@
|
|||
<module>spring-kafka</module>
|
||||
<module>spring-katharsis</module>
|
||||
|
||||
<module>spring-ldap</module>
|
||||
|
||||
<module>spring-mobile</module>
|
||||
<module>spring-mockito</module>
|
||||
|
||||
<module>spring-mvc-basics-2</module>
|
||||
<module>spring-mvc-basics-3</module>
|
||||
<module>spring-mvc-basics-4</module>
|
||||
|
||||
<module>spring-mvc-forms-jsp</module>
|
||||
<module>spring-mvc-forms-thymeleaf</module>
|
||||
<module>spring-mvc-java</module>
|
||||
<module>spring-mvc-java-2</module>
|
||||
|
@ -683,7 +673,6 @@
|
|||
<module>spring-reactor</module>
|
||||
<module>spring-remoting</module>
|
||||
<module>spring-rest-angular</module>
|
||||
<module>spring-rest-http</module>
|
||||
<module>spring-rest-http-2</module>
|
||||
<module>spring-rest-query-language</module>
|
||||
<module>spring-rest-shell</module>
|
||||
|
@ -695,20 +684,15 @@
|
|||
|
||||
<module>spring-scheduling</module>
|
||||
<module>spring-security-modules</module>
|
||||
<module>spring-session</module>
|
||||
<module>spring-shell</module>
|
||||
<module>spring-sleuth</module>
|
||||
<module>spring-soap</module>
|
||||
<module>spring-social-login</module>
|
||||
<module>spring-soap</module>
|
||||
<module>spring-spel</module>
|
||||
<module>spring-state-machine</module>
|
||||
<module>spring-static-resources</module>
|
||||
<module>spring-swagger-codegen</module>
|
||||
|
||||
<module>spring-threads</module>
|
||||
<module>spring-thymeleaf</module>
|
||||
<module>spring-thymeleaf-2</module>
|
||||
<module>spring-thymeleaf-3</module>
|
||||
|
||||
<module>spring-vault</module>
|
||||
<module>spring-vertx</module>
|
||||
|
@ -1094,9 +1078,6 @@
|
|||
<module>spring-5-reactive-client</module>
|
||||
<module>spring-5-reactive-oauth</module>
|
||||
<module>spring-5-reactive-security</module>
|
||||
<module>spring-5-security</module>
|
||||
<module>spring-5-security-cognito</module>
|
||||
<module>spring-5-security-oauth</module>
|
||||
<module>spring-5-webflux</module>
|
||||
|
||||
<module>spring-activiti</module>
|
||||
|
@ -1144,16 +1125,9 @@
|
|||
<module>spring-kafka</module>
|
||||
<module>spring-katharsis</module>
|
||||
|
||||
<module>spring-ldap</module>
|
||||
|
||||
<module>spring-mobile</module>
|
||||
<module>spring-mockito</module>
|
||||
|
||||
<module>spring-mvc-basics-2</module>
|
||||
<module>spring-mvc-basics-3</module>
|
||||
<module>spring-mvc-basics-4</module>
|
||||
|
||||
<module>spring-mvc-forms-jsp</module>
|
||||
<module>spring-mvc-forms-thymeleaf</module>
|
||||
<module>spring-mvc-java</module>
|
||||
<module>spring-mvc-java-2</module>
|
||||
|
@ -1162,7 +1136,6 @@
|
|||
<module>spring-mvc-views</module>
|
||||
<module>spring-mvc-webflow</module>
|
||||
<module>spring-mvc-xml</module>
|
||||
<module>spring-mvc-crash</module>
|
||||
|
||||
<module>spring-protobuf</module>
|
||||
<module>spring-quartz</module>
|
||||
|
@ -1170,7 +1143,6 @@
|
|||
<module>spring-reactor</module>
|
||||
<module>spring-remoting</module>
|
||||
<module>spring-rest-angular</module>
|
||||
<module>spring-rest-http</module>
|
||||
<module>spring-rest-query-language</module>
|
||||
<module>spring-rest-shell</module>
|
||||
<module>spring-rest-simple</module>
|
||||
|
@ -1181,20 +1153,14 @@
|
|||
|
||||
<module>spring-scheduling</module>
|
||||
<module>spring-security-modules</module>
|
||||
<module>spring-session</module>
|
||||
<module>spring-shell</module>
|
||||
<module>spring-sleuth</module>
|
||||
<module>spring-soap</module>
|
||||
<module>spring-social-login</module>
|
||||
<module>spring-spel</module>
|
||||
<module>spring-state-machine</module>
|
||||
<module>spring-static-resources</module>
|
||||
<module>spring-swagger-codegen</module>
|
||||
|
||||
<module>spring-thymeleaf</module>
|
||||
<module>spring-thymeleaf-2</module>
|
||||
<module>spring-thymeleaf-3</module>
|
||||
|
||||
<module>spring-vault</module>
|
||||
<module>spring-vertx</module>
|
||||
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
|
||||
This module contains articles about Spring 5
|
||||
|
||||
### The Course
|
||||
The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||
|
||||
### Relevant Articles
|
||||
|
||||
- [Concurrent Test Execution in Spring 5](https://www.baeldung.com/spring-5-concurrent-tests)
|
||||
|
|
|
@ -9,6 +9,7 @@ This module contains articles about Spring with Apache Camel
|
|||
- [Introduction To Apache Camel](http://www.baeldung.com/apache-camel-intro)
|
||||
- [Integration Patterns With Apache Camel](http://www.baeldung.com/camel-integration-patterns)
|
||||
- [Using Apache Camel with Spring](http://www.baeldung.com/spring-apache-camel-tutorial)
|
||||
- [Unmarshalling a JSON Array Using camel-jackson](https://www.baeldung.com/java-camel-jackson-json-array)
|
||||
|
||||
### Framework Versions:
|
||||
|
||||
|
@ -23,4 +24,4 @@ To build this application execute:
|
|||
|
||||
To run this application you can either run our main class App from your IDE or you can execute following maven command:
|
||||
|
||||
`mvn exec:java -Dexec.mainClass="com.baeldung.camel.main.App"`
|
||||
`mvn exec:java -Dexec.mainClass="com.baeldung.camel.main.App"`
|
||||
|
|
|
@ -23,6 +23,12 @@ public class UserController {
|
|||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@GetMapping("/index")
|
||||
public String showUserList(Model model) {
|
||||
model.addAttribute("users", userRepository.findAll());
|
||||
return "index";
|
||||
}
|
||||
|
||||
@GetMapping("/signup")
|
||||
public String showSignUpForm(User user) {
|
||||
return "add-user";
|
||||
|
@ -35,7 +41,6 @@ public class UserController {
|
|||
}
|
||||
|
||||
userRepository.save(user);
|
||||
model.addAttribute("users", userRepository.findAll());
|
||||
return "redirect:/index";
|
||||
}
|
||||
|
||||
|
@ -43,6 +48,7 @@ public class UserController {
|
|||
public String showUpdateForm(@PathVariable("id") long id, Model model) {
|
||||
User user = userRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
|
||||
model.addAttribute("user", user);
|
||||
|
||||
return "update-user";
|
||||
}
|
||||
|
||||
|
@ -54,7 +60,7 @@ public class UserController {
|
|||
}
|
||||
|
||||
userRepository.save(user);
|
||||
model.addAttribute("users", userRepository.findAll());
|
||||
|
||||
return "redirect:/index";
|
||||
}
|
||||
|
||||
|
@ -62,7 +68,7 @@ public class UserController {
|
|||
public String deleteUser(@PathVariable("id") long id, Model model) {
|
||||
User user = userRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
|
||||
userRepository.delete(user);
|
||||
model.addAttribute("users", userRepository.findAll());
|
||||
return "index";
|
||||
|
||||
return "redirect:/index";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@ public class UserControllerUnitTest {
|
|||
userController = new UserController(mockedUserRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCalledIndex_thenCorrect() {
|
||||
assertThat(userController.showUserList(mockedModel)).isEqualTo("index");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCalledshowSignUpForm_thenCorrect() {
|
||||
User user = new User("John", "john@domain.com");
|
||||
|
@ -78,6 +83,6 @@ public class UserControllerUnitTest {
|
|||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void whenCalleddeleteUser_thenIllegalArgumentException() {
|
||||
assertThat(userController.deleteUser(1l, mockedModel)).isEqualTo("index");
|
||||
assertThat(userController.deleteUser(1l, mockedModel)).isEqualTo("redirect:/index");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
### Relevant Articles:
|
||||
|
||||
- [Spring Boot: Customize the Jackson ObjectMapper](https://www.baeldung.com/spring-boot-customize-jackson-objectmapper)
|
|
@ -15,3 +15,21 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
|||
- [Spring Boot and Togglz Aspect](https://www.baeldung.com/spring-togglz)
|
||||
- [Getting Started with GraphQL and Spring Boot](https://www.baeldung.com/spring-graphql)
|
||||
- [An Introduction to Kong](https://www.baeldung.com/kong)
|
||||
|
||||
### GraphQL sample queries
|
||||
|
||||
Query
|
||||
```shell script
|
||||
curl \
|
||||
--request POST 'localhost:8081/graphql' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{"query":"query {\n recentPosts(count: 2, offset: 0) {\n id\n title\n author {\n id\n posts {\n id\n }\n }\n }\n}"}'
|
||||
```
|
||||
|
||||
Mutation
|
||||
```shell script
|
||||
curl \
|
||||
--request POST 'localhost:8081/graphql' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{"query":"mutation {\n writePost(title: \"New Title\", author: \"Author2\", text: \"New Text\") {\n id\n category\n author {\n id\n name\n }\n }\n}"}'
|
||||
```
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<artifactId>spring-boot-libraries</artifactId>
|
||||
<name>spring-boot-libraries</name>
|
||||
<packaging>war</packaging>
|
||||
<description>This is simple boot application for Spring boot actuator test</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.spring-boot-modules</groupId>
|
||||
|
|
|
@ -2,12 +2,14 @@ package com.baeldung.demo;
|
|||
|
||||
import com.baeldung.graphql.GraphqlConfiguration;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
@SpringBootApplication
|
||||
@Import(GraphqlConfiguration.class)
|
||||
@EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class})
|
||||
public class DemoApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.baeldung.graphql;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.coxautodev.graphql.tools.GraphQLResolver;
|
||||
|
||||
public class PostResolver implements GraphQLResolver<Post> {
|
||||
|
@ -11,7 +9,7 @@ public class PostResolver implements GraphQLResolver<Post> {
|
|||
this.authorDao = authorDao;
|
||||
}
|
||||
|
||||
public Optional<Author> getAuthor(Post post) {
|
||||
return authorDao.getAuthor(post.getAuthorId());
|
||||
public Author getAuthor(Post post) {
|
||||
return authorDao.getAuthor(post.getAuthorId()).orElseThrow(RuntimeException::new);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
server:
|
||||
port: 8081
|
|
@ -3,7 +3,7 @@ type Post {
|
|||
title: String!
|
||||
text: String!
|
||||
category: String
|
||||
author: Author
|
||||
author: Author!
|
||||
}
|
||||
|
||||
type Author {
|
|
@ -9,7 +9,7 @@ server.error.include-exception=true
|
|||
server.error.include-stacktrace=always
|
||||
|
||||
## Server connections configuration
|
||||
server.tomcat.max-threads=200
|
||||
server.tomcat.threads.max=200
|
||||
server.connection-timeout=5s
|
||||
server.max-http-header-size=8KB
|
||||
server.tomcat.max-swallow-size=2MB
|
||||
|
|
|
@ -171,7 +171,7 @@
|
|||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<hibernate.version>5.2.10.Final</hibernate.version>
|
||||
<springdoc.version>1.2.32</springdoc.version>
|
||||
<springdoc.version>1.5.2</springdoc.version>
|
||||
<asciidoctor-plugin.version>1.5.6</asciidoctor-plugin.version>
|
||||
<kotlin.version>1.4.0</kotlin.version>
|
||||
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
|
||||
|
|
|
@ -5,6 +5,17 @@ import java.util.Collection;
|
|||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import com.baeldung.springdoc.exception.BookNotFoundException;
|
||||
import com.baeldung.springdoc.model.Book;
|
||||
import com.baeldung.springdoc.repository.BookRepository;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import org.springdoc.api.annotations.ParameterObject;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
@ -21,17 +32,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
|||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.springdoc.exception.BookNotFoundException;
|
||||
import com.baeldung.springdoc.model.Book;
|
||||
import com.baeldung.springdoc.repository.BookRepository;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/book")
|
||||
public class BookController {
|
||||
|
@ -58,7 +58,7 @@ public class BookController {
|
|||
}
|
||||
|
||||
@GetMapping("/filter")
|
||||
public Page<Book> filterBooks(Pageable pageable) {
|
||||
public Page<Book> filterBooks(@ParameterObject Pageable pageable) {
|
||||
return repository.getBooks(pageable);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,169 +0,0 @@
|
|||
{
|
||||
"info": {
|
||||
"_postman_id": "910d9690-f629-4491-bbbd-adb30982a386",
|
||||
"name": "GraphQL collection",
|
||||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||||
},
|
||||
"item": [
|
||||
{
|
||||
"name": "mutations",
|
||||
"item": [
|
||||
{
|
||||
"name": "writePost",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "graphql",
|
||||
"graphql": {
|
||||
"query": "mutation writePost ($title: String!, $text: String!, $category: String) {\n writePost (title: $title, text: $text, category: $category) {\n id\n title\n text\n category\n }\n}",
|
||||
"variables": "{\n \"title\": \"\",\n \"text\": \"\",\n \"category\": \"\"\n}"
|
||||
},
|
||||
"options": {
|
||||
"graphql": {}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:9090/springbootapp/graphql",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "9090",
|
||||
"path": [
|
||||
"springbootapp",
|
||||
"graphql"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
],
|
||||
"protocolProfileBehavior": {}
|
||||
},
|
||||
{
|
||||
"name": "queries",
|
||||
"item": [
|
||||
{
|
||||
"name": "get recent posts",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "graphql",
|
||||
"graphql": {
|
||||
"query": "{\r\n recentPosts(count: 10, offset: 0) {\r\n id\r\n title\r\n category\r\n text\r\n author {\r\n id\r\n name\r\n thumbnail\r\n }\r\n }\r\n}",
|
||||
"variables": ""
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:9090/springbootapp/graphql",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "9090",
|
||||
"path": [
|
||||
"springbootapp",
|
||||
"graphql"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "recentPosts - variables",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [],
|
||||
"body": {
|
||||
"mode": "graphql",
|
||||
"graphql": {
|
||||
"query": "query recentPosts ($count: Int, $offset: Int) {\n recentPosts (count: $count, offset: $offset) {\n id\n title\n text\n category\n }\n}",
|
||||
"variables": "{\n \"count\": 1,\n \"offset\": 0\n}"
|
||||
},
|
||||
"options": {
|
||||
"graphql": {}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:9090/springbootapp/graphql",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "9090",
|
||||
"path": [
|
||||
"springbootapp",
|
||||
"graphql"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "get recent posts - raw",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/graphql",
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "query {\r\n recentPosts(count: 10, offset: 0) {\r\n id\r\n title\r\n category\r\n author {\r\n id\r\n name\r\n thumbnail\r\n }\r\n }\r\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "http://localhost:9090/springbootapp/graphql",
|
||||
"protocol": "http",
|
||||
"host": [
|
||||
"localhost"
|
||||
],
|
||||
"port": "9090",
|
||||
"path": [
|
||||
"springbootapp",
|
||||
"graphql"
|
||||
]
|
||||
}
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
],
|
||||
"protocolProfileBehavior": {}
|
||||
}
|
||||
],
|
||||
"event": [
|
||||
{
|
||||
"listen": "prerequest",
|
||||
"script": {
|
||||
"id": "b54f267b-c450-4f2d-8105-2f23bab4c922",
|
||||
"type": "text/javascript",
|
||||
"exec": [
|
||||
""
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"listen": "test",
|
||||
"script": {
|
||||
"id": "00b575be-03d4-4b29-b137-733ead139638",
|
||||
"type": "text/javascript",
|
||||
"exec": [
|
||||
""
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"variable": [
|
||||
{
|
||||
"id": "20a274e5-6d51-40d6-81cb-af9eb115b21b",
|
||||
"key": "url",
|
||||
"value": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"protocolProfileBehavior": {}
|
||||
}
|
|
@ -27,11 +27,6 @@
|
|||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
|
|
|
@ -140,7 +140,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xml-apis</groupId>
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xml-apis</groupId>
|
||||
|
|
|
@ -9,3 +9,4 @@ This module contains articles about Spring RestTemplate
|
|||
- [A Custom Media Type for a Spring REST API](https://www.baeldung.com/spring-rest-custom-media-type)
|
||||
- [RestTemplate Post Request with JSON](https://www.baeldung.com/spring-resttemplate-post-json)
|
||||
- [How to Compress Requests Using the Spring RestTemplate](https://www.baeldung.com/spring-resttemplate-compressing-requests)
|
||||
- [Get list of JSON objects with Spring RestTemplate](https://www.baeldung.com/spring-resttemplate-json-list)
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>spring-ldap</module>
|
||||
<module>spring-5-security</module>
|
||||
<module>spring-5-security-cognito</module>
|
||||
<module>spring-5-security-oauth</module>
|
||||
<module>spring-security-acl</module>
|
||||
<module>spring-security-auth0</module>
|
||||
<module>spring-security-web-angular/server</module>
|
||||
|
@ -38,6 +42,8 @@
|
|||
<module>spring-security-oauth2-sso</module>
|
||||
<module>spring-security-web-thymeleaf</module>
|
||||
<module>spring-security-web-x509</module>
|
||||
<module>spring-session</module>
|
||||
<module>spring-social-login</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-2</relativePath>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
|
@ -12,7 +12,7 @@
|
|||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-2</relativePath>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
|
@ -12,7 +12,7 @@
|
|||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-2</relativePath>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue