This commit is contained in:
Jonathan Cook 2020-05-14 15:07:45 +02:00
commit a9602bbdaa
21 changed files with 687 additions and 22 deletions

56
aws-app-sync/pom.xml Normal file
View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.baeldung</groupId>
<artifactId>aws-app-sync</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>aws-app-sync</name>
<description>Spring Boot using AWS App Sync</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,32 @@
package com.baeldung.awsappsync;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import java.nio.charset.StandardCharsets;
import java.util.Map;
public class AppSyncClientHelper {
static String apiUrl = "https://m4i3b6icrrb7livfbypfspiifi.appsync-api.us-east-2.amazonaws.com";
static String apiKey = "da2-bm4rpatkkrc5jfyhvvq7itjeke";
static String API_KEY_HEADER = "x-api-key";
public static WebClient.ResponseSpec getResponseBodySpec(Map<String, Object> requestBody) {
return WebClient
.builder()
.baseUrl(apiUrl)
.defaultHeader(API_KEY_HEADER, apiKey)
.defaultHeader("Content-Type", "application/json")
.build()
.method(HttpMethod.POST)
.uri("/graphql")
.body(BodyInserters.fromValue(requestBody))
.accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML)
.acceptCharset(StandardCharsets.UTF_8)
.retrieve();
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.awsappsync;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AwsAppSyncApplication {
public static void main(String[] args) {
SpringApplication.run(AwsAppSyncApplication.class, args);
}
}

View File

@ -0,0 +1,72 @@
package com.baeldung.awsappsync;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.reactive.function.client.WebClient;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class AwsAppSyncApplicationTests {
@Test
void givenGraphQuery_whenListEvents_thenReturnAllEvents() {
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("query", "query ListEvents {"
+ " listEvents {"
+ " items {"
+ " id"
+ " name"
+ " where"
+ " when"
+ " description"
+ " }"
+ " }"
+ "}");
requestBody.put("variables", "");
requestBody.put("operationName", "ListEvents");
String bodyString = AppSyncClientHelper.getResponseBodySpec(requestBody)
.bodyToMono(String.class).block();
assertNotNull(bodyString);
assertTrue(bodyString.contains("My First Event"));
assertTrue(bodyString.contains("where"));
assertTrue(bodyString.contains("when"));
}
@Test
void givenGraphAdd_whenMutation_thenReturnIdNameDesc() {
String queryString = "mutation add {"
+ " createEvent("
+ " name:\"My added GraphQL event\""
+ " where:\"Day 2\""
+ " when:\"Saturday night\""
+ " description:\"Studying GraphQL\""
+ " ){"
+ " id"
+ " name"
+ " description"
+ " }"
+ "}";
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("query", queryString);
requestBody.put("variables", "");
requestBody.put("operationName", "add");
WebClient.ResponseSpec response = AppSyncClientHelper.getResponseBodySpec(requestBody);
String bodyString = response.bodyToMono(String.class).block();
assertNotNull(bodyString);
assertTrue(bodyString.contains("My added GraphQL event"));
assertFalse(bodyString.contains("where"));
assertFalse(bodyString.contains("when"));
}
}

35
libraries-rpc/pom.xml Normal file
View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>libraries-rpc</artifactId>
<name>libraries-rpc</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.twitter</groupId>
<artifactId>finagle-core_2.13</artifactId>
<version>${finagle.core.version}</version>
</dependency>
<dependency>
<groupId>com.twitter</groupId>
<artifactId>finagle-http_2.13</artifactId>
<version>${finagle.http.version}</version>
</dependency>
</dependencies>
<properties>
<finagle.core.version>20.4.0</finagle.core.version>
<finagle.http.version>20.4.0</finagle.http.version>
</properties>
</project>

View File

@ -0,0 +1,18 @@
package com.baeldung.rpc.finagle;
import com.twitter.finagle.Service;
import com.twitter.finagle.http.Request;
import com.twitter.finagle.http.Response;
import com.twitter.finagle.http.Status;
import com.twitter.io.Buf;
import com.twitter.io.Reader;
import com.twitter.util.Future;
public class GreetingService extends Service<Request, Response> {
@Override
public Future<Response> apply(Request request) {
String greeting = "Hello " + request.getParam("name");
Reader<Buf> reader = Reader.fromBuf(new Buf.ByteArray(greeting.getBytes(), 0, greeting.length()));
return Future.value(Response.apply(request.version(), Status.Ok(), reader));
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.rpc.finagle;
import com.twitter.finagle.Service;
import com.twitter.finagle.SimpleFilter;
import com.twitter.finagle.http.Request;
import com.twitter.finagle.http.Response;
import com.twitter.util.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogFilter extends SimpleFilter<Request, Response> {
private static final Logger logger = LoggerFactory.getLogger(LogFilter.class);
@Override
public Future<Response> apply(Request request, Service<Request, Response> service) {
logger.info("Request host:" + request.host().getOrElse(() -> ""));
logger.info("Request params:");
request.getParams().forEach(entry -> logger.info("\t" + entry.getKey() + " : " + entry.getValue()));
return service.apply(request);
}
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@ -0,0 +1,40 @@
package com.baeldung.rpc.finagle;
import com.twitter.finagle.Http;
import com.twitter.finagle.Service;
import com.twitter.finagle.http.Method;
import com.twitter.finagle.http.Request;
import com.twitter.finagle.http.Response;
import com.twitter.util.Await;
import com.twitter.util.Future;
import org.junit.Test;
import scala.runtime.BoxedUnit;
import static org.junit.Assert.assertEquals;
public class FinagleIntegrationTest {
@Test
public void givenServerAndClient_whenRequestSent_thenClientShouldReceiveResponseFromServer() throws Exception {
// given
Service serverService = new LogFilter().andThen(new GreetingService());
Http.serve(":8080", serverService);
Service<Request, Response> clientService = new LogFilter().andThen(Http.newService(":8080"));
// when
Request request = Request.apply(Method.Get(), "/?name=John");
request.host("localhost");
Future<Response> response = clientService.apply(request);
// then
Await.result(response
.onSuccess(r -> {
assertEquals("Hello John", r.getContentString());
return BoxedUnit.UNIT;
})
.onFailure(r -> {
throw new RuntimeException(r);
})
);
}
}

View File

@ -60,6 +60,16 @@
<artifactId>poi-ooxml</artifactId>
<version>${poi-ooxml.version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.20</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,48 @@
package com.baeldung.pdf;
import com.lowagie.text.DocumentException;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class PDFThymeleafExample {
public static void main(String[] args) throws IOException, DocumentException {
PDFThymeleafExample thymeleaf2Pdf = new PDFThymeleafExample();
String html = thymeleaf2Pdf.parseThymeleafTemplate();
thymeleaf2Pdf.generatePdfFromHtml(html);
}
public void generatePdfFromHtml(String html) throws IOException, DocumentException {
String outputFolder = System.getProperty("user.home") + File.separator + "thymeleaf.pdf";
OutputStream outputStream = new FileOutputStream(outputFolder);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(html);
renderer.layout();
renderer.createPDF(outputStream);
outputStream.close();
}
private String parseThymeleafTemplate() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
Context context = new Context();
context.setVariable("to", "Baeldung.com");
return templateEngine.process("thymeleaf_template", context);
}
}

View File

@ -0,0 +1,7 @@
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<h3 style="text-align: center; color: green">
<span th:text="'Welcome to ' + ${to} + '!'"></span>
</h3>
</body>
</html>

View File

@ -0,0 +1,52 @@
package com.baeldung.pdf;
import com.lowagie.text.DocumentException;
import org.junit.Test;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import static org.junit.Assert.assertTrue;
public class PDFThymeleafUnitTest {
@Test
public void givenThymeleafTemplate_whenParsedAndRenderedToPDF_thenItShouldNotBeEmpty() throws DocumentException, IOException {
String html = parseThymeleafTemplate();
ByteArrayOutputStream outputStream = generatePdfOutputStreamFromHtml(html);
assertTrue(outputStream.size() > 0);
}
private ByteArrayOutputStream generatePdfOutputStreamFromHtml(String html) throws IOException, DocumentException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(html);
renderer.layout();
renderer.createPDF(outputStream);
outputStream.close();
return outputStream;
}
private String parseThymeleafTemplate() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
Context context = new Context();
context.setVariable("to", "Baeldung.com");
return templateEngine.process("thymeleaf_template", context);
}
}

View File

@ -0,0 +1,168 @@
package com.baeldung.bsontojson;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;
import dev.morphia.annotations.Embedded;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Field;
import dev.morphia.annotations.Id;
import dev.morphia.annotations.Index;
import dev.morphia.annotations.IndexOptions;
import dev.morphia.annotations.Indexes;
import dev.morphia.annotations.Property;
import dev.morphia.annotations.Reference;
import dev.morphia.annotations.Validation;
@Entity("Books")
@Indexes({ @Index(fields = @Field("title"), options = @IndexOptions(name = "book_title")) })
@Validation("{ price : { $gt : 0 } }")
public class Book {
@Id
private String isbn;
@Property
private String title;
private String author;
@Embedded
private Publisher publisher;
@Property("price")
private double cost;
@Reference
private Set<Book> companionBooks;
@Property
private LocalDateTime publishDate;
public Book() {
}
public Book(String isbn, String title, String author, double cost, Publisher publisher) {
this.isbn = isbn;
this.title = title;
this.author = author;
this.cost = cost;
this.publisher = publisher;
this.companionBooks = new HashSet<>();
}
// Getters and setters ...
public String getIsbn() {
return isbn;
}
public Book setIsbn(String isbn) {
this.isbn = isbn;
return this;
}
public String getTitle() {
return title;
}
public Book setTitle(String title) {
this.title = title;
return this;
}
public String getAuthor() {
return author;
}
public Book setAuthor(String author) {
this.author = author;
return this;
}
public Publisher getPublisher() {
return publisher;
}
public Book setPublisher(Publisher publisher) {
this.publisher = publisher;
return this;
}
public double getCost() {
return cost;
}
public Book setCost(double cost) {
this.cost = cost;
return this;
}
public LocalDateTime getPublishDate() {
return publishDate;
}
public Book setPublishDate(LocalDateTime publishDate) {
this.publishDate = publishDate;
return this;
}
public Set<Book> getCompanionBooks() {
return companionBooks;
}
public Book addCompanionBooks(Book book) {
if (companionBooks != null)
this.companionBooks.add(book);
return this;
}
@Override
public String toString() {
return "Book [isbn=" + isbn + ", title=" + title + ", author=" + author + ", publisher=" + publisher + ", cost=" + cost + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((author == null) ? 0 : author.hashCode());
long temp;
temp = Double.doubleToLongBits(cost);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + ((isbn == null) ? 0 : isbn.hashCode());
result = prime * result + ((publisher == null) ? 0 : publisher.hashCode());
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Book other = (Book) obj;
if (author == null) {
if (other.author != null)
return false;
} else if (!author.equals(other.author))
return false;
if (Double.doubleToLongBits(cost) != Double.doubleToLongBits(other.cost))
return false;
if (isbn == null) {
if (other.isbn != null)
return false;
} else if (!isbn.equals(other.isbn))
return false;
if (publisher == null) {
if (other.publisher != null)
return false;
} else if (!publisher.equals(other.publisher))
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title))
return false;
return true;
}
}

