diff --git a/geode-spring-boot-starter/src/test/java/example/app/NonBeanType.java b/geode-spring-boot-starter/src/test/java/example/app/NonBeanType.java new file mode 100644 index 00000000..8edf38d7 --- /dev/null +++ b/geode-spring-boot-starter/src/test/java/example/app/NonBeanType.java @@ -0,0 +1,27 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package example.app; + +/** + * The {@link NonBeanType} class is a non-Spring bean, placeholder reference type for classpath component scanning. + * + * @author John Blum + * @since 1.0.0 + */ +public class NonBeanType { + +} diff --git a/geode-spring-boot-starter/src/test/java/example/app/model/Author.java b/geode-spring-boot-starter/src/test/java/example/app/model/Author.java new file mode 100644 index 00000000..1f739a73 --- /dev/null +++ b/geode-spring-boot-starter/src/test/java/example/app/model/Author.java @@ -0,0 +1,52 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package example.app.model; + +import org.springframework.data.annotation.Id; +import org.springframework.data.gemfire.mapping.annotation.Region; + +import lombok.Data; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +/** + * The Author class... + * + * @author John Blum + * @since 1.0.0 + */ +@Data +@Region("Authors") +@RequiredArgsConstructor(staticName = "newAuthor") +@SuppressWarnings("unused") +public class Author { + + @Id + private Long id; + + @NonNull + private String name; + + public boolean isNew() { + return getId() == null; + } + + public Author identifiedBy(Long id) { + setId(id); + return this; + } +} diff --git a/geode-spring-boot-starter/src/test/java/example/app/model/Book.java b/geode-spring-boot-starter/src/test/java/example/app/model/Book.java new file mode 100644 index 00000000..b102085e --- /dev/null +++ b/geode-spring-boot-starter/src/test/java/example/app/model/Book.java @@ -0,0 +1,56 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package example.app.model; + +import org.springframework.data.annotation.Id; +import org.springframework.data.gemfire.mapping.annotation.Region; + +import lombok.Data; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import sun.util.resources.LocaleData; + +/** + * The Book class... + * + * @author John Blum + * @since 1.0.0 + */ +@Region("Books") +@Data +@RequiredArgsConstructor(staticName = "newBook") +public class Book { + + private Author author; + + @Id + private ISBN isbn; + + private LocaleData publishedDate; + + @NonNull + private String title; + + public boolean isNew() { + return getIsbn() == null; + } + + public Book identifiedBy(ISBN isbn) { + setIsbn(isbn); + return this; + } +} diff --git a/geode-spring-boot-starter/src/test/java/example/app/model/ISBN.java b/geode-spring-boot-starter/src/test/java/example/app/model/ISBN.java new file mode 100644 index 00000000..4107f0bd --- /dev/null +++ b/geode-spring-boot-starter/src/test/java/example/app/model/ISBN.java @@ -0,0 +1,90 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package example.app.model; + +import java.util.UUID; + +import org.apache.shiro.util.Assert; + +/** + * The {@link ISBN} class is a Abstract Data Type (ADT) modeling either a {@link Book} ISBN-10 or ISBN-13 number. + * + * @author John Blum + * @see java.lang.Comparable + * @since 1.0.0 + */ +@SuppressWarnings("unused") +public class ISBN implements Comparable { + + public static ISBN autoGenerated() { + return of(UUID.randomUUID().toString()); + } + + public static ISBN of(String number) { + + Assert.hasText(number, String.format("Number [%s] is required", number)); + + return new ISBN(number); + } + + private String number; + + private ISBN(String number) { + this.number = number; + } + + public String getNumber() { + return number; + } + + @Override + @SuppressWarnings("all") + public int compareTo(ISBN other) { + return this.getNumber().compareTo(other.getNumber()); + } + + @Override + public boolean equals(Object obj) { + + if (this == obj) { + return true; + } + + if (!(obj instanceof ISBN)) { + return false; + } + + ISBN that = (ISBN) obj; + + return this.getNumber().equals(that.getNumber()); + } + + @Override + public int hashCode() { + + int hashValue = 17; + + hashValue = 37 * hashValue + getNumber().hashCode(); + + return hashValue; + } + + @Override + public String toString() { + return getNumber(); + } +} diff --git a/geode-spring-boot-starter/src/test/java/example/app/repo/BookRepository.java b/geode-spring-boot-starter/src/test/java/example/app/repo/BookRepository.java new file mode 100644 index 00000000..57e09a2f --- /dev/null +++ b/geode-spring-boot-starter/src/test/java/example/app/repo/BookRepository.java @@ -0,0 +1,46 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package example.app.repo; + +import java.util.List; + +import org.springframework.data.repository.CrudRepository; + +import example.app.model.Author; +import example.app.model.Book; +import example.app.model.ISBN; + +/** + * The {@link BookRepository} interface is a Spring Data {@link CrudRepository} defining basic CRUD + * and simple query data access operations on {@link Book} objects to the backing data store. + * + * @author John Blum + * @see example.app.model.Book + * @see example.app.model.ISBN + * @see org.springframework.data.repository.CrudRepository + * @since 1.0.0 + */ +@SuppressWarnings("unused") +public interface BookRepository extends CrudRepository { + + List findByAuthorOrderByAuthorNameAscTitleAsc(Author author); + + Book findByIsbn(ISBN isbn); + + Book findByTitle(String title); + +} diff --git a/geode-spring-boot-starter/src/test/java/example/app/service/BookService.java b/geode-spring-boot-starter/src/test/java/example/app/service/BookService.java new file mode 100644 index 00000000..dd548648 --- /dev/null +++ b/geode-spring-boot-starter/src/test/java/example/app/service/BookService.java @@ -0,0 +1,79 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package example.app.service; + +import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException; + +import java.util.List; +import java.util.Optional; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import example.app.model.Author; +import example.app.model.Book; +import example.app.model.ISBN; +import example.app.repo.BookRepository; + +/** + * The {@link BookService} class is an application {@link Service service} class for managing {@link Book Books}. + * + * @author John Blum + * @see example.app.model.Author + * @see example.app.model.Book + * @see example.app.model.ISBN + * @see example.app.repo.BookRepository + * @see org.springframework.stereotype.Service + * @since 1.0.0 + */ +@Service +@SuppressWarnings("unused") +public class BookService { + + private final BookRepository bookRepository; + + public BookService(@Autowired(required = false) BookRepository bookRepository) { + this.bookRepository = bookRepository; + } + + protected BookRepository getBookRepository() { + + return Optional.ofNullable(this.bookRepository) + .orElseThrow(() -> newIllegalStateException("BookRepository was not properly configured")); + } + + public List findByAuthor(Author author) { + return getBookRepository().findByAuthorOrderByAuthorNameAscTitleAsc(author); + } + + public Book findByIsbn(ISBN isbn) { + return getBookRepository().findByIsbn(isbn); + } + + public Book findByTitle(String title) { + return getBookRepository().findByTitle(title); + } + + public Book stock(Book book) { + + if (book.isNew()) { + book.identifiedBy(ISBN.autoGenerated()); + } + + return getBookRepository().save(book); + } +} diff --git a/geode-spring-boot-starter/src/test/java/example/app/service/support/CachingBookService.java b/geode-spring-boot-starter/src/test/java/example/app/service/support/CachingBookService.java new file mode 100644 index 00000000..35546c48 --- /dev/null +++ b/geode-spring-boot-starter/src/test/java/example/app/service/support/CachingBookService.java @@ -0,0 +1,60 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package example.app.service.support; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import example.app.model.Book; +import example.app.model.ISBN; +import example.app.repo.BookRepository; +import example.app.service.BookService; + +/** + * The {@link CachingBookService} class is an implementation and extension of {@link BookService} + * with caching capabilities. + * + * @author John Blum + * @see example.app.model.Book + * @see example.app.service.BookService + * @see org.springframework.cache.annotation.Cacheable + * @see org.springframework.stereotype.Service + * @since 1.0.0 + */ +@Service +public class CachingBookService extends BookService { + + private final AtomicBoolean cacheMiss = new AtomicBoolean(false); + + public CachingBookService(@Autowired(required = false) BookRepository bookRepository) { + super(bookRepository); + } + + public boolean isCacheMiss() { + return this.cacheMiss.getAndSet(false); + } + + @Override + @Cacheable(value = "CachedBooks") + public Book findByTitle(String title) { + this.cacheMiss.set(true); + return Book.newBook(title).identifiedBy(ISBN.autoGenerated()); + } +}