From e5bf6f834dd8131aaa57396174bcf2688e5342f0 Mon Sep 17 00:00:00 2001 From: Remo Date: Tue, 15 Nov 2016 19:53:12 +0100 Subject: [PATCH] #212 Update examples (#213) first iteration of example updates - switched from QueryParams to QuerySpec - made use of QuerySpecResourceRepositoryBase for interface-based repos - Spring now has both interface and annotation-based repos - wildfly example switched to CDI-based service discover with katharsis-cdi - new Spring Config KatharsisConfigV3 with QuerySpec setup and ApplicationContext-based lookup of repositories and modules. More advanced use cases have to be added in a next iteration (katharsis-client/jpa/validation/...). --- .../internal/boot/KatharsisBoot.java | 33 ++++- .../io/katharsis/module/ModuleRegistry.java | 4 + .../QuerySpecResourceRepositoryBase.java | 3 +- .../internal/boot/KatharsisBootTest.java | 28 +++- .../repository/QuerySpecRepositoryTest.java | 1 - .../dropwizard-simple-example/README.md | 4 + .../configuration.yml | 2 +- .../simple}/DropwizardConfiguration.java | 9 +- .../simple}/DropwizardService.java | 11 +- .../simple/domain/model/Project.java | 37 ++++++ .../domain/repository/ProjectRepository.java | 46 +++++++ .../domain/model/Project.java | 29 ---- .../domain/repository/ProjectRepository.java | 56 -------- .../SpringBootSimpleExampleApplication.java | 8 +- .../ConstraintViolationExceptionMapper.java | 12 +- .../simple/domain/model/Project.java | 9 +- .../springboot/simple/domain/model/Task.java | 2 +- .../domain/repository/ProjectRepository.java | 109 +++++---------- .../repository/ProjectToTaskRepository.java | 31 +++-- .../domain/repository/TaskRepository.java | 28 ++-- .../repository/TaskToProjectRepository.java | 125 ++---------------- katharsis-examples/wildfly-example/pom.xml | 12 +- .../example/wildfly/KatharsisFeature.java | 25 ---- .../example/wildfly/WildflyApplication.java | 11 ++ .../wildfly/endpoints/UserRepository.java | 67 +++------- .../serviceLocator/WildflyServiceLocator.java | 20 --- .../spring/boot/KatharsisConfigV2.java | 4 + .../boot/KatharsisSpringBootProperties.java | 9 ++ .../spring/boot/v3/KatharsisConfigV3.java | 80 +++++++++++ .../internal/SpringServiceDiscovery.java | 34 +++++ .../SpringBootSimpleExampleApplication.java | 18 +-- ...ringBootSimpleExampleApplicationTests.java | 4 +- .../spring/domain/model/Project.java | 39 +++--- .../katharsis/spring/domain/model/Task.java | 60 ++++----- .../domain/repository/ProjectRepository.java | 66 +++++---- .../domain/repository/TaskRepository.java | 57 +++++--- .../repository/TaskToProjectRepository.java | 37 +----- 37 files changed, 568 insertions(+), 562 deletions(-) create mode 100644 katharsis-examples/dropwizard-simple-example/README.md rename katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/{dropwizardSimple => dropwizard/simple}/DropwizardConfiguration.java (65%) rename katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/{dropwizardSimple => dropwizard/simple}/DropwizardService.java (79%) create mode 100644 katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/domain/model/Project.java create mode 100644 katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/domain/repository/ProjectRepository.java delete mode 100644 katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/domain/model/Project.java delete mode 100644 katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/domain/repository/ProjectRepository.java delete mode 100644 katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/KatharsisFeature.java delete mode 100644 katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/serviceLocator/WildflyServiceLocator.java create mode 100644 katharsis-spring/src/main/java/io/katharsis/spring/boot/v3/KatharsisConfigV3.java create mode 100644 katharsis-spring/src/main/java/io/katharsis/spring/internal/SpringServiceDiscovery.java diff --git a/katharsis-core/src/main/java/io/katharsis/internal/boot/KatharsisBoot.java b/katharsis-core/src/main/java/io/katharsis/internal/boot/KatharsisBoot.java index c9b2e4df..904b6c89 100644 --- a/katharsis-core/src/main/java/io/katharsis/internal/boot/KatharsisBoot.java +++ b/katharsis-core/src/main/java/io/katharsis/internal/boot/KatharsisBoot.java @@ -77,6 +77,10 @@ public class KatharsisBoot { private ServiceDiscoveryFactory serviceDiscoveryFactory = new DefaultServiceDiscoveryFactory(); + private ServiceDiscovery serviceDiscovery; + + private ExceptionMapperRegistry exceptionMapperRegistry; + public void setObjectMapper(ObjectMapper objectMapper) { PreconditionUtil.assertNull("ObjectMapper already set", this.objectMapper); this.objectMapper = objectMapper; @@ -86,6 +90,11 @@ public void setServiceDiscoveryFactory(ServiceDiscoveryFactory factory) { this.serviceDiscoveryFactory = factory; } + public void setServiceDiscovery(ServiceDiscovery serviceDiscovery) { + this.serviceDiscovery = serviceDiscovery; + moduleRegistry.setServiceDiscovery(serviceDiscovery); + } + public void setQueryParamsBuilds(QueryParamsBuilder queryParamsBuilder) { this.queryParamsBuilder = queryParamsBuilder; this.querySpecDeserializer = null; @@ -142,10 +151,12 @@ public void boot() { } private void setupServiceDiscovery() { - // revert to reflection-based approach if no ServiceDiscovery is found - FallbackServiceDiscoveryFactory fallback = new FallbackServiceDiscoveryFactory(serviceDiscoveryFactory, serviceLocator, - propertiesProvider); - moduleRegistry.setServiceDiscovery(fallback.getInstance()); + if (serviceDiscovery == null) { + // revert to reflection-based approach if no ServiceDiscovery is found + FallbackServiceDiscoveryFactory fallback = new FallbackServiceDiscoveryFactory(serviceDiscoveryFactory, + serviceLocator, propertiesProvider); + setServiceDiscovery(fallback.getInstance()); + } } private void bootDiscovery() { @@ -158,12 +169,16 @@ private void bootDiscovery() { JsonApiModuleBuilder jsonApiModuleBuilder = new JsonApiModuleBuilder(); objectMapper.registerModule(jsonApiModuleBuilder.build(resourceRegistry, false)); - ExceptionMapperRegistry exceptionMapperRegistry = buildExceptionMapperRegistry(); + exceptionMapperRegistry = buildExceptionMapperRegistry(); requestDispatcher = createRequestDispatcher(exceptionMapperRegistry); } + public ExceptionMapperRegistry getExceptionMapperRegistry() { + return exceptionMapperRegistry; + } + private RequestDispatcher createRequestDispatcher(ExceptionMapperRegistry exceptionMapperRegistry) { TypeParser typeParser = new TypeParser(); ControllerRegistryBuilder controllerRegistryBuilder = new ControllerRegistryBuilder(resourceRegistry, typeParser, @@ -188,7 +203,9 @@ private ExceptionMapperRegistry buildExceptionMapperRegistry() { } private void setupComponents() { - ServiceDiscovery serviceDiscovery = moduleRegistry.getServiceDiscovery(); + if (resourceFieldNameTransformer == null) { + resourceFieldNameTransformer = new ResourceFieldNameTransformer(objectMapper.getSerializationConfig()); + } // not that the provided default implementation here are added last and as a consequence, // can be overriden by other modules, like the JaxrsResourceRepositoryInformationBuilder. @@ -319,4 +336,8 @@ public void setDefaultPageLimit(Long defaultPageLimit) { public ModuleRegistry getModuleRegistry() { return moduleRegistry; } + + public QuerySpecDeserializer getQuerySpecDeserializer() { + return querySpecDeserializer; + } } diff --git a/katharsis-core/src/main/java/io/katharsis/module/ModuleRegistry.java b/katharsis-core/src/main/java/io/katharsis/module/ModuleRegistry.java index 6bd94542..3fcfdbb6 100644 --- a/katharsis-core/src/main/java/io/katharsis/module/ModuleRegistry.java +++ b/katharsis-core/src/main/java/io/katharsis/module/ModuleRegistry.java @@ -29,6 +29,7 @@ import io.katharsis.resource.registry.RegistryEntry; import io.katharsis.resource.registry.ResourceLookup; import io.katharsis.resource.registry.ResourceRegistry; +import io.katharsis.resource.registry.ResourceRegistryAware; import io.katharsis.resource.registry.repository.AnnotatedRelationshipEntryBuilder; import io.katharsis.resource.registry.repository.AnnotatedResourceEntry; import io.katharsis.resource.registry.repository.DirectResponseRelationshipEntry; @@ -401,6 +402,9 @@ public ResourceInformationBuilder getResourceInformationBuilder() { else { relationshipRepositories.put((RelationshipRepositoryInformation) repositoryInformation, repository); } + if(repository instanceof ResourceRegistryAware){ + ((ResourceRegistryAware)repository).setResourceRegistry(resourceRegistry); + } } for (Map.Entry entry: resourceRepositories.entrySet()) { diff --git a/katharsis-core/src/main/java/io/katharsis/queryspec/QuerySpecResourceRepositoryBase.java b/katharsis-core/src/main/java/io/katharsis/queryspec/QuerySpecResourceRepositoryBase.java index 9114e89d..2b55bbb0 100644 --- a/katharsis-core/src/main/java/io/katharsis/queryspec/QuerySpecResourceRepositoryBase.java +++ b/katharsis-core/src/main/java/io/katharsis/queryspec/QuerySpecResourceRepositoryBase.java @@ -4,6 +4,7 @@ import java.util.Arrays; import java.util.Iterator; +import io.katharsis.resource.exception.ResourceNotFoundException; import io.katharsis.resource.registry.RegistryEntry; import io.katharsis.resource.registry.ResourceRegistry; import io.katharsis.resource.registry.ResourceRegistryAware; @@ -55,7 +56,7 @@ public T findOne(I id, QuerySpec querySpec) { return resource; } else { - return null; + throw new ResourceNotFoundException("resource not found"); } } diff --git a/katharsis-core/src/test/java/io/katharsis/internal/boot/KatharsisBootTest.java b/katharsis-core/src/test/java/io/katharsis/internal/boot/KatharsisBootTest.java index 8290c0dc..3641a096 100644 --- a/katharsis-core/src/test/java/io/katharsis/internal/boot/KatharsisBootTest.java +++ b/katharsis-core/src/test/java/io/katharsis/internal/boot/KatharsisBootTest.java @@ -5,6 +5,7 @@ import org.junit.Assert; import org.junit.Test; +import org.mockito.Mockito; import com.fasterxml.jackson.databind.ObjectMapper; @@ -14,6 +15,7 @@ import io.katharsis.module.ServiceDiscovery; import io.katharsis.module.SimpleModule; import io.katharsis.queryParams.QueryParams; +import io.katharsis.queryspec.QuerySpecDeserializer; import io.katharsis.queryspec.internal.QueryParamsAdapter; import io.katharsis.resource.field.ResourceFieldNameTransformer; import io.katharsis.resource.mock.models.Task; @@ -26,7 +28,31 @@ public class KatharsisBootTest { @Test - public void test() { + public void setObjectMapper() { + KatharsisBoot boot = new KatharsisBoot(); + ObjectMapper mapper = new ObjectMapper(); + boot.setObjectMapper(mapper); + Assert.assertSame(mapper, boot.getObjectMapper()); + } + + @Test + public void setServiceDiscovery() { + KatharsisBoot boot = new KatharsisBoot(); + ServiceDiscovery serviceDiscovery = Mockito.mock(ServiceDiscovery.class); + boot.setServiceDiscovery(serviceDiscovery); + Assert.assertSame(serviceDiscovery, boot.getServiceDiscovery()); + } + + @Test + public void setQuerySpecDeserializer() { + KatharsisBoot boot = new KatharsisBoot(); + QuerySpecDeserializer deserializer = Mockito.mock(QuerySpecDeserializer.class); + boot.setQuerySpecDeserializer(deserializer); + Assert.assertSame(deserializer, boot.getQuerySpecDeserializer()); + } + + @Test + public void boot() { KatharsisBoot boot = new KatharsisBoot(); ObjectMapper objectMapper = boot.getObjectMapper(); ResourceFieldNameTransformer resourceFieldNameTransformer = new ResourceFieldNameTransformer( diff --git a/katharsis-core/src/test/java/io/katharsis/queryspec/repository/QuerySpecRepositoryTest.java b/katharsis-core/src/test/java/io/katharsis/queryspec/repository/QuerySpecRepositoryTest.java index b4b41f1c..6bc36460 100644 --- a/katharsis-core/src/test/java/io/katharsis/queryspec/repository/QuerySpecRepositoryTest.java +++ b/katharsis-core/src/test/java/io/katharsis/queryspec/repository/QuerySpecRepositoryTest.java @@ -145,7 +145,6 @@ private void checkCrud(QueryAdapter queryAdapter) { taskAdapter.delete(task.getId(), queryAdapter); tasks = (List) taskAdapter.findAll(queryAdapter).getEntity(); Assert.assertEquals(0, tasks.size()); - Assert.assertNull(taskAdapter.findOne(2L, queryAdapter).getEntity()); tasks = (List) taskAdapter.findAll(Arrays.asList(2L), queryAdapter).getEntity(); Assert.assertEquals(0, tasks.size()); diff --git a/katharsis-examples/dropwizard-simple-example/README.md b/katharsis-examples/dropwizard-simple-example/README.md new file mode 100644 index 00000000..b1ff1c53 --- /dev/null +++ b/katharsis-examples/dropwizard-simple-example/README.md @@ -0,0 +1,4 @@ + +In order to run this example do: +* run the dropwizard application with the ```server``` parameter +* The service will be available at: http://localhost:8080/projects diff --git a/katharsis-examples/dropwizard-simple-example/configuration.yml b/katharsis-examples/dropwizard-simple-example/configuration.yml index 37e1b969..3d9fd80f 100644 --- a/katharsis-examples/dropwizard-simple-example/configuration.yml +++ b/katharsis-examples/dropwizard-simple-example/configuration.yml @@ -1,5 +1,5 @@ katharsis: - searchPackage: io.katharsis.example.dropwizardSimple.domain + searchPackage: io.katharsis.example.dropwizard.simple.domain server: type: simple diff --git a/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/DropwizardConfiguration.java b/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/DropwizardConfiguration.java similarity index 65% rename from katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/DropwizardConfiguration.java rename to katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/DropwizardConfiguration.java index 87e20fae..c8b9005b 100644 --- a/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/DropwizardConfiguration.java +++ b/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/DropwizardConfiguration.java @@ -1,11 +1,10 @@ -package io.katharsis.example.dropwizardSimple; - -import io.dropwizard.Configuration; -import io.katharsis.example.dropwizardSimple.domain.model.Project; +package io.katharsis.example.dropwizard.simple; import javax.validation.Valid; import javax.validation.constraints.NotNull; +import io.dropwizard.Configuration; + public class DropwizardConfiguration extends Configuration { @Valid @@ -16,6 +15,6 @@ public class KatharsisConfiguration { @Valid @NotNull - public String searchPackage = Project.class.getPackage().getName(); + public String searchPackage = "io.katharsis.example.dropwizard.simple.domain"; } } diff --git a/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/DropwizardService.java b/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/DropwizardService.java similarity index 79% rename from katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/DropwizardService.java rename to katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/DropwizardService.java index 21711555..c791a8eb 100644 --- a/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/DropwizardService.java +++ b/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/DropwizardService.java @@ -1,14 +1,13 @@ -package io.katharsis.example.dropwizardSimple; +package io.katharsis.example.dropwizard.simple; + +import static io.katharsis.rs.KatharsisProperties.RESOURCE_SEARCH_PACKAGE; import io.dropwizard.Application; import io.dropwizard.setup.Environment; import io.katharsis.locator.SampleJsonServiceLocator; -import io.katharsis.queryParams.DefaultQueryParamsParser; -import io.katharsis.queryParams.QueryParamsBuilder; +import io.katharsis.queryspec.DefaultQuerySpecDeserializer; import io.katharsis.rs.KatharsisFeature; -import static io.katharsis.rs.KatharsisProperties.RESOURCE_SEARCH_PACKAGE; - public class DropwizardService extends Application { @Override @@ -18,7 +17,7 @@ public void run(DropwizardConfiguration dropwizardConfiguration, Environment env environment.jersey().property(RESOURCE_SEARCH_PACKAGE, dropwizardConfiguration.katharsis.searchPackage); KatharsisFeature katharsisFeature = new KatharsisFeature(environment.getObjectMapper(), - new QueryParamsBuilder(new DefaultQueryParamsParser()), + new DefaultQuerySpecDeserializer(), new SampleJsonServiceLocator()); environment.jersey().register(katharsisFeature); } diff --git a/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/domain/model/Project.java b/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/domain/model/Project.java new file mode 100644 index 00000000..2b35fe4b --- /dev/null +++ b/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/domain/model/Project.java @@ -0,0 +1,37 @@ +package io.katharsis.example.dropwizard.simple.domain.model; + +import io.katharsis.resource.annotations.JsonApiId; +import io.katharsis.resource.annotations.JsonApiResource; + +@JsonApiResource(type = "projects") +public class Project { + + @JsonApiId + private Long id; + + private String name; + + public Project() { + } + + public Project(long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/domain/repository/ProjectRepository.java b/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/domain/repository/ProjectRepository.java new file mode 100644 index 00000000..7a6e26ce --- /dev/null +++ b/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizard/simple/domain/repository/ProjectRepository.java @@ -0,0 +1,46 @@ +package io.katharsis.example.dropwizard.simple.domain.repository; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import io.katharsis.example.dropwizard.simple.domain.model.Project; +import io.katharsis.queryspec.QuerySpec; +import io.katharsis.queryspec.QuerySpecResourceRepositoryBase; + +public class ProjectRepository extends QuerySpecResourceRepositoryBase { + + private static final AtomicLong ID_GENERATOR = new AtomicLong(124); + + private Map projects = new HashMap<>(); + + public ProjectRepository() { + super(Project.class); + List interests = new ArrayList<>(); + interests.add("coding"); + interests.add("art"); + save(new Project(123L, "Great Project")); + } + + @Override + public synchronized void delete(Long id) { + projects.remove(id); + } + + @Override + public synchronized S save(S project) { + if (project.getId() == null) { + project.setId(ID_GENERATOR.getAndIncrement()); + } + projects.put(project.getId(), project); + return project; + } + + @Override + public synchronized List findAll(QuerySpec querySpec) { + return querySpec.apply(projects.values()); + } + +} diff --git a/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/domain/model/Project.java b/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/domain/model/Project.java deleted file mode 100644 index c54428c1..00000000 --- a/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/domain/model/Project.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.katharsis.example.dropwizardSimple.domain.model; - -import io.katharsis.resource.annotations.JsonApiId; -import io.katharsis.resource.annotations.JsonApiResource; - -@JsonApiResource(type = "projects") -public class Project { - - @JsonApiId - private Long id; - - private String name; - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/domain/repository/ProjectRepository.java b/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/domain/repository/ProjectRepository.java deleted file mode 100644 index b4ca5a6a..00000000 --- a/katharsis-examples/dropwizard-simple-example/src/main/java/io/katharsis/example/dropwizardSimple/domain/repository/ProjectRepository.java +++ /dev/null @@ -1,56 +0,0 @@ -package io.katharsis.example.dropwizardSimple.domain.repository; - -import com.google.common.collect.Iterables; -import io.katharsis.example.dropwizardSimple.domain.model.Project; -import io.katharsis.queryParams.QueryParams; -import io.katharsis.repository.ResourceRepository; -import io.katharsis.resource.exception.ResourceNotFoundException; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -public class ProjectRepository implements ResourceRepository { - - private static final Map REPOSITORY = new ConcurrentHashMap<>(); - private static final AtomicLong ID_GENERATOR = new AtomicLong(1); - - public S save(S entity) { - if (entity.getId() == null) { - entity.setId(ID_GENERATOR.getAndIncrement()); - } - REPOSITORY.put(entity.getId(), entity); - return entity; - } - - public Project findOne(Long id, QueryParams requestParams) { - Project project = REPOSITORY.get(id); - if (project == null) { - throw new ResourceNotFoundException("Project not found"); - } - return project; - } - - @Override - public Iterable findAll(QueryParams requestParams) { - return REPOSITORY.values(); - } - - @Override - public Iterable findAll(Iterable iterable, QueryParams requestParams) { - Set> entries = REPOSITORY.entrySet(); - Map map = new HashMap<>(); - for (Map.Entry entry: entries) { - if (Iterables.contains(iterable, entry.getKey())) { - map.put(entry.getKey(), entry. getValue()); - } - } - return map.values(); - } - - public void delete(Long id) { - REPOSITORY.remove(id); - } -} \ No newline at end of file diff --git a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/SpringBootSimpleExampleApplication.java b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/SpringBootSimpleExampleApplication.java index 58fe7ef1..b5f010a4 100644 --- a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/SpringBootSimpleExampleApplication.java +++ b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/SpringBootSimpleExampleApplication.java @@ -1,8 +1,5 @@ package io.katharsis.example.springboot.simple; -import io.katharsis.resource.registry.ResourceRegistry; -import io.katharsis.spring.boot.KatharsisConfigV2; - import java.util.HashMap; import java.util.Map; @@ -14,10 +11,13 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import io.katharsis.resource.registry.ResourceRegistry; +import io.katharsis.spring.boot.v3.KatharsisConfigV3; + @Configuration @RestController @SpringBootApplication -@Import(KatharsisConfigV2.class) +@Import(KatharsisConfigV3.class) public class SpringBootSimpleExampleApplication { @Autowired diff --git a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/mapper/ConstraintViolationExceptionMapper.java b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/mapper/ConstraintViolationExceptionMapper.java index e9de45c0..811cb2c9 100644 --- a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/mapper/ConstraintViolationExceptionMapper.java +++ b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/mapper/ConstraintViolationExceptionMapper.java @@ -1,10 +1,6 @@ package io.katharsis.example.springboot.simple.domain.mapper; import static io.katharsis.response.HttpStatus.CONFLICT_409; -import io.katharsis.errorhandling.ErrorData; -import io.katharsis.errorhandling.ErrorResponse; -import io.katharsis.errorhandling.mapper.ExceptionMapperProvider; -import io.katharsis.errorhandling.mapper.JsonApiExceptionMapper; import java.util.ArrayList; import java.util.Iterator; @@ -14,7 +10,13 @@ import javax.validation.ConstraintViolationException; import javax.validation.Path.Node; -@ExceptionMapperProvider +import org.springframework.stereotype.Component; + +import io.katharsis.errorhandling.ErrorData; +import io.katharsis.errorhandling.ErrorResponse; +import io.katharsis.errorhandling.mapper.JsonApiExceptionMapper; + +@Component public class ConstraintViolationExceptionMapper implements JsonApiExceptionMapper { @Override diff --git a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/model/Project.java b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/model/Project.java index f1663e90..53bc1adc 100644 --- a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/model/Project.java +++ b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/model/Project.java @@ -33,14 +33,19 @@ public class Project { @JsonProperty private String name; - @JsonApiToMany + @JsonApiToMany(opposite="project") private List tasks = new ArrayList<>(); public Project(Long id) { this.id = id; } - public Long getId() { + public Project(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { return id; } diff --git a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/model/Task.java b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/model/Task.java index c218941b..1bdcbfef 100644 --- a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/model/Task.java +++ b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/model/Task.java @@ -41,7 +41,7 @@ public class Task { @JsonIgnore private Long projectId; - @JsonApiToOne + @JsonApiToOne(opposite="tasks") @JsonApiIncludeByDefault private Project project; diff --git a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/ProjectRepository.java b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/ProjectRepository.java index e51dfae6..90d20092 100644 --- a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/ProjectRepository.java +++ b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/ProjectRepository.java @@ -16,94 +16,53 @@ */ package io.katharsis.example.springboot.simple.domain.repository; -import io.katharsis.example.springboot.simple.domain.model.Project; -import io.katharsis.example.springboot.simple.domain.model.Task; -import io.katharsis.queryParams.QueryParams; -import io.katharsis.repository.annotations.JsonApiDelete; -import io.katharsis.repository.annotations.JsonApiFindAll; -import io.katharsis.repository.annotations.JsonApiFindAllWithIds; -import io.katharsis.repository.annotations.JsonApiFindOne; -import io.katharsis.repository.annotations.JsonApiResourceRepository; -import io.katharsis.repository.annotations.JsonApiSave; -import io.katharsis.resource.exception.ResourceNotFoundException; - import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; -import com.google.common.collect.Iterables; +import io.katharsis.example.springboot.simple.domain.model.Project; +import io.katharsis.queryspec.QuerySpec; +import io.katharsis.queryspec.QuerySpecResourceRepositoryBase; -@JsonApiResourceRepository(Project.class) +/** + * QuerySpecResourceRepositoryBase-based example with the base class providing some base functionality. + */ @Component -public class ProjectRepository { - private static final Map REPOSITORY = new ConcurrentHashMap<>(); - private static final AtomicLong ID_GENERATOR = new AtomicLong(124); - private final TaskRepository taskRepository; +public class ProjectRepository extends QuerySpecResourceRepositoryBase { + + private static final AtomicLong ID_GENERATOR = new AtomicLong(124); - @Autowired @Lazy - public ProjectRepository(TaskRepository taskRepository) { - this.taskRepository = taskRepository; - Project project = new Project(123L); - project.setName("Great Project"); - save(project); - } + private Map projects = new HashMap<>(); - @JsonApiSave - public S save(S entity) { - if (entity.getId() == null) { - entity.setId(ID_GENERATOR.getAndIncrement()); - } - REPOSITORY.put(entity.getId(), entity); - return entity; - } + public ProjectRepository() { + super(Project.class); + List interests = new ArrayList<>(); + interests.add("coding"); + interests.add("art"); + save(new Project(123L, "Great Project")); + } - @JsonApiFindOne - public Project findOne(Long projectId, QueryParams requestParams) { - if (projectId == null) { - return null; - } - Project project = REPOSITORY.get(projectId); - if (project == null) { - throw new ResourceNotFoundException("Project not found!"); - } - if (project.getTasks().isEmpty()) { - Iterable tasks = taskRepository.findAll(null); - for (Task task: tasks) { - if (task.getProjectId().equals(project.getId())) { - project.getTasks().add(task); - } - } - save(project); - } - return project; - } + @Override + public synchronized void delete(Long id) { + projects.remove(id); + } - @JsonApiFindAll - public Iterable findAll(QueryParams requestParams) { - return REPOSITORY.values(); - } + @Override + public synchronized S save(S project) { + if (project.getId() == null) { + project.setId(ID_GENERATOR.getAndIncrement()); + } + projects.put(project.getId(), project); + return project; + } - @JsonApiFindAllWithIds - public Iterable findAll(Iterable projectIds, QueryParams requestParams) { - List foundProjects = new ArrayList<>(); - for (Map.Entry entry: REPOSITORY.entrySet()) { - for (Long projectId: projectIds) { - if (projectId.equals(entry.getKey())) { - foundProjects.add(entry.getValue()); - } - } - } - return foundProjects; - } + @Override + public synchronized List findAll(QuerySpec querySpec) { + return querySpec.apply(projects.values()); + } - @JsonApiDelete - public void delete(Long projectId) { - REPOSITORY.remove(projectId); - } } diff --git a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/ProjectToTaskRepository.java b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/ProjectToTaskRepository.java index 008c5139..38e38dee 100644 --- a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/ProjectToTaskRepository.java +++ b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/ProjectToTaskRepository.java @@ -16,19 +16,28 @@ */ package io.katharsis.example.springboot.simple.domain.repository; -import io.katharsis.example.springboot.simple.domain.model.Project; -import io.katharsis.example.springboot.simple.domain.model.Task; -import io.katharsis.queryParams.QueryParams; -import io.katharsis.repository.RelationshipRepository; -import io.katharsis.repository.annotations.*; -import io.katharsis.utils.PropertyUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import io.katharsis.example.springboot.simple.domain.model.Project; +import io.katharsis.example.springboot.simple.domain.model.Task; +import io.katharsis.queryspec.QuerySpec; +import io.katharsis.repository.annotations.JsonApiAddRelations; +import io.katharsis.repository.annotations.JsonApiFindManyTargets; +import io.katharsis.repository.annotations.JsonApiFindOneTarget; +import io.katharsis.repository.annotations.JsonApiRelationshipRepository; +import io.katharsis.repository.annotations.JsonApiRemoveRelations; +import io.katharsis.repository.annotations.JsonApiSetRelation; +import io.katharsis.repository.annotations.JsonApiSetRelations; +import io.katharsis.utils.PropertyUtils; + +/** + * Manually-written, annotation-based relationship repository example. + */ @JsonApiRelationshipRepository(source = Project.class, target = Task.class) @Component public class ProjectToTaskRepository { @@ -118,7 +127,7 @@ public void removeRelations(Project project, Iterable taskIds, String fiel } @JsonApiFindOneTarget - public Task findOneTarget(Long projectId, String fieldName, QueryParams requestParams) { + public Task findOneTarget(Long projectId, String fieldName, QuerySpec requestParams) { Project project = projectRepository.findOne(projectId, requestParams); try { return (Task) PropertyUtils.getProperty(project, fieldName); @@ -128,7 +137,7 @@ public Task findOneTarget(Long projectId, String fieldName, QueryParams requestP } @JsonApiFindManyTargets - public Iterable findManyTargets(Long projectId, String fieldName, QueryParams requestParams) { + public Iterable findManyTargets(Long projectId, String fieldName, QuerySpec requestParams) { Project project = projectRepository.findOne(projectId, requestParams); try { return (Iterable) PropertyUtils.getProperty(project, fieldName); diff --git a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/TaskRepository.java b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/TaskRepository.java index 861e3082..da37054c 100644 --- a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/TaskRepository.java +++ b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/TaskRepository.java @@ -16,16 +16,6 @@ */ package io.katharsis.example.springboot.simple.domain.repository; -import io.katharsis.example.springboot.simple.domain.model.Task; -import io.katharsis.queryParams.QueryParams; -import io.katharsis.repository.annotations.JsonApiDelete; -import io.katharsis.repository.annotations.JsonApiFindAll; -import io.katharsis.repository.annotations.JsonApiFindAllWithIds; -import io.katharsis.repository.annotations.JsonApiFindOne; -import io.katharsis.repository.annotations.JsonApiResourceRepository; -import io.katharsis.repository.annotations.JsonApiSave; -import io.katharsis.resource.exception.ResourceNotFoundException; - import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -39,7 +29,15 @@ import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; -import com.google.common.collect.Iterables; +import io.katharsis.example.springboot.simple.domain.model.Task; +import io.katharsis.queryspec.QuerySpec; +import io.katharsis.repository.annotations.JsonApiDelete; +import io.katharsis.repository.annotations.JsonApiFindAll; +import io.katharsis.repository.annotations.JsonApiFindAllWithIds; +import io.katharsis.repository.annotations.JsonApiFindOne; +import io.katharsis.repository.annotations.JsonApiResourceRepository; +import io.katharsis.repository.annotations.JsonApiSave; +import io.katharsis.resource.exception.ResourceNotFoundException; @Component @JsonApiResourceRepository(Task.class) @@ -74,24 +72,24 @@ public S save(@Valid S entity) { } @JsonApiFindOne - public Task findOne(Long taskId, QueryParams requestParams) { + public Task findOne(Long taskId, QuerySpec requestParams) { Task task = REPOSITORY.get(taskId); if (task == null) { throw new ResourceNotFoundException("Project not found!"); } if (task.getProject() == null) { - task.setProject(projectRepository.findOne(task.getProjectId(), null)); + task.setProject(projectRepository.findOne(task.getProjectId(), new QuerySpec(Task.class))); } return task; } @JsonApiFindAll - public Iterable findAll(QueryParams requestParams) { + public Iterable findAll(QuerySpec requestParams) { return REPOSITORY.values(); } @JsonApiFindAllWithIds - public Iterable findAll(Iterable taskIds, QueryParams requestParams) { + public Iterable findAll(Iterable taskIds, QuerySpec requestParams) { List foundTasks = new ArrayList<>(); for (Map.Entry entry: REPOSITORY.entrySet()) { for (Long id: taskIds) { diff --git a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/TaskToProjectRepository.java b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/TaskToProjectRepository.java index 04e52f82..ec43f7f2 100644 --- a/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/TaskToProjectRepository.java +++ b/katharsis-examples/spring-boot-simple-example/src/main/java/io/katharsis/example/springboot/simple/domain/repository/TaskToProjectRepository.java @@ -16,124 +16,19 @@ */ package io.katharsis.example.springboot.simple.domain.repository; -import io.katharsis.example.springboot.simple.domain.model.Project; -import io.katharsis.example.springboot.simple.domain.model.Task; -import io.katharsis.queryParams.QueryParams; -import io.katharsis.repository.RelationshipRepository; -import io.katharsis.repository.annotations.*; -import io.katharsis.utils.PropertyUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; +import io.katharsis.example.springboot.simple.domain.model.Project; +import io.katharsis.example.springboot.simple.domain.model.Task; +import io.katharsis.queryspec.QuerySpecRelationshipRepositoryBase; -@JsonApiRelationshipRepository(source = Task.class, target = Project.class) +/** + * Example based on QuerySpecRelationshipRepositoryBase which by default accesses the repositories on both sides. + */ @Component -public class TaskToProjectRepository { - - private final TaskRepository taskRepository; - private final ProjectRepository projectRepository; - - @Autowired - public TaskToProjectRepository(TaskRepository taskRepository, ProjectRepository projectRepository) { - this.taskRepository = taskRepository; - this.projectRepository = projectRepository; - } - - @JsonApiSetRelation - public void setRelation(Task task, Long projectId, String fieldName) { - Project project = projectRepository.findOne(projectId, null); - try { - PropertyUtils.setProperty(task, fieldName, project); - } catch (Exception e) { - throw new RuntimeException(e); - } - taskRepository.save(task); - } - - @JsonApiSetRelations - public void setRelations(Task task, Iterable projectIds, String fieldName) { - Iterable projects = projectRepository.findAll(projectIds, null); - try { - PropertyUtils.setProperty(task, fieldName, projects); - } catch (Exception e) { - throw new RuntimeException(e); - } - taskRepository.save(task); - } - - @JsonApiAddRelations - public void addRelations(Task task, Iterable projectIds, String fieldName) { - List newProjectList = new LinkedList<>(); - Iterable projectsToAdd = projectRepository.findAll(projectIds, null); - for (Project project: projectsToAdd) { - newProjectList.add(project); - } - try { - if (PropertyUtils.getProperty(task, fieldName) != null) { - Iterable projects = (Iterable) PropertyUtils.getProperty(task, fieldName); - for (Project project: projects) { - newProjectList.add(project); - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - try { - PropertyUtils.setProperty(task, fieldName, newProjectList); - } catch (Exception e) { - throw new RuntimeException(e); - } - taskRepository.save(task); - - } - - @JsonApiRemoveRelations - public void removeRelations(Task task, Iterable projectIds, String fieldName) { - try { - if (PropertyUtils.getProperty(task, fieldName) != null) { - Iterable projects = (Iterable) PropertyUtils.getProperty(task, fieldName); - Iterator iterator = projects.iterator(); - while (iterator.hasNext()) { - for (Long projectIdToRemove : projectIds) { - if (iterator.next().getId().equals(projectIdToRemove)) { - iterator.remove(); - break; - } - } - } - List newProjectList = new LinkedList<>(); - for (Project project: projects) { - newProjectList.add(project); - } - - PropertyUtils.setProperty(task, fieldName, newProjectList); - taskRepository.save(task); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @JsonApiFindOneTarget - public Project findOneTarget(Long taskId, String fieldName, QueryParams requestParams) { - Task task = taskRepository.findOne(taskId, requestParams); - try { - return (Project) PropertyUtils.getProperty(task, fieldName); - } catch (Exception e) { - throw new RuntimeException(e); - } - } +public class TaskToProjectRepository extends QuerySpecRelationshipRepositoryBase { - @JsonApiFindManyTargets - public Iterable findManyTargets(Long taskId, String fieldName, QueryParams requestParams) { - Task task = taskRepository.findOne(taskId, requestParams); - try { - return (Iterable) PropertyUtils.getProperty(task, fieldName); - } catch (Exception e) { - throw new RuntimeException(e); - } - } + public TaskToProjectRepository() { + super(Task.class, Project.class); + } } diff --git a/katharsis-examples/wildfly-example/pom.xml b/katharsis-examples/wildfly-example/pom.xml index bccd331f..573e5707 100644 --- a/katharsis-examples/wildfly-example/pom.xml +++ b/katharsis-examples/wildfly-example/pom.xml @@ -55,13 +55,13 @@ - - - - com.google.guava - guava - 19.0 + + + io.katharsis + katharsis-cdi + ${project.version} + diff --git a/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/KatharsisFeature.java b/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/KatharsisFeature.java deleted file mode 100644 index 2d6f6f3a..00000000 --- a/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/KatharsisFeature.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.katharsis.example.wildfly; - -import com.fasterxml.jackson.databind.ObjectMapper; -import io.katharsis.example.wildfly.serviceLocator.WildflyServiceLocator; -import io.katharsis.queryParams.DefaultQueryParamsParser; -import io.katharsis.queryParams.QueryParamsBuilder; -import io.katharsis.rs.KatharsisProperties; - -import javax.ws.rs.core.Feature; -import javax.ws.rs.core.FeatureContext; -import javax.ws.rs.ext.Provider; - -@Provider -public class KatharsisFeature implements Feature { - public static final String APPLICATION_URL = "http://localhost:8080/wildfly-example"; - - @Override - public boolean configure(FeatureContext featureContext) { - featureContext.property(KatharsisProperties.RESOURCE_SEARCH_PACKAGE, "io.katharsis.example.wildfly") - .property(KatharsisProperties.RESOURCE_DEFAULT_DOMAIN, APPLICATION_URL) - .register(new io.katharsis.rs.KatharsisFeature(new ObjectMapper(), new QueryParamsBuilder(new DefaultQueryParamsParser()), new WildflyServiceLocator())); - - return true; - } -} diff --git a/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/WildflyApplication.java b/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/WildflyApplication.java index 3620784e..fb481959 100644 --- a/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/WildflyApplication.java +++ b/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/WildflyApplication.java @@ -1,9 +1,20 @@ package io.katharsis.example.wildfly; +import java.util.HashSet; +import java.util.Set; + import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; +import io.katharsis.rs.KatharsisFeature; + @ApplicationPath("/") public class WildflyApplication extends Application { + @Override + public Set> getClasses() { + Set> set = new HashSet<>(); + set.add(KatharsisFeature.class); + return set; + } } diff --git a/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/endpoints/UserRepository.java b/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/endpoints/UserRepository.java index 78bd3404..e558d0c3 100644 --- a/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/endpoints/UserRepository.java +++ b/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/endpoints/UserRepository.java @@ -1,62 +1,32 @@ package io.katharsis.example.wildfly.endpoints; -import io.katharsis.example.wildfly.model.User; -import io.katharsis.queryParams.QueryParams; -import io.katharsis.repository.ResourceRepository; -import io.katharsis.resource.exception.ResourceNotFoundException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; -import java.util.*; +import io.katharsis.example.wildfly.model.User; +import io.katharsis.queryspec.QuerySpec; +import io.katharsis.queryspec.QuerySpecResourceRepositoryBase; -public class UserRepository implements ResourceRepository { +public class UserRepository extends QuerySpecResourceRepositoryBase { - private Set users = new LinkedHashSet<>(); + private Map users = new HashMap<>(); public UserRepository() { + super(User.class); List interests = new ArrayList<>(); interests.add("coding"); interests.add("art"); - users.add(new User(UUID.randomUUID().toString(), "grogdj@gmail.com", "grogdj", "grogj", "dj", interests)); - users.add(new User(UUID.randomUUID().toString(), "bot@gmail.com", "bot", "bot", "harry", interests)); - users.add(new User(UUID.randomUUID().toString(), "evilbot@gmail.com", "evilbot", "bot", "john", interests)); - } - - @Override - public synchronized User findOne(String id, QueryParams requestParams) { - for (User user : users) { - if (user.getId().equals(id)) { - return user; - } - } - throw new ResourceNotFoundException("users/" + id); - } - - @Override - public synchronized Iterable findAll(QueryParams requestParams) { - return users; - } - - @Override - public synchronized Iterable findAll(Iterable ids, QueryParams requestParams) { - List foundUsers = new ArrayList<>(); - for (User user : users) { - for (String id: ids) { - if (id.equals(user.getId())) { - foundUsers.add(user); - } - } - } - return foundUsers; + save(new User(UUID.randomUUID().toString(), "grogdj@gmail.com", "grogdj", "grogj", "dj", interests)); + save(new User(UUID.randomUUID().toString(), "bot@gmail.com", "bot", "bot", "harry", interests)); + save(new User(UUID.randomUUID().toString(), "evilbot@gmail.com", "evilbot", "bot", "john", interests)); } @Override public synchronized void delete(String id) { - Iterator usersIterator = users.iterator(); - - while (usersIterator.hasNext()) { - if (usersIterator.next().getId().equals(id)) { - usersIterator.remove(); - } - } + users.remove(id); } @Override @@ -64,7 +34,12 @@ public synchronized S save(S user) { if (user.getId() == null) { user.setId(UUID.randomUUID().toString()); } - users.add(user); + users.put(user.getId(), user); return user; } + + @Override + public synchronized List findAll(QuerySpec querySpec) { + return querySpec.apply(users.values()); + } } diff --git a/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/serviceLocator/WildflyServiceLocator.java b/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/serviceLocator/WildflyServiceLocator.java deleted file mode 100644 index 942330bc..00000000 --- a/katharsis-examples/wildfly-example/src/main/java/io/katharsis/example/wildfly/serviceLocator/WildflyServiceLocator.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.katharsis.example.wildfly.serviceLocator; - -import io.katharsis.locator.JsonServiceLocator; - -import javax.enterprise.context.spi.CreationalContext; -import javax.enterprise.inject.spi.Bean; -import javax.enterprise.inject.spi.BeanManager; -import javax.enterprise.inject.spi.CDI; - -public class WildflyServiceLocator implements JsonServiceLocator { - - @Override - public T getInstance(Class aClass) { - BeanManager beanManager = CDI.current().getBeanManager(); - Bean bean = beanManager.resolve(beanManager.getBeans(aClass)); - CreationalContext creationalContext = beanManager.createCreationalContext(bean); - - return (T) beanManager.getReference(bean, aClass, creationalContext); - } -} diff --git a/katharsis-spring/src/main/java/io/katharsis/spring/boot/KatharsisConfigV2.java b/katharsis-spring/src/main/java/io/katharsis/spring/boot/KatharsisConfigV2.java index 4a2ab488..f9398e88 100644 --- a/katharsis-spring/src/main/java/io/katharsis/spring/boot/KatharsisConfigV2.java +++ b/katharsis-spring/src/main/java/io/katharsis/spring/boot/KatharsisConfigV2.java @@ -25,6 +25,10 @@ ModuleConfiguration.class, KatharsisRegistryConfiguration.class}) @EnableConfigurationProperties(KatharsisSpringBootProperties.class) +/** + * @Deprecated in favor of new version with JSON API compliance, QuerySpec and module support. + */ +@Deprecated public class KatharsisConfigV2 { @Autowired diff --git a/katharsis-spring/src/main/java/io/katharsis/spring/boot/KatharsisSpringBootProperties.java b/katharsis-spring/src/main/java/io/katharsis/spring/boot/KatharsisSpringBootProperties.java index 0d597025..6f7baacd 100644 --- a/katharsis-spring/src/main/java/io/katharsis/spring/boot/KatharsisSpringBootProperties.java +++ b/katharsis-spring/src/main/java/io/katharsis/spring/boot/KatharsisSpringBootProperties.java @@ -7,6 +7,7 @@ public class KatharsisSpringBootProperties { private String resourcePackage; private String domainName; private String pathPrefix; + private Long defaultPageLimit; public String getResourcePackage() { return resourcePackage; @@ -31,4 +32,12 @@ public String getPathPrefix() { public void setPathPrefix(String pathPrefix) { this.pathPrefix = pathPrefix; } + + public Long getDefaultPageLimit() { + return defaultPageLimit; + } + + public void setDefaultPageLimit(Long defaultPageLimit) { + this.defaultPageLimit = defaultPageLimit; + } } diff --git a/katharsis-spring/src/main/java/io/katharsis/spring/boot/v3/KatharsisConfigV3.java b/katharsis-spring/src/main/java/io/katharsis/spring/boot/v3/KatharsisConfigV3.java new file mode 100644 index 00000000..bdb975b8 --- /dev/null +++ b/katharsis-spring/src/main/java/io/katharsis/spring/boot/v3/KatharsisConfigV3.java @@ -0,0 +1,80 @@ +package io.katharsis.spring.boot.v3; + +import javax.servlet.Filter; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; + +import io.katharsis.dispatcher.RequestDispatcher; +import io.katharsis.internal.boot.KatharsisBoot; +import io.katharsis.jackson.JsonApiModuleBuilder; +import io.katharsis.module.ModuleRegistry; +import io.katharsis.resource.registry.ConstantServiceUrlProvider; +import io.katharsis.resource.registry.ResourceRegistry; +import io.katharsis.spring.ErrorHandlerFilter; +import io.katharsis.spring.KatharsisFilterV2; +import io.katharsis.spring.boot.KatharsisSpringBootProperties; +import io.katharsis.spring.internal.SpringServiceDiscovery; + +/** + * Current katharsis configuration with JSON API compliance, QuerySpec and module support. + * Note that there is no support for QueryParams is this version due to the lack of JSON API compatibility. + */ +@Configuration +@EnableConfigurationProperties(KatharsisSpringBootProperties.class) +public class KatharsisConfigV3 { + + @Autowired + private KatharsisSpringBootProperties properties; + + @Autowired + private ObjectMapper objectMapper; + + @Bean + public SpringServiceDiscovery discovery() { + return new SpringServiceDiscovery(); + } + + @Bean + public KatharsisBoot katharsisBoot(SpringServiceDiscovery serviceDiscovery) { + KatharsisBoot boot = new KatharsisBoot(); + boot.setObjectMapper(objectMapper); + String baseUrl = properties.getDomainName() + properties.getPathPrefix(); + boot.setServiceUrlProvider(new ConstantServiceUrlProvider(baseUrl)); + boot.setServiceDiscovery(serviceDiscovery); + boot.setDefaultPageLimit(properties.getDefaultPageLimit()); + boot.boot(); + return boot; + } + + @Bean + public Filter springBootSampleKatharsisFilter(KatharsisBoot boot) { + JsonApiModuleBuilder jsonApiModuleBuilder = new JsonApiModuleBuilder(); + SimpleModule parameterNamesModule = jsonApiModuleBuilder.build(boot.getResourceRegistry(), false); + + objectMapper.registerModule(parameterNamesModule); + ResourceRegistry resourceRegistry = boot.getResourceRegistry(); + RequestDispatcher requestDispatcher = boot.getRequestDispatcher(); + return new KatharsisFilterV2(objectMapper, resourceRegistry, requestDispatcher, properties.getPathPrefix()); + } + + @Bean + public Filter errorHandlerFilter(KatharsisBoot boot) { + return new ErrorHandlerFilter(objectMapper, boot.getExceptionMapperRegistry()); + } + + @Bean + public ResourceRegistry resourceRegistry(KatharsisBoot boot) { + return boot.getResourceRegistry(); + } + + @Bean + public ModuleRegistry moduleRegistry(KatharsisBoot boot) { + return boot.getModuleRegistry(); + } +} diff --git a/katharsis-spring/src/main/java/io/katharsis/spring/internal/SpringServiceDiscovery.java b/katharsis-spring/src/main/java/io/katharsis/spring/internal/SpringServiceDiscovery.java new file mode 100644 index 00000000..8c89d5b3 --- /dev/null +++ b/katharsis-spring/src/main/java/io/katharsis/spring/internal/SpringServiceDiscovery.java @@ -0,0 +1,34 @@ +package io.katharsis.spring.internal; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +import io.katharsis.module.ServiceDiscovery; + +/** + * Spring-based discovery of services. + */ +public class SpringServiceDiscovery implements ServiceDiscovery, ApplicationContextAware { + + private ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + @Override + public List getInstancesByType(Class clazz) { + return new ArrayList<>(applicationContext.getBeansOfType(clazz).values()); + } + + @Override + public List getInstancesByAnnotation(Class annotationClass) { + return new ArrayList<>(applicationContext.getBeansWithAnnotation(annotationClass).values()); + } +} diff --git a/katharsis-spring/src/test/java/io/katharsis/spring/boot/SpringBootSimpleExampleApplication.java b/katharsis-spring/src/test/java/io/katharsis/spring/boot/SpringBootSimpleExampleApplication.java index e7da0650..02daaaf5 100644 --- a/katharsis-spring/src/test/java/io/katharsis/spring/boot/SpringBootSimpleExampleApplication.java +++ b/katharsis-spring/src/test/java/io/katharsis/spring/boot/SpringBootSimpleExampleApplication.java @@ -4,22 +4,22 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType; -import org.springframework.context.annotation.Import; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @SpringBootApplication @ComponentScan(value = "io.katharsis.spring", - excludeFilters = @ComponentScan.Filter(classes = KatharsisConfig.class, type = FilterType.ASSIGNABLE_TYPE)) + excludeFilters = @ComponentScan.Filter(classes = { KatharsisConfig.class, KatharsisConfigV2.class, KatharsisSpringBootProperties.class }, + type = FilterType.ASSIGNABLE_TYPE)) public class SpringBootSimpleExampleApplication { - @RequestMapping("/api/tasks/1") - public String customMethod() { - return "hello"; - } + @RequestMapping("/api/custom") + public String customMethod() { + return "hello"; + } - public static void main(String[] args) { - SpringApplication.run(SpringBootSimpleExampleApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(SpringBootSimpleExampleApplication.class, args); + } } diff --git a/katharsis-spring/src/test/java/io/katharsis/spring/boot/SpringBootSimpleExampleApplicationTests.java b/katharsis-spring/src/test/java/io/katharsis/spring/boot/SpringBootSimpleExampleApplicationTests.java index b1a6cf9a..e4c98cfd 100644 --- a/katharsis-spring/src/test/java/io/katharsis/spring/boot/SpringBootSimpleExampleApplicationTests.java +++ b/katharsis-spring/src/test/java/io/katharsis/spring/boot/SpringBootSimpleExampleApplicationTests.java @@ -27,7 +27,7 @@ public class SpringBootSimpleExampleApplicationTests { public void testTestEndpointWithQueryParams() throws Exception { TestRestTemplate testRestTemplate = new TestRestTemplate(); ResponseEntity response = testRestTemplate - .getForEntity("http://localhost:" + this.port + "/api/tasks?filter[Task][name]=John", String.class); + .getForEntity("http://localhost:" + this.port + "/api/tasks?filter[tasks][name]=John", String.class); assertEquals(HttpStatus.OK, response.getStatusCode()); assertThatJson(response.getBody()).node("data[0].attributes.name").isStringEqualTo("John"); assertThatJson(response.getBody()).node("data[0].links.self").isStringEqualTo("http://localhost:8080/api/tasks/1"); @@ -38,7 +38,7 @@ public void testTestEndpointWithQueryParams() throws Exception { public void testTestCustomEndpoint() throws Exception { TestRestTemplate testRestTemplate = new TestRestTemplate(); ResponseEntity response = testRestTemplate - .getForEntity("http://localhost:" + this.port + "/api/tasks/1", String.class); + .getForEntity("http://localhost:" + this.port + "/api/custom", String.class); assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals(response.getBody(), "hello"); } diff --git a/katharsis-spring/src/test/java/io/katharsis/spring/domain/model/Project.java b/katharsis-spring/src/test/java/io/katharsis/spring/domain/model/Project.java index 896f4d09..c4bcc7ce 100644 --- a/katharsis-spring/src/test/java/io/katharsis/spring/domain/model/Project.java +++ b/katharsis-spring/src/test/java/io/katharsis/spring/domain/model/Project.java @@ -6,24 +6,33 @@ @JsonApiResource(type = "projects") public class Project { - @JsonApiId - private Long id; + @JsonApiId + private Long id; - private String name; + private String name; - public Long getId() { - return id; - } + public Project() { - public void setId(Long id) { - this.id = id; - } + } - public String getName() { - return name; - } + public Project(long id, String name) { + this.id = id; + this.name = name; + } - public void setName(String name) { - this.name = name; - } + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } diff --git a/katharsis-spring/src/test/java/io/katharsis/spring/domain/model/Task.java b/katharsis-spring/src/test/java/io/katharsis/spring/domain/model/Task.java index c122d1f1..a5566267 100644 --- a/katharsis-spring/src/test/java/io/katharsis/spring/domain/model/Task.java +++ b/katharsis-spring/src/test/java/io/katharsis/spring/domain/model/Task.java @@ -8,44 +8,44 @@ @JsonApiResource(type = "tasks") public class Task { - @JsonApiId - private Long id; + @JsonApiId + private Long id; - private String name; + private String name; - @JsonApiToOne - @JsonApiIncludeByDefault - private Project project; + @JsonApiToOne + @JsonApiIncludeByDefault + private Project project; - public Task() { - } + public Task() { + } - public Task(Long id, String name) { - this.id = id; - this.name = name; - } + public Task(Long id, String name) { + this.id = id; + this.name = name; + } - public Long getId() { - return id; - } + public Long getId() { + return id; + } - public void setId(Long id) { - this.id = id; - } + public void setId(Long id) { + this.id = id; + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public Project getProject() { - return project; - } + public Project getProject() { + return project; + } - public void setProject(Project project) { - this.project = project; - } + public void setProject(Project project) { + this.project = project; + } } diff --git a/katharsis-spring/src/test/java/io/katharsis/spring/domain/repository/ProjectRepository.java b/katharsis-spring/src/test/java/io/katharsis/spring/domain/repository/ProjectRepository.java index be0c89d2..44330080 100644 --- a/katharsis-spring/src/test/java/io/katharsis/spring/domain/repository/ProjectRepository.java +++ b/katharsis-spring/src/test/java/io/katharsis/spring/domain/repository/ProjectRepository.java @@ -1,34 +1,44 @@ package io.katharsis.spring.domain.repository; -import io.katharsis.queryParams.QueryParams; -import io.katharsis.repository.ResourceRepository; -import io.katharsis.spring.domain.model.Project; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.springframework.stereotype.Component; +import io.katharsis.queryspec.QuerySpec; +import io.katharsis.queryspec.QuerySpecResourceRepositoryBase; +import io.katharsis.spring.domain.model.Project; + @Component -public class ProjectRepository implements ResourceRepository { - @Override - public S save(S entity) { - return null; - } - - @Override - public Project findOne(Long aLong, QueryParams requestParams) { - return null; - } - - @Override - public Iterable findAll(QueryParams requestParams) { - return null; - } - - @Override - public Iterable findAll(Iterable projectIds, QueryParams requestParams) { - return null; - } - - @Override - public void delete(Long aLong) { - - } +public class ProjectRepository extends QuerySpecResourceRepositoryBase { + + private Map projects = new HashMap<>(); + + public ProjectRepository() { + super(Project.class); + List interests = new ArrayList<>(); + interests.add("coding"); + interests.add("art"); + save(new Project(1L, "Project A")); + save(new Project(2L, "Project B")); + save(new Project(3L, "Project C")); + } + + @Override + public synchronized void delete(String id) { + projects.remove(id); + } + + @Override + public synchronized S save(S project) { + projects.put(project.getId(), project); + return project; + } + + @Override + public synchronized List findAll(QuerySpec querySpec) { + return querySpec.apply(projects.values()); + } } diff --git a/katharsis-spring/src/test/java/io/katharsis/spring/domain/repository/TaskRepository.java b/katharsis-spring/src/test/java/io/katharsis/spring/domain/repository/TaskRepository.java index 37fd25b8..6cb2e413 100644 --- a/katharsis-spring/src/test/java/io/katharsis/spring/domain/repository/TaskRepository.java +++ b/katharsis-spring/src/test/java/io/katharsis/spring/domain/repository/TaskRepository.java @@ -1,24 +1,47 @@ package io.katharsis.spring.domain.repository; -import io.katharsis.repository.annotations.JsonApiFindAll; -import io.katharsis.repository.annotations.JsonApiResourceRepository; -import io.katharsis.response.JsonApiResponse; -import io.katharsis.response.MetaInformation; -import io.katharsis.spring.domain.model.Task; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.springframework.stereotype.Component; -import java.util.Collections; +import io.katharsis.queryspec.QuerySpec; +import io.katharsis.queryspec.QuerySpecMetaRepository; +import io.katharsis.queryspec.QuerySpecResourceRepositoryBase; +import io.katharsis.response.MetaInformation; +import io.katharsis.spring.domain.model.Task; @Component -@JsonApiResourceRepository(Task.class) -public class TaskRepository { - - @JsonApiFindAll - public JsonApiResponse findAll() { - return new JsonApiResponse() - .setEntity(Collections.singletonList(new Task(1L, "John"))) - .setMetaInformation(new MetaInformation() { - public String name = "meta information"; - }); - } +public class TaskRepository extends QuerySpecResourceRepositoryBase implements QuerySpecMetaRepository { + + private Map tasks = new HashMap<>(); + + public TaskRepository() { + super(Task.class); + save(new Task(1L, "John")); + } + + @Override + public synchronized void delete(String id) { + tasks.remove(id); + } + + @Override + public synchronized S save(S task) { + tasks.put(task.getId(), task); + return task; + } + + @Override + public synchronized List findAll(QuerySpec querySpec) { + return querySpec.apply(tasks.values()); + } + + @Override + public MetaInformation getMetaInformation(Iterable resources, QuerySpec querySpec) { + return new MetaInformation() { + public String name = "meta information"; + }; + } } diff --git a/katharsis-spring/src/test/java/io/katharsis/spring/domain/repository/TaskToProjectRepository.java b/katharsis-spring/src/test/java/io/katharsis/spring/domain/repository/TaskToProjectRepository.java index 63162454..e592563a 100644 --- a/katharsis-spring/src/test/java/io/katharsis/spring/domain/repository/TaskToProjectRepository.java +++ b/katharsis-spring/src/test/java/io/katharsis/spring/domain/repository/TaskToProjectRepository.java @@ -1,39 +1,16 @@ package io.katharsis.spring.domain.repository; -import io.katharsis.queryParams.QueryParams; -import io.katharsis.repository.RelationshipRepository; +import org.springframework.stereotype.Component; + +import io.katharsis.queryspec.QuerySpecRelationshipRepositoryBase; import io.katharsis.spring.domain.model.Project; import io.katharsis.spring.domain.model.Task; -import org.springframework.stereotype.Component; @Component -public class TaskToProjectRepository implements RelationshipRepository { - - @Override - public void setRelation(Task task, Long projectId, String fieldName) { - - } - - @Override - public void setRelations(Task task, Iterable projectId, String fieldName) { - - } - - @Override - public void addRelations(Task source, Iterable targetIds, String fieldName) { - } - - @Override - public void removeRelations(Task source, Iterable targetIds, String fieldName) { - } +public class TaskToProjectRepository extends QuerySpecRelationshipRepositoryBase { - @Override - public Project findOneTarget(Long sourceId, String fieldName, QueryParams requestParams) { - return null; - } + protected TaskToProjectRepository() { + super(Task.class, Project.class); + } - @Override - public Iterable findManyTargets(Long sourceId, String fieldName, QueryParams requestParams) { - return null; - } }