View File

@ -0,0 +1,70 @@
package com.baeldung.bsontojson;
import org.bson.types.ObjectId;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
@Entity
public class Publisher {
@Id
private ObjectId id;
private String name;
public Publisher() {
}
public Publisher(ObjectId id, String name) {
this.id = id;
this.name = name;
}
public ObjectId getId() {
return id;
}
public void setId(ObjectId id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Catalog [id=" + id + ", name=" + name + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Publisher other = (Publisher) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}

View File

@ -2,32 +2,18 @@ package com.baeldung.bsontojson;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bson.Document;
import org.bson.json.Converter;
import org.bson.json.JsonMode;
import org.bson.json.JsonWriterSettings;
import org.bson.json.StrictJsonWriter;
import org.bson.types.ObjectId;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.AfterEach;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baeldung.morphia.domain.Book;
import com.baeldung.morphia.domain.Publisher;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
@ -42,7 +28,7 @@ public class BsonToJsonLiveTest {
@BeforeClass
public static void setUp() {
Morphia morphia = new Morphia();
morphia.mapPackage("com.baeldung.morphia");
morphia.mapPackage("com.baeldung.bsontojson");
datastore = morphia.createDatastore(new MongoClient(), DB_NAME);
datastore.ensureIndexes();
@ -72,7 +58,7 @@ public class BsonToJsonLiveTest {
}
String expectedJson = "{\"_id\": \"isbn\", " +
"\"className\": \"com.baeldung.morphia.domain.Book\", " +
"\"className\": \"com.baeldung.bsontojson.Book\", " +
"\"title\": \"title\", " +
"\"author\": \"author\", " +
"\"publisher\": {\"_id\": {\"$oid\": \"fffffffffffffffffffffffa\"}, " +
@ -100,7 +86,7 @@ public class BsonToJsonLiveTest {
}
String expectedJson = "{\"_id\": \"isbn\", " +
"\"className\": \"com.baeldung.morphia.domain.Book\", " +
"\"className\": \"com.baeldung.bsontojson.Book\", " +
"\"title\": \"title\", " +
"\"author\": \"author\", " +
"\"publisher\": {\"_id\": {\"$oid\": \"fffffffffffffffffffffffa\"}, " +
@ -127,7 +113,7 @@ public class BsonToJsonLiveTest {
}
String expectedJson = "{\"_id\": \"isbn\", " +
"\"className\": \"com.baeldung.morphia.domain.Book\", " +
"\"className\": \"com.baeldung.bsontojson.Book\", " +
"\"title\": \"title\", " +
"\"author\": \"author\", " +
"\"publisher\": {\"_id\": {\"$oid\": \"fffffffffffffffffffffffa\"}, " +

View File

@ -509,6 +509,7 @@
<module>libraries-http-2</module>
<module>libraries-io</module>
<module>libraries-primitive</module>
<module>libraries-rpc</module>
<module>libraries-security</module>
<module>libraries-server</module>
<module>libraries-testing</module>
@ -897,6 +898,7 @@
<module>atomix</module>
<module>aws</module>
<module>aws-app-sync</module>
<module>aws-lambda</module>
<module>aws-reactive</module>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"
>
<context:property-placeholder location="classpath:database.properties"/>
<bean id="dataSource" class="com.baeldung.configurationproperties.Database">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
</beans>

View File

@ -7,6 +7,7 @@
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"
>
<context:property-placeholder location="classpath:foo.properties,classpath:bar.properties,classpath:database.properties"/>
<bean id="componentInXmlUsingProperties" class="com.baeldung.properties.core.ComponentInXmlUsingProperties">

View File

@ -1,4 +1,5 @@
database.url=jdbc:postgresql:/localhost:5432/instance
jdbc.url=jdbc:postgresql:/localhost:5432
database.username=foo
database.password=bar
jdbc.url=jdbc:postgresql:/localhost:5432

View File

@ -6,7 +6,7 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
@SpringJUnitConfig(locations = "classpath:configForProperties.xml")
@SpringJUnitConfig(locations = {"classpath:configForProperties.xml", "classpath:configForDbProperties.xml"})
public class MultiplePropertiesXmlConfigIntegrationTest {
@Value("${key.something}") private String something;