diff --git a/algorithms-miscellaneous-2/README.md b/algorithms-miscellaneous-2/README.md index de054566ed..462644dddb 100644 --- a/algorithms-miscellaneous-2/README.md +++ b/algorithms-miscellaneous-2/README.md @@ -15,3 +15,5 @@ - [Calculate Percentage in Java](https://www.baeldung.com/java-calculate-percentage) - [Converting Between Byte Arrays and Hexadecimal Strings in Java](https://www.baeldung.com/java-byte-arrays-hex-strings) - [Convert Latitude and Longitude to a 2D Point in Java](https://www.baeldung.com/java-convert-latitude-longitude) +- [Reversing a Binary Tree in Java](https://www.baeldung.com/java-reversing-a-binary-tree) +- [Find If Two Numbers Are Relatively Prime in Java](https://www.baeldung.com/java-two-relatively-prime-numbers) diff --git a/algorithms-miscellaneous-3/README.md b/algorithms-miscellaneous-3/README.md index f299492d9c..4dd4b66ff2 100644 --- a/algorithms-miscellaneous-3/README.md +++ b/algorithms-miscellaneous-3/README.md @@ -4,4 +4,3 @@ - [Implementing Simple State Machines with Java Enums](https://www.baeldung.com/java-enum-simple-state-machine) - [Converting Between Roman and Arabic Numerals in Java](http://www.baeldung.com/java-convert-roman-arabic) - [Practical Java Examples of the Big O Notation](http://www.baeldung.com/java-algorithm-complexity) -- [An Introduction to the Theory of Big-O Notation](http://www.baeldung.com/big-o-notation) \ No newline at end of file diff --git a/apache-meecrowave/pom.xml b/apache-meecrowave/pom.xml index bb851577e2..4eb1094f94 100644 --- a/apache-meecrowave/pom.xml +++ b/apache-meecrowave/pom.xml @@ -60,7 +60,6 @@ 1.8 1.8 - 4.10 1.2.0 3.10.0 1.2.1 diff --git a/apache-olingo/Samples.md b/apache-olingo/Samples.md new file mode 100644 index 0000000000..def8971d64 --- /dev/null +++ b/apache-olingo/Samples.md @@ -0,0 +1,21 @@ +## OData test URLs + +This following table contains test URLs that can be used with the Olingo V2 demo project. + +| URL | Description | +|------------------------------------------|-------------------------------------------------| +| `http://localhost:8180/odata/$metadata` | fetch OData metadata document | +| `http://localhost:8180/odata/CarMakers?$top=10&$skip=10` | Get 10 entities starting at offset 10 | +| `http://localhost:8180/odata/CarMakers?$count` | Return total count of entities in this set | +| `http://localhost:8180/odata/CarMakers?$filter=startswith(Name,'B')` | Return entities where the *Name* property starts with 'B' | +| `http://localhost:8180/odata/CarModels?$filter=Year eq 2008 and CarMakerDetails/Name eq 'BWM'` | Return *CarModel* entities where the *Name* property of its maker starts with 'B' | +| `http://localhost:8180/odata/CarModels(1L)?$expand=CarMakerDetails` | Return the *CarModel* with primary key '1', along with its maker| +| `http://localhost:8180/odata/CarModels(1L)?$select=Name,Sku` | Return the *CarModel* with primary key '1', returing only its *Name* and *Sku* properties | +| `http://localhost:8180/odata/CarModels?$orderBy=Name asc,Sku desc` | Return *CarModel* entities, ordered by the their *Name* and *Sku* properties | +| `http://localhost:8180/odata/CarModels?$format=json` | Return *CarModel* entities, using a JSON representation| + + + + + + diff --git a/spring-boot-exceptions/.gitignore b/apache-olingo/olingo2/.gitignore similarity index 100% rename from spring-boot-exceptions/.gitignore rename to apache-olingo/olingo2/.gitignore diff --git a/apache-olingo/olingo2/pom.xml b/apache-olingo/olingo2/pom.xml new file mode 100644 index 0000000000..4fc81e5e49 --- /dev/null +++ b/apache-olingo/olingo2/pom.xml @@ -0,0 +1,108 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + org.baeldung.examples.olingo2 + olingo2-sample + 0.0.1-SNAPSHOT + olingo2-sample + Sample Olingo 2 Project + + + 1.8 + 2.0.11 + + + + + + org.springframework.boot + spring-boot-starter-jersey + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.apache.olingo + olingo-odata2-core + ${olingo2.version} + + + + javax.ws.rs + javax.ws.rs-api + + + + + org.apache.olingo + olingo-odata2-api + ${olingo2.version} + + + org.apache.olingo + olingo-odata2-jpa-processor-api + ${olingo2.version} + + + org.apache.olingo + olingo-odata2-jpa-processor-core + ${olingo2.version} + + + org.apache.olingo + olingo-odata2-jpa-processor-ref + ${olingo2.version} + + + org.eclipse.persistence + eclipselink + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java new file mode 100644 index 0000000000..65a0428154 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java @@ -0,0 +1,298 @@ +package org.baeldung.examples.olingo2; + +import java.util.List; +import java.util.Map; + +import javax.persistence.EntityGraph; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.FlushModeType; +import javax.persistence.LockModeType; +import javax.persistence.Persistence; +import javax.persistence.Query; +import javax.persistence.StoredProcedureQuery; +import javax.persistence.SynchronizationType; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaDelete; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.CriteriaUpdate; +import javax.persistence.metamodel.Metamodel; +import javax.servlet.http.HttpServletRequest; + +import org.apache.olingo.odata2.api.processor.ODataContext; +import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext; +import org.apache.olingo.odata2.jpa.processor.api.ODataJPAServiceFactory; +import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException; +import org.baeldung.examples.olingo2.JerseyConfig.EntityManagerFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.orm.jpa.EntityManagerFactoryUtils; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.stereotype.Component; + +/** + * ODataJPAServiceFactory implementation for our sample domain + * @author Philippe + * + */ +@Component +public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory { + + private static final Logger log = LoggerFactory.getLogger(CarsODataJPAServiceFactory.class); + + public CarsODataJPAServiceFactory() { + // Enable detailed error messages (useful for debugging) + setDetailErrors(true); + } + + /** + * This method will be called by Olingo on every request to + * initialize the ODataJPAContext that will be used. + */ + @Override + public ODataJPAContext initializeODataJPAContext() throws ODataJPARuntimeException { + + log.info("[I32] >>> initializeODataJPAContext()"); + ODataJPAContext ctx = getODataJPAContext(); + ODataContext octx = ctx.getODataContext(); + HttpServletRequest request = (HttpServletRequest)octx.getParameter(ODataContext.HTTP_SERVLET_REQUEST_OBJECT); + EntityManager em = (EntityManager)request.getAttribute(EntityManagerFilter.EM_REQUEST_ATTRIBUTE); + + // Here we're passing the EM that was created by the EntityManagerFilter (see JerseyConfig) + ctx.setEntityManager(new EntityManagerWrapper(em)); + ctx.setPersistenceUnitName("default"); + + // We're managing the EM's lifecycle, so we must inform Olingo that it should not + // try to manage transactions and/or persistence sessions + ctx.setContainerManaged(true); + return ctx; + } + + static class EntityManagerWrapper implements EntityManager { + + private EntityManager delegate; + + public void persist(Object entity) { + log.info("[I68] persist: entity.class=" + entity.getClass() + .getSimpleName()); + delegate.persist(entity); + // delegate.flush(); + } + + public T merge(T entity) { + log.info("[I74] merge: entity.class=" + entity.getClass() + .getSimpleName()); + return delegate.merge(entity); + } + + public void remove(Object entity) { + log.info("[I78] remove: entity.class=" + entity.getClass() + .getSimpleName()); + delegate.remove(entity); + } + + public T find(Class entityClass, Object primaryKey) { + return delegate.find(entityClass, primaryKey); + } + + public T find(Class entityClass, Object primaryKey, Map properties) { + return delegate.find(entityClass, primaryKey, properties); + } + + public T find(Class entityClass, Object primaryKey, LockModeType lockMode) { + return delegate.find(entityClass, primaryKey, lockMode); + } + + public T find(Class entityClass, Object primaryKey, LockModeType lockMode, Map properties) { + return delegate.find(entityClass, primaryKey, lockMode, properties); + } + + public T getReference(Class entityClass, Object primaryKey) { + return delegate.getReference(entityClass, primaryKey); + } + + public void flush() { + delegate.flush(); + } + + public void setFlushMode(FlushModeType flushMode) { + delegate.setFlushMode(flushMode); + } + + public FlushModeType getFlushMode() { + return delegate.getFlushMode(); + } + + public void lock(Object entity, LockModeType lockMode) { + delegate.lock(entity, lockMode); + } + + public void lock(Object entity, LockModeType lockMode, Map properties) { + delegate.lock(entity, lockMode, properties); + } + + public void refresh(Object entity) { + delegate.refresh(entity); + } + + public void refresh(Object entity, Map properties) { + delegate.refresh(entity, properties); + } + + public void refresh(Object entity, LockModeType lockMode) { + delegate.refresh(entity, lockMode); + } + + public void refresh(Object entity, LockModeType lockMode, Map properties) { + delegate.refresh(entity, lockMode, properties); + } + + public void clear() { + delegate.clear(); + } + + public void detach(Object entity) { + delegate.detach(entity); + } + + public boolean contains(Object entity) { + return delegate.contains(entity); + } + + public LockModeType getLockMode(Object entity) { + return delegate.getLockMode(entity); + } + + public void setProperty(String propertyName, Object value) { + delegate.setProperty(propertyName, value); + } + + public Map getProperties() { + return delegate.getProperties(); + } + + public Query createQuery(String qlString) { + return delegate.createQuery(qlString); + } + + public TypedQuery createQuery(CriteriaQuery criteriaQuery) { + return delegate.createQuery(criteriaQuery); + } + + public Query createQuery(CriteriaUpdate updateQuery) { + return delegate.createQuery(updateQuery); + } + + public Query createQuery(CriteriaDelete deleteQuery) { + return delegate.createQuery(deleteQuery); + } + + public TypedQuery createQuery(String qlString, Class resultClass) { + return delegate.createQuery(qlString, resultClass); + } + + public Query createNamedQuery(String name) { + return delegate.createNamedQuery(name); + } + + public TypedQuery createNamedQuery(String name, Class resultClass) { + return delegate.createNamedQuery(name, resultClass); + } + + public Query createNativeQuery(String sqlString) { + return delegate.createNativeQuery(sqlString); + } + + public Query createNativeQuery(String sqlString, Class resultClass) { + return delegate.createNativeQuery(sqlString, resultClass); + } + + public Query createNativeQuery(String sqlString, String resultSetMapping) { + return delegate.createNativeQuery(sqlString, resultSetMapping); + } + + public StoredProcedureQuery createNamedStoredProcedureQuery(String name) { + return delegate.createNamedStoredProcedureQuery(name); + } + + public StoredProcedureQuery createStoredProcedureQuery(String procedureName) { + return delegate.createStoredProcedureQuery(procedureName); + } + + public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) { + return delegate.createStoredProcedureQuery(procedureName, resultClasses); + } + + public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) { + return delegate.createStoredProcedureQuery(procedureName, resultSetMappings); + } + + public void joinTransaction() { + delegate.joinTransaction(); + } + + public boolean isJoinedToTransaction() { + return delegate.isJoinedToTransaction(); + } + + public T unwrap(Class cls) { + return delegate.unwrap(cls); + } + + public Object getDelegate() { + return delegate.getDelegate(); + } + + public void close() { + log.info("[I229] close"); + delegate.close(); + } + + public boolean isOpen() { + boolean isOpen = delegate.isOpen(); + log.info("[I236] isOpen: " + isOpen); + return isOpen; + } + + public EntityTransaction getTransaction() { + log.info("[I240] getTransaction()"); + return delegate.getTransaction(); + } + + public EntityManagerFactory getEntityManagerFactory() { + return delegate.getEntityManagerFactory(); + } + + public CriteriaBuilder getCriteriaBuilder() { + return delegate.getCriteriaBuilder(); + } + + public Metamodel getMetamodel() { + return delegate.getMetamodel(); + } + + public EntityGraph createEntityGraph(Class rootType) { + return delegate.createEntityGraph(rootType); + } + + public EntityGraph createEntityGraph(String graphName) { + return delegate.createEntityGraph(graphName); + } + + public EntityGraph getEntityGraph(String graphName) { + return delegate.getEntityGraph(graphName); + } + + public List> getEntityGraphs(Class entityClass) { + return delegate.getEntityGraphs(entityClass); + } + + public EntityManagerWrapper(EntityManager delegate) { + this.delegate = delegate; + } + + } + +} diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/JerseyConfig.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/JerseyConfig.java new file mode 100644 index 0000000000..78caf99861 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/JerseyConfig.java @@ -0,0 +1,125 @@ + package org.baeldung.examples.olingo2; + +import java.io.IOException; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.Path; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.core.Context; +import javax.ws.rs.ext.Provider; + +import org.apache.olingo.odata2.api.ODataServiceFactory; +import org.apache.olingo.odata2.core.rest.ODataRootLocator; +import org.apache.olingo.odata2.core.rest.app.ODataApplication; +import org.glassfish.jersey.server.ResourceConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * Jersey JAX-RS configuration + * @author Philippe + * + */ +@Component +@ApplicationPath("/odata") +public class JerseyConfig extends ResourceConfig { + + + public JerseyConfig(CarsODataJPAServiceFactory serviceFactory, EntityManagerFactory emf) { + + ODataApplication app = new ODataApplication(); + + app + .getClasses() + .forEach( c -> { + // Avoid using the default RootLocator, as we want + // a Spring Managed one + if ( !ODataRootLocator.class.isAssignableFrom(c)) { + register(c); + } + }); + + register(new CarsRootLocator(serviceFactory)); + register( new EntityManagerFilter(emf)); + } + + /** + * This filter handles the EntityManager transaction lifecycle. + * @author Philippe + * + */ + @Provider + public static class EntityManagerFilter implements ContainerRequestFilter, ContainerResponseFilter { + + private static final Logger log = LoggerFactory.getLogger(EntityManagerFilter.class); + public static final String EM_REQUEST_ATTRIBUTE = EntityManagerFilter.class.getName() + "_ENTITY_MANAGER"; + + private final EntityManagerFactory emf; + + @Context + private HttpServletRequest httpRequest; + + public EntityManagerFilter(EntityManagerFactory emf) { + this.emf = emf; + } + + @Override + public void filter(ContainerRequestContext ctx) throws IOException { + log.info("[I60] >>> filter"); + EntityManager em = this.emf.createEntityManager(); + httpRequest.setAttribute(EM_REQUEST_ATTRIBUTE, em); + + // Start a new transaction unless we have a simple GET + if (!"GET".equalsIgnoreCase(ctx.getMethod())) { + em.getTransaction() + .begin(); + } + } + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { + + log.info("[I68] <<< filter"); + EntityManager em = (EntityManager) httpRequest.getAttribute(EM_REQUEST_ATTRIBUTE); + + if (!"GET".equalsIgnoreCase(requestContext.getMethod())) { + EntityTransaction t = em.getTransaction(); + if (t.isActive()) { + if (!t.getRollbackOnly()) { + t.commit(); + } + } + } + + em.close(); + + } + + } + + @Path("/") + public static class CarsRootLocator extends ODataRootLocator { + + private CarsODataJPAServiceFactory serviceFactory; + + public CarsRootLocator(CarsODataJPAServiceFactory serviceFactory) { + this.serviceFactory = serviceFactory; + } + + @Override + public ODataServiceFactory getServiceFactory() { + return this.serviceFactory; + } + + } + +} diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/Olingo2SampleApplication.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/Olingo2SampleApplication.java new file mode 100644 index 0000000000..fa58612088 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/Olingo2SampleApplication.java @@ -0,0 +1,14 @@ +package org.baeldung.examples.olingo2; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +@SpringBootApplication +public class Olingo2SampleApplication extends SpringBootServletInitializer { + + public static void main(String[] args) { + SpringApplication.run(Olingo2SampleApplication.class); + } +} diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarMaker.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarMaker.java new file mode 100644 index 0000000000..42a3eaa59d --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarMaker.java @@ -0,0 +1,36 @@ +package org.baeldung.examples.olingo2.domain; + +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.validation.constraints.NotNull; + +import lombok.Data; + +@Entity +@Data +@Table(name="car_maker") +public class CarMaker { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + private Long id; + + @NotNull + @Column(name="name") + private String name; + + @OneToMany(mappedBy="maker", + orphanRemoval = true, + cascade=CascadeType.ALL) + private List models; + + +} diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarModel.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarModel.java new file mode 100644 index 0000000000..a4f2a04f6e --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarModel.java @@ -0,0 +1,38 @@ +package org.baeldung.examples.olingo2.domain; + + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.validation.constraints.NotNull; + +import lombok.Data; + +@Entity +@Data +@Table(name="car_model") +public class CarModel { + + @Id + @GeneratedValue(strategy=GenerationType.AUTO) + private Long id; + + @NotNull + private String name; + + @NotNull + private Integer year; + + @NotNull + private String sku; + + @ManyToOne(optional=false, fetch= FetchType.LAZY) + @JoinColumn(name="maker_fk") + private CarMaker maker; + +} diff --git a/apache-olingo/olingo2/src/main/resources/application.yml b/apache-olingo/olingo2/src/main/resources/application.yml new file mode 100644 index 0000000000..21563a94fe --- /dev/null +++ b/apache-olingo/olingo2/src/main/resources/application.yml @@ -0,0 +1,12 @@ +server: + port: 8180 + +spring: + jersey: + application-path: /odata + + jpa: + show-sql: true + open-in-view: false + hibernate: + ddl-auto: update \ No newline at end of file diff --git a/apache-olingo/olingo2/src/main/resources/data.sql b/apache-olingo/olingo2/src/main/resources/data.sql new file mode 100644 index 0000000000..327f2688c5 --- /dev/null +++ b/apache-olingo/olingo2/src/main/resources/data.sql @@ -0,0 +1,12 @@ +insert into car_maker(id,name) values (1,'Special Motors'); +insert into car_maker(id,name) values (2,'BWM'); +insert into car_maker(id,name) values (3,'Dolores'); + +insert into car_model(id,maker_fk,name,sku,year) values(1,1,'Muze','SM001',2018); +insert into car_model(id,maker_fk,name,sku,year) values(2,1,'Empada','SM002',2008); + +insert into car_model(id,maker_fk,name,sku,year) values(4,2,'BWM-100','BWM100',2008); +insert into car_model(id,maker_fk,name,sku,year) values(5,2,'BWM-200','BWM200',2009); +insert into car_model(id,maker_fk,name,sku,year) values(6,2,'BWM-300','BWM300',2008); + +alter sequence hibernate_sequence restart with 100; \ No newline at end of file diff --git a/spring-boot-exceptions/src/test/java/com/baeldung/jsonexception/SpringContextIntegrationTest.java b/apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java similarity index 63% rename from spring-boot-exceptions/src/test/java/com/baeldung/jsonexception/SpringContextIntegrationTest.java rename to apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java index aa91e242ab..687f6ab1ff 100644 --- a/spring-boot-exceptions/src/test/java/com/baeldung/jsonexception/SpringContextIntegrationTest.java +++ b/apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java @@ -1,4 +1,4 @@ -package com.baeldung.jsonexception; +package org.baeldung.examples.olingo2; import org.junit.Test; import org.junit.runner.RunWith; @@ -7,10 +7,10 @@ import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest -public class SpringContextIntegrationTest { +public class Olingo2SampleApplicationTests { - @Test - public void contextLoads() { - } + @Test + public void contextLoads() { + } } diff --git a/apache-olingo/olingo2/src/test/resources/olingo2-queries.json b/apache-olingo/olingo2/src/test/resources/olingo2-queries.json new file mode 100644 index 0000000000..9fdade6d10 --- /dev/null +++ b/apache-olingo/olingo2/src/test/resources/olingo2-queries.json @@ -0,0 +1,256 @@ +{ + "info": { + "_postman_id": "afa8e1e5-ab0e-4f1d-8b99-b7d1f091f975", + "name": "OLingo2 - Cars", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" + }, + "item": [ + { + "name": "GET Metadata", + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": "http://localhost:8080/odata/$metadata" + }, + "response": [] + }, + { + "name": "GET All CarMakers", + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": "http://localhost:8080/odata/CarMakers" + }, + "response": [] + }, + { + "name": "GET Makers with Pagination", + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8080/odata/CarMakers?$top=1&$orderby=Name&$skip=3", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "odata", + "CarMakers" + ], + "query": [ + { + "key": "$top", + "value": "1" + }, + { + "key": "$orderby", + "value": "Name" + }, + { + "key": "$skip", + "value": "3" + } + ] + } + }, + "response": [] + }, + { + "name": "GET Makers and Models", + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8080/odata/CarMakers?$expand=CarModelDetails", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "odata", + "CarMakers" + ], + "query": [ + { + "key": "$expand", + "value": "CarModelDetails" + } + ] + } + }, + "response": [] + }, + { + "name": "GET Makers with filter", + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8080/odata/CarMakers?$filter=Name eq 'BWM'&$expand=CarModelDetails", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "odata", + "CarMakers" + ], + "query": [ + { + "key": "$filter", + "value": "Name eq 'BWM'" + }, + { + "key": "$expand", + "value": "CarModelDetails" + } + ] + } + }, + "response": [] + }, + { + "name": "Create CarMaker", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "value": "application/atom+xml", + "type": "text" + }, + { + "key": "Accept", + "value": "application/atom+xml", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": " \r\n\r\n \r\n 2019-04-02T21:36:47Z\r\n \r\n \r\n \r\n \r\n \r\n \r\n Lucien\r\n \r\n \r\n" + }, + "url": "http://localhost:8080/odata/CarMakers" + }, + "response": [] + }, + { + "name": "Create CarModel", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/atom+xml" + }, + { + "key": "Accept", + "type": "text", + "value": "application/atom+xml" + } + ], + "body": { + "mode": "raw", + "raw": " \r\n\r\n \r\n 2019-04-02T21:36:47Z\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\t Tata\r\n\t TT101\r\n\t 2018\r\n \r\n \r\n" + }, + "url": "http://localhost:8080/odata/CarModels" + }, + "response": [] + }, + { + "name": "Update CarMaker", + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/atom+xml" + }, + { + "key": "Accept", + "type": "text", + "value": "application/atom+xml" + } + ], + "body": { + "mode": "raw", + "raw": " \r\n\r\n \r\n 2019-04-02T21:36:47Z\r\n \r\n \r\n \r\n \r\n \r\n \r\n 5\r\n KaiserWagen\r\n \r\n \r\n" + }, + "url": "http://localhost:8080/odata/CarMakers(5L)" + }, + "response": [] + }, + { + "name": "All CarModels", + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": "http://localhost:8080/odata/CarModels" + }, + "response": [] + }, + { + "name": "Delete CarModel", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "type": "text", + "value": "application/atom+xml" + }, + { + "key": "Accept", + "type": "text", + "value": "application/atom+xml" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": "http://localhost:8080/odata/CarModels(100L)" + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/apache-olingo/olingo4/.gitignore b/apache-olingo/olingo4/.gitignore new file mode 100644 index 0000000000..153c9335eb --- /dev/null +++ b/apache-olingo/olingo4/.gitignore @@ -0,0 +1,29 @@ +HELP.md +/target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +/build/ + +### VS Code ### +.vscode/ diff --git a/apache-olingo/olingo4/pom.xml b/apache-olingo/olingo4/pom.xml new file mode 100644 index 0000000000..794aee0711 --- /dev/null +++ b/apache-olingo/olingo4/pom.xml @@ -0,0 +1,95 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + org.baeldung.examples.olingo4 + olingo4-sample + 0.0.1-SNAPSHOT + olingo4-sample + Sample Olingo 4 Project + + + 1.8 + 4.5.0 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + com.h2database + h2 + runtime + + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-web + + + + org.apache.olingo + odata-server-api + ${odata.version} + + + org.apache.olingo + odata-server-core + ${odata.version} + runtime + + + + org.apache.olingo + odata-commons-api + ${odata.version} + + + org.apache.olingo + odata-commons-core + ${odata.version} + + + + commons-beanutils + commons-beanutils + 1.9.3 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/DefaultODataFactory.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/DefaultODataFactory.java new file mode 100644 index 0000000000..18f7f8ba24 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/DefaultODataFactory.java @@ -0,0 +1,20 @@ +package org.baeldung.examples.olingo4; + +import org.apache.olingo.server.api.OData; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.stereotype.Component; + +/** + * Default implementation for ODataFactory + * @author Philippe + * + */ +@Component +public class DefaultODataFactory implements ODataFactory { + + @Override + public OData newInstance() { + return OData.newInstance(); + } + +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataFactory.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataFactory.java new file mode 100644 index 0000000000..9acb4b8c5e --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataFactory.java @@ -0,0 +1,8 @@ +package org.baeldung.examples.olingo4; + +import org.apache.olingo.server.api.OData; + +public interface ODataFactory { + + public OData newInstance(); +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataHttpHandlerFactory.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataHttpHandlerFactory.java new file mode 100644 index 0000000000..27d0737c24 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataHttpHandlerFactory.java @@ -0,0 +1,8 @@ +package org.baeldung.examples.olingo4; + +import org.apache.olingo.server.api.ODataHttpHandler; + +public interface ODataHttpHandlerFactory { + + ODataHttpHandler newInstance(); +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataHttpHandlerFactoryImpl.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataHttpHandlerFactoryImpl.java new file mode 100644 index 0000000000..68d39dc052 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataHttpHandlerFactoryImpl.java @@ -0,0 +1,42 @@ +package org.baeldung.examples.olingo4; + +import java.util.Collections; +import java.util.List; + +import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataHttpHandler; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.processor.Processor; + +import lombok.Builder; + +@Builder +public class ODataHttpHandlerFactoryImpl implements ODataHttpHandlerFactory { + + + private final ODataFactory odataFactory; + private final CsdlEdmProvider edmProvider; + private final List processors; + + public ODataHttpHandlerFactoryImpl(ODataFactory odataFactory,CsdlEdmProvider edmProvider, List processors) { + this.odataFactory = odataFactory; + this.edmProvider = edmProvider; + this.processors = processors; + } + + @Override + public ODataHttpHandler newInstance() { + + OData odata = odataFactory.newInstance(); + ServiceMetadata metadata = odata.createServiceMetadata(edmProvider, Collections.emptyList()); + ODataHttpHandler handler = odata.createHandler(metadata); + + // Register all available processors + processors.forEach(p -> handler.register(p)); + + + return handler; + } + +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServiceConfiguration.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServiceConfiguration.java new file mode 100644 index 0000000000..0cde665359 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServiceConfiguration.java @@ -0,0 +1,35 @@ +package org.baeldung.examples.olingo4; + +import java.util.List; + +import javax.persistence.EntityManagerFactory; +import javax.servlet.http.HttpServlet; + +import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider; +import org.apache.olingo.server.api.processor.Processor; +import org.baeldung.examples.olingo4.ODataHttpHandlerFactoryImpl.ODataHttpHandlerFactoryImplBuilder; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ODataServiceConfiguration { + + @Bean + public ServletRegistrationBean odataServletRegistration(ODataHttpHandlerFactory factory) { + ServletRegistrationBean srb = + new ServletRegistrationBean<>(new ODataServlet(factory), "/odata/*"); + srb.setLoadOnStartup(1); + return srb; + } + + @Bean + public ODataHttpHandlerFactory httpHandlerFactory(CsdlEdmProvider edmProvider, ODataFactory odataFactory, List processors) { + return new ODataHttpHandlerFactoryImplBuilder() + .edmProvider(edmProvider) + .odataFactory(odataFactory) + .processors(processors) + .build(); + } + +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServlet.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServlet.java new file mode 100644 index 0000000000..c379124541 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServlet.java @@ -0,0 +1,38 @@ +/** + * + */ +package org.baeldung.examples.olingo4; + +import java.io.IOException; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.olingo.server.api.ODataHttpHandler; + +/** + * @author Philippe + * + */ +public class ODataServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + private final ODataHttpHandlerFactory odataHttpHandlerFactory; + + + public ODataServlet(ODataHttpHandlerFactory factory) { + this.odataHttpHandlerFactory = factory; + } + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + ODataHttpHandler handler = odataHttpHandlerFactory.newInstance(); + handler.process(req, resp); + } +} diff --git a/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/JsonErrorApplication.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/Olingo4SampleApplication.java similarity index 56% rename from spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/JsonErrorApplication.java rename to apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/Olingo4SampleApplication.java index 188584bd7c..1ac872ea0f 100644 --- a/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/JsonErrorApplication.java +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/Olingo4SampleApplication.java @@ -1,13 +1,13 @@ -package com.baeldung.jsonexception; +package org.baeldung.examples.olingo4; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class JsonErrorApplication { +public class Olingo4SampleApplication { public static void main(String[] args) { - SpringApplication.run(JsonErrorApplication.class, args); + SpringApplication.run(Olingo4SampleApplication.class, args); } -} \ No newline at end of file +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/domain/CarMaker.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/domain/CarMaker.java new file mode 100644 index 0000000000..79825b4556 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/domain/CarMaker.java @@ -0,0 +1,36 @@ +package org.baeldung.examples.olingo4.domain; + +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.validation.constraints.NotNull; + +import lombok.Data; + +@Entity +@Data +@Table(name="car_maker") +public class CarMaker { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + private Long id; + + @NotNull + @Column(name="name") + private String name; + + @OneToMany(mappedBy="maker", + orphanRemoval = true, + cascade=CascadeType.ALL) + private List models; + + +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/domain/CarModel.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/domain/CarModel.java new file mode 100644 index 0000000000..a9254e48b9 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/domain/CarModel.java @@ -0,0 +1,38 @@ +package org.baeldung.examples.olingo4.domain; + + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.validation.constraints.NotNull; + +import lombok.Data; + +@Entity +@Data +@Table(name="car_model") +public class CarModel { + + @Id + @GeneratedValue(strategy=GenerationType.AUTO) + private Long id; + + @NotNull + private String name; + + @NotNull + private Integer year; + + @NotNull + private String sku; + + @ManyToOne(optional=false, fetch= FetchType.EAGER ) + @JoinColumn(name="maker_fk") + private CarMaker maker; + +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/EdmTypeMapper.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/EdmTypeMapper.java new file mode 100644 index 0000000000..95797752a2 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/EdmTypeMapper.java @@ -0,0 +1,46 @@ +package org.baeldung.examples.olingo4.edm; + +import java.util.Collections; +import java.util.Date; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.sql.Time; +import java.util.AbstractMap.SimpleEntry; + +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; +import org.springframework.stereotype.Component; + +@Component +public class EdmTypeMapper { + + public EdmPrimitiveTypeKind java2edm(Class clazz) { + EdmPrimitiveTypeKind result = java2edm.get(clazz); + if ( result == null ) { + throw new IllegalArgumentException("[E19] Unsupported class mapping: class=" + clazz); + } + else { + return result; + } + } + + // Static map used generate attribute metadada based on Java types + static Map,EdmPrimitiveTypeKind> java2edm = Collections + .unmodifiableMap(Stream.of( + new SimpleEntry<>(Boolean.class,EdmPrimitiveTypeKind.Boolean), + new SimpleEntry<>(Byte.class,EdmPrimitiveTypeKind.SByte), + new SimpleEntry<>(Date.class,EdmPrimitiveTypeKind.Date), + new SimpleEntry<>(Time.class,EdmPrimitiveTypeKind.TimeOfDay), + new SimpleEntry<>(Number.class,EdmPrimitiveTypeKind.Decimal), + new SimpleEntry<>(Float.class,EdmPrimitiveTypeKind.Single), + new SimpleEntry<>(Double.class,EdmPrimitiveTypeKind.Double), + new SimpleEntry<>(UUID.class,EdmPrimitiveTypeKind.Guid), + new SimpleEntry<>(Short.class,EdmPrimitiveTypeKind.Int16), + new SimpleEntry<>(Integer.class,EdmPrimitiveTypeKind.Int32), + new SimpleEntry<>(Long.class,EdmPrimitiveTypeKind.Int64), + new SimpleEntry<>(String.class,EdmPrimitiveTypeKind.String) + + ).collect(Collectors.toMap((e)-> e.getKey(),(e)-> e.getValue()))); + +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/JpaEdmProvider.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/JpaEdmProvider.java new file mode 100644 index 0000000000..4cd979e931 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/JpaEdmProvider.java @@ -0,0 +1,269 @@ +package org.baeldung.examples.olingo4.edm; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.persistence.EntityManagerFactory; +import javax.persistence.metamodel.Attribute.PersistentAttributeType; +import javax.persistence.metamodel.EntityType; +import javax.persistence.metamodel.Metamodel; +import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.SingularAttribute; + +import org.apache.olingo.commons.api.edm.FullQualifiedName; +import org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmProvider; +import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer; +import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainerInfo; +import org.apache.olingo.commons.api.edm.provider.CsdlEntitySet; +import org.apache.olingo.commons.api.edm.provider.CsdlEntityType; +import org.apache.olingo.commons.api.edm.provider.CsdlNavigationProperty; +import org.apache.olingo.commons.api.edm.provider.CsdlProperty; +import org.apache.olingo.commons.api.edm.provider.CsdlPropertyRef; +import org.apache.olingo.commons.api.edm.provider.CsdlSchema; +import org.apache.olingo.commons.api.ex.ODataException; +import org.springframework.stereotype.Component; + +@Component +public class JpaEdmProvider extends CsdlAbstractEdmProvider { + + EntityManagerFactory emf; + + // + private EdmTypeMapper typeMapper; + + // Service Namespace + public static final String NAMESPACE = "Baeldung.OData"; + + // EDM Container + public static final String CONTAINER_NAME = "Cars"; + public static final FullQualifiedName CONTAINER = new FullQualifiedName(NAMESPACE, CONTAINER_NAME); + + // Caches of OData types by it fully qualified name + private Map cdslName2Type = new HashMap<>(); + + public JpaEdmProvider(EntityManagerFactory emf, EdmTypeMapper mapper) { + this.emf = emf; + this.typeMapper = mapper; + } + + /* (non-Javadoc) + * @see org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmProvider#getEntitySet(org.apache.olingo.commons.api.edm.FullQualifiedName, java.lang.String) + */ + @Override + public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) throws ODataException { + + if (entityContainer.equals(CONTAINER)) { + + EntityType e = emf.getMetamodel() + .getEntities() + .stream() + .filter((ent) -> (ent.getName() + "s") + .equals(entitySetName)) + .findFirst() + .orElse(null); + + if (e != null) { + CsdlEntitySet entitySet = new CsdlEntitySet(); + entitySet + .setName(entitySetName) + .setType(new FullQualifiedName(NAMESPACE, e.getName())); + return entitySet; + } + } + + return null; + } + + /* (non-Javadoc) + * @see org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmProvider#getEntityContainerInfo(org.apache.olingo.commons.api.edm.FullQualifiedName) + */ + @Override + public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) throws ODataException { + + // This method is invoked when displaying the Service Document at e.g. http://localhost:8080/DemoService/DemoService.svc + if (entityContainerName == null || entityContainerName.equals(CONTAINER)) { + CsdlEntityContainerInfo entityContainerInfo = new CsdlEntityContainerInfo(); + entityContainerInfo.setContainerName(CONTAINER); + return entityContainerInfo; + } + + return null; + } + + /* (non-Javadoc) + * @see org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmProvider#getSchemas() + */ + @Override + public List getSchemas() throws ODataException { + // create Schema + CsdlSchema schema = new CsdlSchema(); + schema.setNamespace(NAMESPACE); + + // add EntityTypes + List entityTypes = emf.getMetamodel() + .getEntities() + .stream() + .map((e) -> { + try { + return getEntityType(new FullQualifiedName(NAMESPACE, e.getName())); + } catch (ODataException oe) { + throw new RuntimeException(oe); + } + }) + .collect(Collectors.toList()); + + schema.setEntityTypes(entityTypes); + + // add EntityContainer + schema.setEntityContainer(getEntityContainer()); + + // finally + List schemas = new ArrayList(); + schemas.add(schema); + + return schemas; + } + + /* (non-Javadoc) + * @see org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmProvider#getEntityContainer() + */ + @Override + public CsdlEntityContainer getEntityContainer() throws ODataException { + + + // add EntityTypes + List entitySets = emf.getMetamodel() + .getEntities() + .stream() + .map((e) -> { + try { + // Here we use a simple mapping strategy to map entity types to entity set names: + return getEntitySet(CONTAINER, e.getName() + "s"); + } catch (ODataException oe) { + throw new RuntimeException(oe); + } + }) + .collect(Collectors.toList()); + + // create EntityContainer + CsdlEntityContainer entityContainer = new CsdlEntityContainer(); + entityContainer.setName(CONTAINER_NAME); + entityContainer.setEntitySets(entitySets); + + return entityContainer; + } + + @Override + public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) throws ODataException { + + CsdlEntityType result = cdslName2Type.get(entityTypeName); + if ( result != null ) { + return result; + } + + Metamodel mm = emf.getMetamodel(); + result = mm.getEntities() + .stream() + .filter(et -> entityTypeName.equals(new FullQualifiedName(NAMESPACE, et.getName()))) + .map(et -> buildODataType(et)) + .findFirst() + .orElse(null); + + // save for future use + cdslName2Type.put(entityTypeName, result); + return result; + + } + + /** + * Maps a JPA type to its OData counterpart. + * @param et + * @return + */ + protected CsdlEntityType buildODataType(EntityType et) { + + CsdlEntityType result = new CsdlEntityType(); + result.setName(et.getName()); + + // Process simple properties + List properties = et.getDeclaredSingularAttributes() + .stream() + .filter(attr -> attr.getPersistentAttributeType() == PersistentAttributeType.BASIC) + .map(attr -> buildBasicAttribute(et, attr)) + .collect(Collectors.toList()); + + result.setProperties(properties); + + // Process Ids + List ids = et.getDeclaredSingularAttributes() + .stream() + .filter(attr -> attr.getPersistentAttributeType() == PersistentAttributeType.BASIC && attr.isId()) + .map(attr -> buildRefAttribute(et, attr)) + .collect(Collectors.toList()); + + result.setKey(ids); + + // Process 1:N navs + List navs = et.getDeclaredPluralAttributes() + .stream() + .map(attr -> buildNavAttribute(et, attr)) + .collect(Collectors.toList()); + result.setNavigationProperties(navs); + + // Process N:1 navs + List navs2 = et.getDeclaredSingularAttributes() + .stream() + .filter(attr -> attr.getPersistentAttributeType() == PersistentAttributeType.MANY_TO_ONE) + .map(attr -> buildNavAttribute(et, attr)) + .collect(Collectors.toList()); + + result.getNavigationProperties().addAll(navs2); + + + return result; + } + + private CsdlProperty buildBasicAttribute(EntityType et, SingularAttribute attr) { + + CsdlProperty p = new CsdlProperty().setName(attr.getName()) + .setType(typeMapper.java2edm(attr.getJavaType()) + .getFullQualifiedName()) + .setNullable(et.getDeclaredSingularAttribute(attr.getName()) + .isOptional()); + + return p; + } + + private CsdlPropertyRef buildRefAttribute(EntityType et, SingularAttribute attr) { + + CsdlPropertyRef p = new CsdlPropertyRef().setName(attr.getName()); + + return p; + } + + // Build NavProperty for 1:N or M:N associations + private CsdlNavigationProperty buildNavAttribute(EntityType et, PluralAttribute attr) { + + CsdlNavigationProperty p = new CsdlNavigationProperty().setName(attr.getName()) + .setType(new FullQualifiedName(NAMESPACE, attr.getBindableJavaType().getSimpleName())) + .setCollection(true) + .setNullable(false); + + return p; + } + + // Build NavProperty for N:1 associations + private CsdlNavigationProperty buildNavAttribute(EntityType et, SingularAttribute attr) { + + CsdlNavigationProperty p = new CsdlNavigationProperty().setName(attr.getName()) + .setType(new FullQualifiedName(NAMESPACE, attr.getBindableJavaType().getSimpleName())) + .setCollection(false) + .setNullable(attr.isOptional()); + + return p; + } + +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityCollectionProcessor.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityCollectionProcessor.java new file mode 100644 index 0000000000..4a4e5026f3 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityCollectionProcessor.java @@ -0,0 +1,161 @@ +package org.baeldung.examples.olingo4.processor; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collection; +import java.util.List; + +import javax.persistence.EntityManagerFactory; +import javax.persistence.metamodel.EntityType; +import javax.persistence.metamodel.SingularAttribute; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.olingo.commons.api.data.ContextURL; +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.EntityCollection; +import org.apache.olingo.commons.api.data.Property; +import org.apache.olingo.commons.api.data.ValueType; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmNavigationProperty; +import org.apache.olingo.commons.api.ex.ODataRuntimeException; +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataLibraryException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor; +import org.apache.olingo.server.api.processor.EntityCollectionProcessor; +import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions; +import org.apache.olingo.server.api.serializer.ODataSerializer; +import org.apache.olingo.server.api.serializer.SerializerResult; +import org.apache.olingo.server.api.uri.UriInfo; +import org.apache.olingo.server.api.uri.UriParameter; +import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourceEntitySet; +import org.baeldung.examples.olingo4.repository.RepositoryRegistry; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Component; + +@Component +public class JpaEntityCollectionProcessor implements CountEntityCollectionProcessor { + + private OData odata; + private ServiceMetadata serviceMetadata; + private EntityManagerFactory emf; + private RepositoryRegistry repositoryRegistry; + private JpaEntityMapper entityMapper; + + public JpaEntityCollectionProcessor(EntityManagerFactory emf, RepositoryRegistry repositoryRegistry, JpaEntityMapper entityMapper) { + this.emf = emf; + this.repositoryRegistry = repositoryRegistry; + this.entityMapper = entityMapper; + } + + @Override + public void init(OData odata, ServiceMetadata serviceMetadata) { + this.odata = odata; + this.serviceMetadata = serviceMetadata; + } + + @Override + public void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { + + // 1st we have retrieve the requested EntitySet from the uriInfo object (representation of the parsed service URI) + List resourcePaths = uriInfo.getUriResourceParts(); + UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0); // in our example, the first segment is the EntitySet + EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet(); + + // 2nd: fetch the data from backend for this requested EntitySetName + // it has to be delivered as EntitySet object + EntityCollection entitySet = getData(edmEntitySet, uriInfo); + + // 3rd: create a serializer based on the requested format (json) + ODataSerializer serializer = odata.createSerializer(responseFormat); + + // 4th: Now serialize the content: transform from the EntitySet object to InputStream + EdmEntityType edmEntityType = edmEntitySet.getEntityType(); + ContextURL contextUrl = ContextURL.with() + .entitySet(edmEntitySet) + .build(); + + final String id = request.getRawBaseUri() + "/" + edmEntitySet.getName(); + EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with() + .id(id) + .contextURL(contextUrl) + .build(); + SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, edmEntityType, entitySet, opts); + InputStream serializedContent = serializerResult.getContent(); + + // Finally: configure the response object: set the body, headers and status code + response.setContent(serializedContent); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); + response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); + + } + + @Override + public void countEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo) throws ODataApplicationException, ODataLibraryException { + + // 1st we have retrieve the requested EntitySet from the uriInfo object (representation of the parsed service URI) + List resourcePaths = uriInfo.getUriResourceParts(); + UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0); // in our example, the first segment is the EntitySet + EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet(); + + // 2nd: fetch the data from backend for this requested EntitySetName + Long count = getCount(edmEntitySet, uriInfo); + + // Finally: configure the response object: set the body, headers and status code + response.setContent(new ByteArrayInputStream(count.toString().getBytes())); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); + response.setHeader(HttpHeader.CONTENT_TYPE, "text/plain"); + + } + + /** + * Helper method to retrieve all entities of an entity set from an the backend database + * @param edmEntitySet + * @param uriInfo + * @return + */ + protected EntityCollection getData(EdmEntitySet edmEntitySet, UriInfo uriInfo) { + + EdmEntityType type = edmEntitySet.getEntityType(); + JpaRepository repo = (JpaRepository)repositoryRegistry.getRepositoryForEntity(type); + EntityCollection result = new EntityCollection(); + + repo.findAll() + .stream() + .forEach((it) -> result.getEntities() + .add(entityMapper.map2entity(edmEntitySet, it))); + + return result; + } + + + /** + * Helper method to get the total size of an entity set + * @param edmEntitySet + * @param uriInfo + * @return + */ + protected Long getCount(EdmEntitySet edmEntitySet, UriInfo uriInfo) { + + EdmEntityType type = edmEntitySet.getEntityType(); + JpaRepository repo = (JpaRepository)repositoryRegistry.getRepositoryForEntity(type); + EntityCollection result = new EntityCollection(); + + return repo.count(); + } + + + + +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityMapper.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityMapper.java new file mode 100644 index 0000000000..1978aa4fd6 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityMapper.java @@ -0,0 +1,93 @@ +/** + * + */ +package org.baeldung.examples.olingo4.processor; + +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.net.URISyntaxException; + +import javax.persistence.EntityManagerFactory; +import javax.persistence.metamodel.EntityType; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.Property; +import org.apache.olingo.commons.api.data.ValueType; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.ex.ODataRuntimeException; +import org.springframework.stereotype.Component; + +/** + *

Helper class that converts a JPA entity into an OData entity using + * available metadata from the JPA's EntityManagerFactory.

+ * + * @author Philippe + * + */ +@Component +public class JpaEntityMapper { + + private EntityManagerFactory emf; + + public JpaEntityMapper(EntityManagerFactory emf) { + this.emf = emf; + } + + + public Entity map2entity(EdmEntitySet edmEntitySet, Object entry) { + + EntityType et = emf.getMetamodel() + .entity(entry.getClass()); + + + Entity e = new Entity(); + try { + et.getDeclaredSingularAttributes().stream() + .forEach( (attr) -> { + if ( !attr.isAssociation()) { + Object v = getPropertyValue(entry,attr.getName()); + Property p = new Property(null, attr.getName(),ValueType.PRIMITIVE,v); + e.addProperty(p); + + if ( attr.isId()) { + e.setId(createId(edmEntitySet.getName(),v)); + } + } + }); + } catch (Exception ex) { + throw new ODataRuntimeException("[E141] Unable to create OData entity", ex); + } + + return e; + } + + + public Object getPropertyValue(Object entry, String name) { + try { + return PropertyUtils.getProperty(entry,name); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new ODataRuntimeException("[E141] Unable to read property from entity, property=" + name, e); + } + } + + public void setPropertyValue(Object entry, String name,Object value) { + try { + PropertyUtils.setProperty(entry,name,value); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new ODataRuntimeException("[E141] Unable to read property from entity, property=" + name, e); + } + } + + + private URI createId(String entitySetName, Object id) { + try { + return new URI(entitySetName + "(" + String.valueOf(id) + ")"); + } catch (URISyntaxException e) { + throw new ODataRuntimeException("[E177] Unable to create URI", e); + } + } + + + +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityProcessor.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityProcessor.java new file mode 100644 index 0000000000..719e5de160 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityProcessor.java @@ -0,0 +1,304 @@ +/** + * + */ +package org.baeldung.examples.olingo4.processor; + +import java.io.InputStream; +import java.util.List; +import java.util.Locale; +import java.util.Optional; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.metamodel.SingularAttribute; + +import org.apache.olingo.commons.api.data.ContextURL; +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmNavigationProperty; +import org.apache.olingo.commons.api.ex.ODataRuntimeException; +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataLibraryException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.processor.EntityProcessor; +import org.apache.olingo.server.api.serializer.EntitySerializerOptions; +import org.apache.olingo.server.api.serializer.ODataSerializer; +import org.apache.olingo.server.api.serializer.SerializerResult; +import org.apache.olingo.server.api.uri.UriInfo; +import org.apache.olingo.server.api.uri.UriParameter; +import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourceEntitySet; +import org.apache.olingo.server.api.uri.UriResourceNavigation; +import org.baeldung.examples.olingo4.repository.EdmEntityRepository; +import org.baeldung.examples.olingo4.repository.RepositoryRegistry; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Component; + +/** + * JpaEntityProcessor adapter. + *

This implementation is heavily based on the Tutorial available + * at Olingo's site. It is meant to be an starting point for an actual implementation.

+ *

Please note that many features from a full-fledged are missing + * @author Philippe + * + */ +@Component +public class JpaEntityProcessor implements EntityProcessor { + + private EntityManagerFactory emf; + private OData odata; + private ServiceMetadata serviceMetadata; + private RepositoryRegistry registry; + private JpaEntityMapper entityMapper; + + public JpaEntityProcessor(EntityManagerFactory emf, RepositoryRegistry registry, JpaEntityMapper entityMapper) { + this.emf = emf; + this.registry = registry; + this.entityMapper = entityMapper; + } + + /* (non-Javadoc) + * @see org.apache.olingo.server.api.processor.Processor#init(org.apache.olingo.server.api.OData, org.apache.olingo.server.api.ServiceMetadata) + */ + @Override + public void init(OData odata, ServiceMetadata serviceMetadata) { + this.odata = odata; + this.serviceMetadata = serviceMetadata; + + } + + /* (non-Javadoc) + * @see org.apache.olingo.server.api.processor.EntityProcessor#readEntity(org.apache.olingo.server.api.ODataRequest, org.apache.olingo.server.api.ODataResponse, org.apache.olingo.server.api.uri.UriInfo, org.apache.olingo.commons.api.format.ContentType) + */ + @Override + public void readEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { + + // First, we have to figure out which entity is requested + List resourceParts = uriInfo.getUriResourceParts(); + InputStream entityStream; + + UriResourceEntitySet rootResourceEntitySet = (UriResourceEntitySet) resourceParts.get(0); + EdmEntitySet rootEntitySet = rootResourceEntitySet.getEntitySet(); + List rootPredicates = rootResourceEntitySet.getKeyPredicates(); + + if ( resourceParts.size() == 1 ) { + entityStream = readRootEntity(rootEntitySet,rootPredicates,responseFormat); + } + else if ( resourceParts.size() == 2 ) { + UriResource part = resourceParts.get(1); + if ( !(part instanceof UriResourceNavigation)) { + throw new ODataRuntimeException("[E103] part type not supported: class=" + part.getClass().getName()); + } + + UriResourceNavigation navSegment = (UriResourceNavigation)part; + entityStream = readRelatedEntity(request, rootEntitySet,rootPredicates,navSegment.getProperty(),navSegment.getKeyPredicates(),responseFormat); + } + else { + // For now, we'll only allow navigation just to directly linked navs + throw new ODataApplicationException("[E109] Multi-level navigation not supported", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + + //4. configure the response object + response.setContent(entityStream); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); + response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); + + } + + + // Lookup the EntitySet associated with an EntityType + // In our example, we assume we have only one entityset for each entity type + private EdmEntitySet entitySetFromType(EdmEntityType type) { + return serviceMetadata + .getEdm() + .getEntityContainer() + .getEntitySets() + .stream() + .filter((s) -> s.getEntityType().getName().equals(type.getName())) + .findFirst() + .orElseThrow(() -> new ODataRuntimeException("[E144] No entity set found for type " + type.getFullQualifiedName())); + } + + // + // private boolean isOne2ManyProperty(EdmEntityType entityType, EdmNavigationProperty property) { + // return entityType.getProperty(property.getName()) != null && property.isCollection(); + //} + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private InputStream readRootEntity(EdmEntitySet entitySet, List keyPredicates,ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { + EdmEntityType type = entitySet.getEntityType(); + JpaRepository repo = registry.getRepositoryForEntity(type); + + // Get key value + Long keyValue = getEntityKey(keyPredicates); + Optional entry = repo.findById(keyValue); + if ( !entry.isPresent()) { + throw new ODataApplicationException( + "[E116] NO entity found for the given key", + HttpStatusCode.NOT_FOUND.getStatusCode(), + Locale.ENGLISH); + } + + Entity e = entityMapper.map2entity(entitySet, entry.get()); + return serializeEntity(entitySet,e,responseFormat); + } + + private InputStream serializeEntity(EdmEntitySet entitySet, Entity entity,ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { + ContextURL contextUrl = ContextURL.with().entitySet(entitySet).build(); + // expand and select currently not supported + EntitySerializerOptions options = EntitySerializerOptions + .with() + .contextURL(contextUrl) + .build(); + + ODataSerializer serializer = odata.createSerializer(responseFormat); + + SerializerResult serializerResult = serializer.entity(serviceMetadata, entitySet.getEntityType(), entity, options); + return serializerResult.getContent(); + + } + +// @SuppressWarnings("unchecked") +// protected InputStream readRelatedEntities(EdmEntitySet rootEntitySet, List rootPredicates, EdmNavigationProperty property, ContentType responseFormat) throws ODataApplicationException { +// +// Object jpaEntity = readJPAEntity(rootEntitySet, rootPredicates); +// try { +// Collection set = (Collection)PropertyUtils.getProperty(jpaEntity, property.getName()); +// EdmEntitySet entitySet = entitySetFromType(property.getType()); +// ContextURL contextUrl = ContextURL +// .with() +// .entitySet(entitySet) +// .build(); +// +// EntityCollectionSerializerOptions options = EntityCollectionSerializerOptions +// .with() +// .contextURL(contextUrl) +// .build(); +// +// EntityCollection result = new EntityCollection(); +// +// set.stream() +// .map((o) -> this.entityMapper.map2entity(entitySet, o)) +// .forEach((e) -> result.getEntities().add(e)); +// +// ODataSerializer serializer = odata.createSerializer(responseFormat); +// SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, property.getType(), result, options); +// return serializerResult.getContent(); +// } +// catch(Exception ex) { +// throw new ODataRuntimeException("[E181] Error accessing database", ex); +// } +// } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private InputStream readRelatedEntity(ODataRequest request, EdmEntitySet entitySet, List rootPredicates, EdmNavigationProperty property, List parentPredicates, ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { + + + JpaRepository repo = (JpaRepository)registry.getRepositoryForEntity(entitySet.getEntityType()); + EdmEntityRepository relatedRepo = (EdmEntityRepository)registry.getRepositoryForEntity(property.getType()); + + // We assume here that we have a bi-directional 1:N relationship, so we'll + // always have a property in the child entity that points to the parent + Class rootClass = ((EdmEntityRepository)repo).getEntityClass(); + Class relatedClass = ((EdmEntityRepository)relatedRepo).getEntityClass(); + + SingularAttribute fk = emf.getMetamodel() + .entity(rootClass) + .getSingularAttributes() + .stream() + .filter((attr) -> { + boolean b = attr.isAssociation() && attr.getJavaType().isAssignableFrom(relatedClass); + return b; + }) + .findFirst() + .orElse(null); + + if ( fk == null ) { + throw new ODataRuntimeException("[E230] No singular attribute of child class '" + relatedClass.getName() + "' found" ); + } + + Long pkValue = getEntityKey(rootPredicates); + EntityManager em = this.emf.createEntityManager(); + try { + // Read data from DB + Object root = em.find(rootClass, pkValue); + Object related = this.entityMapper.getPropertyValue(root, fk.getName()); + + EdmEntitySet relatedEntitySet = entitySetFromType(property.getType()); + Entity e = entityMapper.map2entity(relatedEntitySet, related); + return serializeEntity(relatedEntitySet,e,responseFormat); + } + finally { + em.close(); + } + } + +// @SuppressWarnings("unchecked") +// private Object readJPAEntity(EdmEntitySet edmEntitySet, List keyPredicates) throws ODataApplicationException { +// EdmEntityType type = edmEntitySet.getEntityType(); +// JpaRepository repo = (JpaRepository)registry.getRepositoryForEntity(type); +// +// // Get key value +// Object keyValue = getEntityKey(type,keyPredicates); +// Object entry = repo +// .findById(keyValue) +// .orElseThrow( +// () -> new ODataApplicationException("[E116] NO entity found for the given key", +// HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ENGLISH)); +// +// return entry; +// } + + private Long getEntityKey(List keyPredicates) { + + if ( keyPredicates.size() > 1 ) { + throw new ODataRuntimeException("[E131] Composite keys are not supported"); + } + + // For now, we'll assume we only have numeric keys. + UriParameter keyParam = keyPredicates.get(0); + try { + return Long.parseLong(keyParam.getText()); + } + catch(NumberFormatException nfe) { + throw new ODataRuntimeException("[E140] Invalid key value. Only numeric keys are supported by this service"); + } + + + } + + /* (non-Javadoc) + * @see org.apache.olingo.server.api.processor.EntityProcessor#createEntity(org.apache.olingo.server.api.ODataRequest, org.apache.olingo.server.api.ODataResponse, org.apache.olingo.server.api.uri.UriInfo, org.apache.olingo.commons.api.format.ContentType, org.apache.olingo.commons.api.format.ContentType) + */ + @Override + public void createEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.apache.olingo.server.api.processor.EntityProcessor#updateEntity(org.apache.olingo.server.api.ODataRequest, org.apache.olingo.server.api.ODataResponse, org.apache.olingo.server.api.uri.UriInfo, org.apache.olingo.commons.api.format.ContentType, org.apache.olingo.commons.api.format.ContentType) + */ + @Override + public void updateEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.apache.olingo.server.api.processor.EntityProcessor#deleteEntity(org.apache.olingo.server.api.ODataRequest, org.apache.olingo.server.api.ODataResponse, org.apache.olingo.server.api.uri.UriInfo) + */ + @Override + public void deleteEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo) throws ODataApplicationException, ODataLibraryException { + // TODO Auto-generated method stub + + } + +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarMakerRepository.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarMakerRepository.java new file mode 100644 index 0000000000..1bde9f148c --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarMakerRepository.java @@ -0,0 +1,16 @@ +package org.baeldung.examples.olingo4.repository; + +import org.baeldung.examples.olingo4.domain.CarMaker; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +@Repository +public interface CarMakerRepository extends EdmEntityRepository, JpaRepository, JpaSpecificationExecutor { + + public default String getEdmEntityName() { return CarMaker.class.getSimpleName();} + @Override + default Class getEntityClass() { + return CarMaker.class; + } +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarModelRepository.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarModelRepository.java new file mode 100644 index 0000000000..247bf6e77b --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarModelRepository.java @@ -0,0 +1,22 @@ +package org.baeldung.examples.olingo4.repository; + +import java.util.List; + +import org.baeldung.examples.olingo4.domain.CarModel; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +@Repository +public interface CarModelRepository extends EdmEntityRepository, JpaRepository, JpaSpecificationExecutor { + + public List findByMakerId(Long makerId); + + public default String getEdmEntityName() { return CarModel.class.getSimpleName();} + + @Override + default Class getEntityClass() { + return CarModel.class; + } + +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/EdmEntityRepository.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/EdmEntityRepository.java new file mode 100644 index 0000000000..dbfd0e6f93 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/EdmEntityRepository.java @@ -0,0 +1,17 @@ +/** + * + */ +package org.baeldung.examples.olingo4.repository; + + +/** + * @author Philippe + * + */ +public interface EdmEntityRepository { + + public String getEdmEntityName(); + public Class getEntityClass(); + + +} diff --git a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/RepositoryRegistry.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/RepositoryRegistry.java new file mode 100644 index 0000000000..e3bb172e3a --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/RepositoryRegistry.java @@ -0,0 +1,29 @@ +package org.baeldung.examples.olingo4.repository; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Component; + +@Component +public class RepositoryRegistry { + + private Map> repositoriesByClassName = new HashMap<>(); + + public RepositoryRegistry(List> allRepositories) { + + allRepositories.stream() + .forEach((r) -> + repositoriesByClassName.put(r.getEdmEntityName(),(JpaRepository)r)); + + } + + + public JpaRepository getRepositoryForEntity(EdmEntityType entityType) { + JpaRepository repo = repositoriesByClassName.get(entityType.getName()); + return repo; + } +} diff --git a/apache-olingo/olingo4/src/main/resources/application.properties b/apache-olingo/olingo4/src/main/resources/application.properties new file mode 100644 index 0000000000..02c7fe5c4d --- /dev/null +++ b/apache-olingo/olingo4/src/main/resources/application.properties @@ -0,0 +1,9 @@ +server: + port: 8080 + +spring: + jpa: + show-sql: true + open-in-view: true + hibernate: + ddl-auto: update diff --git a/apache-olingo/olingo4/src/main/resources/data.sql b/apache-olingo/olingo4/src/main/resources/data.sql new file mode 100644 index 0000000000..327f2688c5 --- /dev/null +++ b/apache-olingo/olingo4/src/main/resources/data.sql @@ -0,0 +1,12 @@ +insert into car_maker(id,name) values (1,'Special Motors'); +insert into car_maker(id,name) values (2,'BWM'); +insert into car_maker(id,name) values (3,'Dolores'); + +insert into car_model(id,maker_fk,name,sku,year) values(1,1,'Muze','SM001',2018); +insert into car_model(id,maker_fk,name,sku,year) values(2,1,'Empada','SM002',2008); + +insert into car_model(id,maker_fk,name,sku,year) values(4,2,'BWM-100','BWM100',2008); +insert into car_model(id,maker_fk,name,sku,year) values(5,2,'BWM-200','BWM200',2009); +insert into car_model(id,maker_fk,name,sku,year) values(6,2,'BWM-300','BWM300',2008); + +alter sequence hibernate_sequence restart with 100; \ No newline at end of file diff --git a/apache-olingo/olingo4/src/test/java/org/baeldung/examples/olingo4/Olingo4SampleApplicationTests.java b/apache-olingo/olingo4/src/test/java/org/baeldung/examples/olingo4/Olingo4SampleApplicationTests.java new file mode 100644 index 0000000000..5d23a4148e --- /dev/null +++ b/apache-olingo/olingo4/src/test/java/org/baeldung/examples/olingo4/Olingo4SampleApplicationTests.java @@ -0,0 +1,16 @@ +package org.baeldung.examples.olingo4; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class Olingo4SampleApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/apache-velocity/pom.xml b/apache-velocity/pom.xml index a0a8389f7d..24ab0b861d 100644 --- a/apache-velocity/pom.xml +++ b/apache-velocity/pom.xml @@ -59,7 +59,6 @@ - 1.2 4.5.2 1.7 2.0 diff --git a/cdi/pom.xml b/cdi/pom.xml index 85da8518d0..c98ad57495 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -27,7 +27,7 @@ org.hamcrest hamcrest-core - ${hamcrest-core.version} + ${org.hamcrest.version} test @@ -64,7 +64,6 @@ 2.0.SP1 3.0.5.Final 1.9.2 - 1.3 3.10.0 5.1.2.RELEASE diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml b/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml index f650498b69..c6de00dbe9 100644 --- a/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml @@ -34,8 +34,5 @@ - - - 1.8 - + diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml index 710cecbd4e..56fb23e9d8 100644 --- a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml @@ -35,8 +35,4 @@ - - 1.8 - - diff --git a/core-groovy-2/README.md b/core-groovy-2/README.md index f60bdb3cbe..c8df242e1a 100644 --- a/core-groovy-2/README.md +++ b/core-groovy-2/README.md @@ -3,5 +3,5 @@ ## Relevant articles: - [String Matching in Groovy](http://www.baeldung.com/) -- [Groovy def Keyword] - +- [Groovy def Keyword](https://www.baeldung.com/groovy-def-keyword) +- [Pattern Matching in Strings in Groovy](https://www.baeldung.com/groovy-pattern-matching) diff --git a/core-groovy-2/src/main/resources/articleEmail.template b/core-groovy-2/src/main/resources/articleEmail.template new file mode 100644 index 0000000000..26488f6288 --- /dev/null +++ b/core-groovy-2/src/main/resources/articleEmail.template @@ -0,0 +1,5 @@ +Dear <% out << (user) %>, +Please read the requested article below. +<% out << (articleText) %> +From, +<% out << (signature) %> \ No newline at end of file diff --git a/core-groovy-2/src/main/resources/email.template b/core-groovy-2/src/main/resources/email.template new file mode 100644 index 0000000000..fe4eaff851 --- /dev/null +++ b/core-groovy-2/src/main/resources/email.template @@ -0,0 +1,3 @@ +Dear $user, +Thanks for subscribing our services. +${signature} \ No newline at end of file diff --git a/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy b/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy new file mode 100644 index 0000000000..1846ae664c --- /dev/null +++ b/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy @@ -0,0 +1,96 @@ +package com.baeldung.templateengine + +import groovy.text.SimpleTemplateEngine +import groovy.text.StreamingTemplateEngine +import groovy.text.GStringTemplateEngine +import groovy.text.XmlTemplateEngine +import groovy.text.XmlTemplateEngine +import groovy.text.markup.MarkupTemplateEngine +import groovy.text.markup.TemplateConfiguration + +class TemplateEnginesUnitTest extends GroovyTestCase { + + def bindMap = [user: "Norman", signature: "Baeldung"] + + void testSimpleTemplateEngine() { + def smsTemplate = 'Dear <% print user %>, Thanks for reading our Article. ${signature}' + def smsText = new SimpleTemplateEngine().createTemplate(smsTemplate).make(bindMap) + + assert smsText.toString() == "Dear Norman, Thanks for reading our Article. Baeldung" + } + + void testStreamingTemplateEngine() { + def articleEmailTemplate = new File('src/main/resources/articleEmail.template') + bindMap.articleText = """1. Overview +This is a tutorial article on Template Engines""" //can be a string larger than 64k + + def articleEmailText = new StreamingTemplateEngine().createTemplate(articleEmailTemplate).make(bindMap) + + assert articleEmailText.toString() == """Dear Norman, +Please read the requested article below. +1. Overview +This is a tutorial article on Template Engines +From, +Baeldung""" + + } + + void testGStringTemplateEngine() { + def emailTemplate = new File('src/main/resources/email.template') + def emailText = new GStringTemplateEngine().createTemplate(emailTemplate).make(bindMap) + + assert emailText.toString() == "Dear Norman,\nThanks for subscribing our services.\nBaeldung" + } + + void testXmlTemplateEngine() { + def emailXmlTemplate = ''' + def emailContent = "Thanks for subscribing our services." + + Dear ${user} + emailContent + ${signature} + + ''' + def emailXml = new XmlTemplateEngine().createTemplate(emailXmlTemplate).make(bindMap) + println emailXml.toString() + } + + void testMarkupTemplateEngineHtml() { + def emailHtmlTemplate = """html { + head { + title('Service Subscription Email') + } + body { + p('Dear Norman') + p('Thanks for subscribing our services.') + p('Baeldung') + } + }""" + + + def emailHtml = new MarkupTemplateEngine().createTemplate(emailHtmlTemplate).make() + println emailHtml.toString() + + } + + void testMarkupTemplateEngineXml() { + def emailXmlTemplate = """xmlDeclaration() + xs{ + email { + greet('Dear Norman') + content('Thanks for subscribing our services.') + signature('Baeldung') + } + } + """ + TemplateConfiguration config = new TemplateConfiguration() + config.autoIndent = true + config.autoEscape = true + config.autoNewLine = true + + def emailXml = new MarkupTemplateEngine(config).createTemplate(emailXmlTemplate).make() + + println emailXml.toString() + } + +} \ No newline at end of file diff --git a/core-groovy-collections/README.md b/core-groovy-collections/README.md index 482e33bce1..aeba8933be 100644 --- a/core-groovy-collections/README.md +++ b/core-groovy-collections/README.md @@ -2,5 +2,5 @@ ## Relevant articles: -- [Maps in Groovy](http://www.baeldung.com/) +- [Maps in Groovy](https://www.baeldung.com/groovy-maps) diff --git a/core-java-arrays/README.MD b/core-java-arrays/README.MD new file mode 100644 index 0000000000..9ee6998784 --- /dev/null +++ b/core-java-arrays/README.MD @@ -0,0 +1,3 @@ +## Relevant Articles + +- [Extending an Array’s Length](https://www.baeldung.com/java-array-add-element-at-the-end) diff --git a/core-java-arrays/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java b/core-java-arrays/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java new file mode 100644 index 0000000000..26a4ca7ef4 --- /dev/null +++ b/core-java-arrays/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java @@ -0,0 +1,52 @@ +package com.baeldung.array.conversions; + +import java.util.Arrays; +import java.util.function.IntFunction; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +public class StreamArrayConversion { + + public static String[] stringStreamToStringArrayUsingFunctionalInterface(Stream stringStream) { + IntFunction intFunction = new IntFunction() { + @Override + public String[] apply(int value) { + return new String[value]; + } + }; + + return stringStream.toArray(intFunction); + } + + public static String[] stringStreamToStringArrayUsingMethodReference(Stream stringStream) { + return stringStream.toArray(String[]::new); + } + + public static String[] stringStreamToStringArrayUsingLambda(Stream stringStream) { + return stringStream.toArray(value -> new String[value]); + } + + public static Integer[] integerStreamToIntegerArray(Stream integerStream) { + return integerStream.toArray(Integer[]::new); + } + + public static int[] intStreamToPrimitiveIntArray(Stream integerStream) { + return integerStream.mapToInt(i -> i).toArray(); + } + + public static Stream stringArrayToStreamUsingArraysStream(String[] stringArray) { + return Arrays.stream(stringArray); + } + + public static Stream stringArrayToStreamUsingStreamOf(String[] stringArray) { + return Stream.of(stringArray); + } + + public static IntStream primitiveIntArrayToStreamUsingArraysStream(int[] intArray) { + return Arrays.stream(intArray); + } + + public static Stream primitiveIntArrayToStreamUsingStreamOf(int[] intArray) { + return Stream.of(intArray); + } +} diff --git a/core-java-arrays/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java b/core-java-arrays/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java new file mode 100644 index 0000000000..d2173fea5b --- /dev/null +++ b/core-java-arrays/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java @@ -0,0 +1,70 @@ +package com.baeldung.array.conversions; + +import static com.baeldung.array.conversions.StreamArrayConversion.intStreamToPrimitiveIntArray; +import static com.baeldung.array.conversions.StreamArrayConversion.integerStreamToIntegerArray; +import static com.baeldung.array.conversions.StreamArrayConversion.stringStreamToStringArrayUsingFunctionalInterface; +import static com.baeldung.array.conversions.StreamArrayConversion.stringStreamToStringArrayUsingLambda; +import static com.baeldung.array.conversions.StreamArrayConversion.stringStreamToStringArrayUsingMethodReference; +import static com.baeldung.array.conversions.StreamArrayConversion.stringArrayToStreamUsingArraysStream; +import static com.baeldung.array.conversions.StreamArrayConversion.stringArrayToStreamUsingStreamOf; +import static com.baeldung.array.conversions.StreamArrayConversion.primitiveIntArrayToStreamUsingArraysStream; +import static com.baeldung.array.conversions.StreamArrayConversion.primitiveIntArrayToStreamUsingStreamOf; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.common.collect.Iterators; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import org.junit.Test; + +public class StreamArrayConversionUnitTest { + + private String[] stringArray = new String[]{"baeldung", "convert", "to", "string", "array"}; + private Integer[] integerArray = new Integer[]{1, 2, 3, 4, 5, 6, 7}; + private int[] intPrimitiveArray = new int[]{1, 2, 3, 4, 5, 6, 7}; + + @Test + public void givenStringStream_thenConvertToStringArrayUsingFunctionalInterface() { + Stream stringStream = Stream.of("baeldung", "convert", "to", "string", "array"); + assertArrayEquals(stringArray, stringStreamToStringArrayUsingFunctionalInterface(stringStream)); + } + + @Test + public void givenStringStream_thenConvertToStringArrayUsingMethodReference() { + Stream stringStream = Stream.of("baeldung", "convert", "to", "string", "array"); + assertArrayEquals(stringArray, stringStreamToStringArrayUsingMethodReference(stringStream)); + } + + @Test + public void givenStringStream_thenConvertToStringArrayUsingLambda() { + Stream stringStream = Stream.of("baeldung", "convert", "to", "string", "array"); + assertArrayEquals(stringArray, stringStreamToStringArrayUsingLambda(stringStream)); + } + + @Test + public void givenIntegerStream_thenConvertToIntegerArray() { + Stream integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7); + assertArrayEquals(integerArray, integerStreamToIntegerArray(integerStream)); + } + + @Test + public void givenIntStream_thenConvertToIntegerArray() { + Stream integerStream = IntStream.rangeClosed(1, 7).boxed(); + assertArrayEquals(intPrimitiveArray, intStreamToPrimitiveIntArray(integerStream)); + } + + @Test + public void givenStringArray_whenConvertedTwoWays_thenConvertedStreamsAreEqual() { + assertTrue(Iterators + .elementsEqual(stringArrayToStreamUsingArraysStream(stringArray).iterator(), + stringArrayToStreamUsingStreamOf(stringArray).iterator())); + } + + @Test + public void givenPrimitiveArray_whenConvertedTwoWays_thenConvertedStreamsAreNotEqual() { + assertFalse(Iterators.elementsEqual( + primitiveIntArrayToStreamUsingArraysStream(intPrimitiveArray).iterator(), + primitiveIntArrayToStreamUsingStreamOf(intPrimitiveArray).iterator())); + } +} diff --git a/core-java-lambdas/README.md b/core-java-lambdas/README.md new file mode 100644 index 0000000000..5b94953e68 --- /dev/null +++ b/core-java-lambdas/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Java 9 java.lang.Module API](https://www.baeldung.com/java-lambda-effectively-final-local-variables) diff --git a/core-java-modules/core-java-11/README.md b/core-java-modules/core-java-11/README.md index a4b0e0e59c..d68a1c87eb 100644 --- a/core-java-modules/core-java-11/README.md +++ b/core-java-modules/core-java-11/README.md @@ -7,3 +7,4 @@ - [Exploring the New HTTP Client in Java 9 and 11](https://www.baeldung.com/java-9-http-client) - [An Introduction to Epsilon GC: A No-Op Experimental Garbage Collector](https://www.baeldung.com/jvm-epsilon-gc-garbage-collector) - [Guide to jlink](https://www.baeldung.com/jlink) +- [Transforming an Empty String into an Empty Optional](https://www.baeldung.com/java-empty-string-to-empty-optional) diff --git a/core-java-modules/core-java-8-2/README.md b/core-java-modules/core-java-8-2/README.md index e2b12e8819..383fe5da34 100644 --- a/core-java-modules/core-java-8-2/README.md +++ b/core-java-modules/core-java-8-2/README.md @@ -3,4 +3,5 @@ ## Core Java 8 Cookbooks and Examples (part 2) ### Relevant Articles: -- [Anonymous Classes in Java](http://www.baeldung.com/) +- [Anonymous Classes in Java](https://www.baeldung.com/java-anonymous-classes) +- [Run JAR Application With Command Line Arguments](https://www.baeldung.com/java-run-jar-with-arguments) diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java index 70ec324cb3..3e0d752bb6 100644 --- a/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java +++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java @@ -101,7 +101,7 @@ public class OptionalChainingUnitTest { } private Optional createOptional(String input) { - if (input == null || input == "" || input == "empty") { + if (input == null || "".equals(input) || "empty".equals(input)) { return Optional.empty(); } diff --git a/core-java-modules/core-java-9/README.md b/core-java-modules/core-java-9/README.md index 8fdc3f6ee2..5715520bae 100644 --- a/core-java-modules/core-java-9/README.md +++ b/core-java-modules/core-java-9/README.md @@ -20,6 +20,14 @@ - [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar) - [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation) - [Java 9 Process API Improvements](https://www.baeldung.com/java-9-process-api) -- [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api) - - +- [Java 9 java.util.Objects Additions](https://www.baeldung.com/java-9-objects-new) +- [Java 9 Reactive Streams](https://www.baeldung.com/java-9-reactive-streams) +- [Java 9 Optional API Additions](https://www.baeldung.com/java-9-optional) +- [Java 9 CompletableFuture API Improvements](https://www.baeldung.com/java-9-completablefuture) +- [Introduction to Java 9 StackWalking API](https://www.baeldung.com/java-9-stackwalking-api) +- [Java 9 Convenience Factory Methods for Collections](https://www.baeldung.com/java-9-collections-factory-methods) +- [Java 9 Stream API Improvements](https://www.baeldung.com/java-9-stream-api) +- [A Guide to Java 9 Modularity](https://www.baeldung.com/java-9-modularity) +- [Java 9 Platform Module API](https://www.baeldung.com/java-9-module-api) +- [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api) +- [Filtering a Stream of Optionals in Java](https://www.baeldung.com/java-filter-stream-of-optional) diff --git a/core-java-modules/core-java-collections-set/README.md b/core-java-modules/core-java-collections-set/README.md index 217e9ee6a5..2e09e920dc 100644 --- a/core-java-modules/core-java-collections-set/README.md +++ b/core-java-modules/core-java-collections-set/README.md @@ -8,4 +8,5 @@ - [A Guide to HashSet in Java](http://www.baeldung.com/java-hashset) - [A Guide to TreeSet in Java](http://www.baeldung.com/java-tree-set) - [Initializing HashSet at the Time of Construction](http://www.baeldung.com/java-initialize-hashset) -- [Guide to EnumSet](https://www.baeldung.com/java-enumset) \ No newline at end of file +- [Guide to EnumSet](https://www.baeldung.com/java-enumset) +- [Set Operations in Java](https://www.baeldung.com/java-set-operations) diff --git a/core-java-modules/core-java-exceptions/pom.xml b/core-java-modules/core-java-exceptions/pom.xml new file mode 100644 index 0000000000..51c4e51341 --- /dev/null +++ b/core-java-modules/core-java-exceptions/pom.xml @@ -0,0 +1,26 @@ + + 4.0.0 + com.baeldung.exception.numberformat + core-java-exceptions + 0.0.1-SNAPSHOT + core-java-exceptions + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + junit + junit + 4.12 + test + + + + diff --git a/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/numberformat/NumberFormatExceptionUnitTest.java b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/numberformat/NumberFormatExceptionUnitTest.java new file mode 100644 index 0000000000..a1e8c7c30f --- /dev/null +++ b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/numberformat/NumberFormatExceptionUnitTest.java @@ -0,0 +1,154 @@ +package com.baeldung.exception.numberformat; + +import static org.junit.Assert.assertEquals; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Locale; +import java.util.logging.Logger; + +import org.junit.Test; + +/** + * A set of examples tested to show cases where NumberFormatException is thrown and not thrown. + */ +public class NumberFormatExceptionUnitTest { + + Logger LOG = Logger.getLogger(NumberFormatExceptionUnitTest.class.getName()); + + /* ---INTEGER FAIL CASES--- */ + @Test(expected = NumberFormatException.class) + public void givenByteConstructor_whenAlphabetAsInput_thenFail() { + Byte byteInt = new Byte("one"); + } + + @Test(expected = NumberFormatException.class) + public void givenShortConstructor_whenSpaceInInput_thenFail() { + Short shortInt = new Short("2 "); + } + + @Test(expected = NumberFormatException.class) + public void givenParseIntMethod_whenSpaceInInput_thenFail() { + Integer aIntPrim = Integer.parseInt("6000 "); + } + + @Test(expected = NumberFormatException.class) + public void givenParseIntMethod_whenUnderscoreInInput_thenFail() { + int bIntPrim = Integer.parseInt("6_000"); + } + + @Test(expected = NumberFormatException.class) + public void givenIntegerValueOfMethod_whenCommaInInput_thenFail() { + Integer cIntPrim = Integer.valueOf("6,000"); + } + + @Test(expected = NumberFormatException.class) + public void givenBigIntegerConstructor_whenDecimalInInput_thenFail() { + BigInteger bigInteger = new BigInteger("4.0"); + } + + @Test(expected = NumberFormatException.class) + public void givenDecodeMethod_whenAlphabetInInput_thenFail() { + Long decodeInteger = Long.decode("64403L"); + } + + /* ---INTEGER PASS CASES--- */ + @Test + public void givenInvalidNumberInputs_whenOptimized_thenPass() { + Byte byteInt = new Byte("1"); + assertEquals(1, byteInt.intValue()); + + Short shortInt = new Short("2 ".trim()); + assertEquals(2, shortInt.intValue()); + + Integer aIntObj = Integer.valueOf("6"); + assertEquals(6, aIntObj.intValue()); + + BigInteger bigInteger = new BigInteger("4"); + assertEquals(4, bigInteger.intValue()); + + int aIntPrim = Integer.parseInt("6000 ".trim()); + assertEquals(6000, aIntPrim); + + int bIntPrim = Integer.parseInt("6_000".replaceAll("_", "")); + assertEquals(6000, bIntPrim); + + int cIntPrim = Integer.parseInt("-6000"); + assertEquals(-6000, cIntPrim); + + Long decodeInteger = Long.decode("644032334"); + assertEquals(644032334L, decodeInteger.longValue()); + } + + /* ---DOUBLE FAIL CASES--- */ + @Test(expected = NumberFormatException.class) + public void givenFloatConstructor_whenAlphabetInInput_thenFail() { + Float floatDecimalObj = new Float("one.1"); + } + + @Test(expected = NumberFormatException.class) + public void givenDoubleConstructor_whenAlphabetInInput_thenFail() { + Double doubleDecimalObj = new Double("two.2"); + } + + @Test(expected = NumberFormatException.class) + public void givenBigDecimalConstructor_whenSpecialCharsInInput_thenFail() { + BigDecimal bigDecimalObj = new BigDecimal("3_0.3"); + } + + @Test(expected = NumberFormatException.class) + public void givenParseDoubleMethod_whenCommaInInput_thenFail() { + double aDoublePrim = Double.parseDouble("4000,1"); + } + + /* ---DOUBLE PASS CASES--- */ + @Test + public void givenDoubleConstructor_whenDecimalInInput_thenPass() { + Double doubleDecimalObj = new Double("2.2"); + assertEquals(2.2, doubleDecimalObj.doubleValue(), 0); + } + + @Test + public void givenDoubleValueOfMethod_whenMinusInInput_thenPass() { + Double aDoubleObj = Double.valueOf("-6000"); + assertEquals(-6000, aDoubleObj.doubleValue(), 0); + } + + @Test + public void givenUsDecimalNumber_whenParsedWithNumberFormat_thenPass() throws ParseException { + Number parsedNumber = parseNumberWithLocale("4000.1", Locale.US); + assertEquals(4000.1, parsedNumber); + assertEquals(4000.1, parsedNumber.doubleValue(), 0); + assertEquals(4000, parsedNumber.intValue()); + } + + /** + * In most European countries (for example, France), comma is used as decimal in place of period. + * @throws ParseException if the input string contains special characters other than comma or decimal. + * In this test case, anything after decimal (period) is dropped when a European locale is set. + */ + @Test + public void givenEuDecimalNumberHasComma_whenParsedWithNumberFormat_thenPass() throws ParseException { + Number parsedNumber = parseNumberWithLocale("4000,1", Locale.FRANCE); + LOG.info("Number parsed is: " + parsedNumber); + assertEquals(4000.1, parsedNumber); + assertEquals(4000.1, parsedNumber.doubleValue(), 0); + assertEquals(4000, parsedNumber.intValue()); + } + + /** + * Converts a string into a number retaining all decimals, and symbols valid in a locale. + * @param number the input string for a number. + * @param locale the locale to consider while parsing a number. + * @return the generic number object which can represent multiple number types. + * @throws ParseException when input contains invalid characters. + */ + private Number parseNumberWithLocale(String number, Locale locale) throws ParseException { + locale = locale == null ? Locale.getDefault() : locale; + NumberFormat numberFormat = NumberFormat.getInstance(locale); + return numberFormat.parse(number); + } + +} diff --git a/core-java-modules/core-java-io/README.md b/core-java-modules/core-java-io/README.md index 9ce39459dd..6737ad6eb9 100644 --- a/core-java-modules/core-java-io/README.md +++ b/core-java-modules/core-java-io/README.md @@ -40,3 +40,4 @@ - [How to Write to a CSV File in Java](https://www.baeldung.com/java-csv) - [List Files in a Directory in Java](https://www.baeldung.com/java-list-directory-files) - [Java InputStream to Byte Array and ByteBuffer](https://www.baeldung.com/convert-input-stream-to-array-of-bytes) +- [Introduction to the Java NIO Selector](https://www.baeldung.com/java-nio-selector) diff --git a/core-java-modules/core-java-lang-oop-2/README.md b/core-java-modules/core-java-lang-oop-2/README.md index af0aed5af3..2e36d251ca 100644 --- a/core-java-modules/core-java-lang-oop-2/README.md +++ b/core-java-modules/core-java-lang-oop-2/README.md @@ -4,3 +4,5 @@ ### Relevant Articles: - [Generic Constructors in Java](https://www.baeldung.com/java-generic-constructors) +- [Cannot Reference “X” Before Supertype Constructor Has Been Called](https://www.baeldung.com/java-cannot-reference-x-before-supertype-constructor-error) +- [Anonymous Classes in Java](https://www.baeldung.com/java-anonymous-classes) diff --git a/core-java-modules/core-java-reflection/README.MD b/core-java-modules/core-java-reflection/README.MD new file mode 100644 index 0000000000..c8766d6858 --- /dev/null +++ b/core-java-modules/core-java-reflection/README.MD @@ -0,0 +1,3 @@ +## Relevant Articles + +- [Void Type in Java](https://www.baeldung.com/java-void-type) diff --git a/core-java-modules/core-java/README.md b/core-java-modules/core-java/README.md index c2d1b4a06b..65fb5ddb9d 100644 --- a/core-java-modules/core-java/README.md +++ b/core-java-modules/core-java/README.md @@ -51,3 +51,4 @@ - [Java Bitwise Operators](https://www.baeldung.com/java-bitwise-operators) - [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar) - [Making a JSON POST Request With HttpURLConnection](https://www.baeldung.com/httpurlconnection-post) +- [Convert Hex to ASCII in Java](https://www.baeldung.com/java-convert-hex-to-ascii) diff --git a/core-java-modules/core-java/pom.xml b/core-java-modules/core-java/pom.xml index b0f9fea26e..7942f3e7e2 100644 --- a/core-java-modules/core-java/pom.xml +++ b/core-java-modules/core-java/pom.xml @@ -454,7 +454,7 @@ 2.8.2 - 3.5 + 3.9 2.5 3.6.1 1.0.3 diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/RootCauseFinder.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/RootCauseFinder.java new file mode 100644 index 0000000000..cf449110e6 --- /dev/null +++ b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/RootCauseFinder.java @@ -0,0 +1,98 @@ +package com.baeldung.exceptions; + +import java.time.LocalDate; +import java.time.Period; +import java.time.format.DateTimeParseException; +import java.util.Objects; + +/** + * Utility class to find root cause exceptions. + */ +public class RootCauseFinder { + + private RootCauseFinder() { + } + + public static Throwable findCauseUsingPlainJava(Throwable throwable) { + Objects.requireNonNull(throwable); + Throwable rootCause = throwable; + while (rootCause.getCause() != null && rootCause.getCause() != rootCause) { + rootCause = rootCause.getCause(); + } + return rootCause; + } + + /** + * Calculates the age of a person from a given date. + */ + static class AgeCalculator { + + private AgeCalculator() { + } + + public static int calculateAge(String birthDate) { + if (birthDate == null || birthDate.isEmpty()) { + throw new IllegalArgumentException(); + } + + try { + return Period + .between(parseDate(birthDate), LocalDate.now()) + .getYears(); + } catch (DateParseException ex) { + throw new CalculationException(ex); + } + } + + private static LocalDate parseDate(String birthDateAsString) { + + LocalDate birthDate; + try { + birthDate = LocalDate.parse(birthDateAsString); + } catch (DateTimeParseException ex) { + throw new InvalidFormatException(birthDateAsString, ex); + } + + if (birthDate.isAfter(LocalDate.now())) { + throw new DateOutOfRangeException(birthDateAsString); + } + + return birthDate; + } + + } + + static class CalculationException extends RuntimeException { + + CalculationException(DateParseException ex) { + super(ex); + } + } + + static class DateParseException extends RuntimeException { + + DateParseException(String input) { + super(input); + } + + DateParseException(String input, Throwable thr) { + super(input, thr); + } + } + + static class InvalidFormatException extends DateParseException { + + InvalidFormatException(String input, Throwable thr) { + super("Invalid date format: " + input, thr); + } + } + + static class DateOutOfRangeException extends DateParseException { + + DateOutOfRangeException(String date) { + super("Date out of range: " + date); + } + + } + +} diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java new file mode 100644 index 0000000000..5d0f3b9c3e --- /dev/null +++ b/core-java-modules/core-java/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java @@ -0,0 +1,114 @@ +package com.baeldung.exceptions; + +import com.google.common.base.Throwables; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoUnit; + +import static com.baeldung.exceptions.RootCauseFinder.*; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Tests the {@link RootCauseFinder}. + */ +public class RootCauseFinderUnitTest { + + @Test + public void givenBirthDate_whenCalculatingAge_thenAgeReturned() { + try { + int age = AgeCalculator.calculateAge("1990-01-01"); + Assertions.assertEquals(1990, LocalDate + .now() + .minus(age, ChronoUnit.YEARS) + .getYear()); + } catch (CalculationException e) { + Assertions.fail(e.getMessage()); + } + } + + @Test + public void givenWrongFormatDate_whenFindingRootCauseUsingJava_thenRootCauseFound() { + try { + AgeCalculator.calculateAge("010102"); + } catch (CalculationException ex) { + assertTrue(findCauseUsingPlainJava(ex) instanceof DateTimeParseException); + } + } + + @Test + public void givenOutOfRangeDate_whenFindingRootCauseUsingJava_thenRootCauseFound() { + try { + AgeCalculator.calculateAge("2020-04-04"); + } catch (CalculationException ex) { + assertTrue(findCauseUsingPlainJava(ex) instanceof DateOutOfRangeException); + } + } + + @Test + public void givenNullDate_whenFindingRootCauseUsingJava_thenRootCauseFound() { + try { + AgeCalculator.calculateAge(null); + } catch (Exception ex) { + assertTrue(findCauseUsingPlainJava(ex) instanceof IllegalArgumentException); + } + } + + @Test + public void givenWrongFormatDate_whenFindingRootCauseUsingApacheCommons_thenRootCauseFound() { + try { + AgeCalculator.calculateAge("010102"); + } catch (CalculationException ex) { + assertTrue(ExceptionUtils.getRootCause(ex) instanceof DateTimeParseException); + } + } + + @Test + public void givenOutOfRangeDate_whenFindingRootCauseUsingApacheCommons_thenRootCauseFound() { + try { + AgeCalculator.calculateAge("2020-04-04"); + } catch (CalculationException ex) { + assertTrue(ExceptionUtils.getRootCause(ex) instanceof DateOutOfRangeException); + } + } + + @Test + public void givenNullDate_whenFindingRootCauseUsingApacheCommons_thenRootCauseNotFound() { + try { + AgeCalculator.calculateAge(null); + } catch (Exception ex) { + assertTrue(ExceptionUtils.getRootCause(ex) instanceof IllegalArgumentException); + } + } + + @Test + public void givenWrongFormatDate_whenFindingRootCauseUsingGuava_thenRootCauseFound() { + try { + AgeCalculator.calculateAge("010102"); + } catch (CalculationException ex) { + assertTrue(Throwables.getRootCause(ex) instanceof DateTimeParseException); + } + } + + @Test + public void givenOutOfRangeDate_whenFindingRootCauseUsingGuava_thenRootCauseFound() { + try { + AgeCalculator.calculateAge("2020-04-04"); + } catch (CalculationException ex) { + assertTrue(Throwables.getRootCause(ex) instanceof DateOutOfRangeException); + } + } + + @Test + public void givenNullDate_whenFindingRootCauseUsingGuava_thenRootCauseFound() { + try { + AgeCalculator.calculateAge(null); + } catch (Exception ex) { + assertTrue(Throwables.getRootCause(ex) instanceof IllegalArgumentException); + } + } + +} diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index ed6a056448..2b563a7be4 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -15,6 +15,7 @@ pre-jpms + core-java-exceptions diff --git a/core-java-modules/pre-jpms/README.MD b/core-java-modules/pre-jpms/README.MD new file mode 100644 index 0000000000..8c9af82ba5 --- /dev/null +++ b/core-java-modules/pre-jpms/README.MD @@ -0,0 +1,3 @@ +## Relevant Articles + +- [Java 9 Migration Issues and Resolutions](https://www.baeldung.com/java-9-migration-issue) diff --git a/core-kotlin-2/README.md b/core-kotlin-2/README.md index 6d0b20135d..d75dd2208a 100644 --- a/core-kotlin-2/README.md +++ b/core-kotlin-2/README.md @@ -6,4 +6,5 @@ - [Kotlin Scope Functions](https://www.baeldung.com/kotlin-scope-functions) - [Kotlin Annotations](https://www.baeldung.com/kotlin-annotations) - [Split a List into Parts in Kotlin](https://www.baeldung.com/kotlin-split-list-into-parts) -- [String Comparison in Kotlin](https://www.baeldung.com/kotlin-string-comparison) \ No newline at end of file +- [String Comparison in Kotlin](https://www.baeldung.com/kotlin-string-comparison) +- [Guide to JVM Platform Annotations in Kotlin](https://www.baeldung.com/kotlin-jvm-annotations) diff --git a/ethereum/pom.xml b/ethereum/pom.xml index baa74b58a5..80e1c04676 100644 --- a/ethereum/pom.xml +++ b/ethereum/pom.xml @@ -88,7 +88,7 @@ javax.servlet javax.servlet-api - ${javax-servlet.version} + ${javax.servlet-api.version} javax.servlet.jsp.jstl @@ -98,7 +98,7 @@ javax.servlet.jsp javax.servlet.jsp-api - ${javax-jsp.version} + ${javax.servlet.jsp-api.version} @@ -160,7 +160,7 @@ org.hamcrest hamcrest-library - ${hamcrest.version} + ${org.hamcrest.version} test @@ -213,12 +213,7 @@ 3.3.1 1.5.6.RELEASE 2.21.0 - 1.3 - 2.3.1 - 3.1.0 2.4.0 - 1.2 - 4.12 1.2.3 1.7.25 2.0.4.RELEASE diff --git a/google-cloud/pom.xml b/google-cloud/pom.xml index e39e186f05..ec53b78070 100644 --- a/google-cloud/pom.xml +++ b/google-cloud/pom.xml @@ -30,7 +30,6 @@ - 1.16.18 1.16.0 diff --git a/google-web-toolkit/pom.xml b/google-web-toolkit/pom.xml index f4c6a0ab39..0723cd3be2 100644 --- a/google-web-toolkit/pom.xml +++ b/google-web-toolkit/pom.xml @@ -120,7 +120,6 @@ UTF-8 UTF-8 - 4.11 2.8.2 diff --git a/gson/pom.xml b/gson/pom.xml index 8222cb50e1..a21d783c39 100644 --- a/gson/pom.xml +++ b/gson/pom.xml @@ -67,7 +67,6 @@ 3.5 4.1 2.9.6 - 1.16.10 \ No newline at end of file diff --git a/guava-collections-set/README.md b/guava-collections-set/README.md new file mode 100644 index 0000000000..cfbe67c13e --- /dev/null +++ b/guava-collections-set/README.md @@ -0,0 +1,4 @@ + +### Relevant Articles: + +- [Guide to Guava Multiset](https://www.baeldung.com/guava-multiset) diff --git a/guest/junit5-example/pom.xml b/guest/junit5-example/pom.xml index 7c0cc3e776..c6370941d1 100644 --- a/guest/junit5-example/pom.xml +++ b/guest/junit5-example/pom.xml @@ -60,7 +60,6 @@ 5.0.0-M4 4.12.0-M4 - 1.4.195 2.8.2 1.0.0-M4 diff --git a/guest/log4j2-example/pom.xml b/guest/log4j2-example/pom.xml index 045ff7325b..31a32a4562 100644 --- a/guest/log4j2-example/pom.xml +++ b/guest/log4j2-example/pom.xml @@ -41,7 +41,6 @@ - 2.9.7 2.8.2 diff --git a/guest/tomcat-app/pom.xml b/guest/tomcat-app/pom.xml index 9ce77c758a..ab18023f70 100644 --- a/guest/tomcat-app/pom.xml +++ b/guest/tomcat-app/pom.xml @@ -31,9 +31,9 @@ ${rest-assured.version} - com.h2database + com.h2 h2 - ${h2database.version} + ${h2.version} runtime @@ -62,7 +62,6 @@ 2.25.1 - 1.4.195 3.0.3 2.8.2 1.69.0 diff --git a/httpclient-simple/pom.xml b/httpclient-simple/pom.xml index f3d00251d7..efcf0452e2 100644 --- a/httpclient-simple/pom.xml +++ b/httpclient-simple/pom.xml @@ -172,7 +172,7 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} provided @@ -295,9 +295,6 @@ - - 1.2 - 3.1.0 19.0 3.5 diff --git a/hystrix/pom.xml b/hystrix/pom.xml index fb044588de..7bb3e98246 100644 --- a/hystrix/pom.xml +++ b/hystrix/pom.xml @@ -64,8 +64,6 @@ 1.5.8 0.20.7 - - 1.3 2.6 2.7 diff --git a/jackson-2/README.md b/jackson-2/README.md index ec147f5fd9..ee9f8458a0 100644 --- a/jackson-2/README.md +++ b/jackson-2/README.md @@ -7,3 +7,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [Mapping Multiple JSON Fields to a Single Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field) +- [How to Process YAML with Jackson](https://www.baeldung.com/jackson-yaml) +- [Working with Tree Model Nodes in Jackson](https://www.baeldung.com/jackson-json-node-tree-model) + diff --git a/jackson-2/src/main/java/com/baeldung/jackson/node/JsonNodeIterator.java b/jackson-2/src/main/java/com/baeldung/jackson/node/JsonNodeIterator.java new file mode 100644 index 0000000000..f582772587 --- /dev/null +++ b/jackson-2/src/main/java/com/baeldung/jackson/node/JsonNodeIterator.java @@ -0,0 +1,62 @@ +package com.baeldung.jackson.node; + +import java.util.Iterator; +import java.util.Map.Entry; + +import com.fasterxml.jackson.databind.JsonNode; + +public class JsonNodeIterator { + + private static final String NEW_LINE = "\n"; + private static final String FIELD_DELIMITER = ": "; + private static final String ARRAY_PREFIX = "- "; + private static final String YAML_PREFIX = " "; + + public String toYaml(JsonNode root) { + StringBuilder yaml = new StringBuilder(); + processNode(root, yaml, 0); + return yaml.toString(); + } + + private void processNode(JsonNode jsonNode, StringBuilder yaml, int depth) { + if (jsonNode.isValueNode()) { + yaml.append(jsonNode.asText()); + } + else if (jsonNode.isArray()) { + for (JsonNode arrayItem : jsonNode) { + appendNodeToYaml(arrayItem, yaml, depth, true); + } + } + else if (jsonNode.isObject()) { + appendNodeToYaml(jsonNode, yaml, depth, false); + } + } + + private void appendNodeToYaml(JsonNode node, StringBuilder yaml, int depth, boolean isArrayItem) { + Iterator> fields = node.fields(); + boolean isFirst = true; + while (fields.hasNext()) { + Entry jsonField = fields.next(); + addFieldNameToYaml(yaml, jsonField.getKey(), depth, isArrayItem && isFirst); + processNode(jsonField.getValue(), yaml, depth+1); + isFirst = false; + } + + } + +private void addFieldNameToYaml(StringBuilder yaml, String fieldName, int depth, boolean isFirstInArray) { + if (yaml.length()>0) { + yaml.append(NEW_LINE); + int requiredDepth = (isFirstInArray) ? depth-1 : depth; + for(int i = 0; i < requiredDepth; i++) { + yaml.append(YAML_PREFIX); + } + if (isFirstInArray) { + yaml.append(ARRAY_PREFIX); + } + } + yaml.append(fieldName); + yaml.append(FIELD_DELIMITER); +} + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/node/ExampleStructure.java b/jackson-2/src/test/java/com/baeldung/jackson/node/ExampleStructure.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/node/ExampleStructure.java rename to jackson-2/src/test/java/com/baeldung/jackson/node/ExampleStructure.java diff --git a/jackson-2/src/test/java/com/baeldung/jackson/node/JsonNodeIteratorUnitTest.java b/jackson-2/src/test/java/com/baeldung/jackson/node/JsonNodeIteratorUnitTest.java new file mode 100644 index 0000000000..05426fc844 --- /dev/null +++ b/jackson-2/src/test/java/com/baeldung/jackson/node/JsonNodeIteratorUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.jackson.node; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.junit.Test; + +import com.fasterxml.jackson.databind.JsonNode; + +public class JsonNodeIteratorUnitTest { + + private JsonNodeIterator onTest = new JsonNodeIterator(); + private static String expectedYaml = "name: \n" + + " first: Tatu\n" + + " last: Saloranta\n" + + "title: Jackson founder\n" + + "company: FasterXML\n" + + "pets: \n" + + "- type: dog\n" + + " number: 1\n" + + "- type: fish\n" + + " number: 50"; + +@Test +public void givenANodeTree_whenIteratingSubNodes_thenWeFindExpected() throws IOException { + final JsonNode rootNode = ExampleStructure.getExampleRoot(); + + String yaml = onTest.toYaml(rootNode); + System.out.println(yaml.toString()); + + assertEquals(expectedYaml, yaml); + +} + + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/node/NodeBean.java b/jackson-2/src/test/java/com/baeldung/jackson/node/NodeBean.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/node/NodeBean.java rename to jackson-2/src/test/java/com/baeldung/jackson/node/NodeBean.java diff --git a/jackson/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java b/jackson-2/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java rename to jackson-2/src/test/java/com/baeldung/jackson/node/NodeOperationUnitTest.java diff --git a/jackson-2/src/test/resources/node_example.json b/jackson-2/src/test/resources/node_example.json new file mode 100644 index 0000000000..d57c1df6e3 --- /dev/null +++ b/jackson-2/src/test/resources/node_example.json @@ -0,0 +1,18 @@ +{ + "name": { + "first": "Tatu", + "last": "Saloranta" + }, + "title": "Jackson founder", + "company": "FasterXML", + "pets": [ + { + "type": "dog", + "number": 1 + }, + { + "type": "fish", + "number": 50 + } + ] +} \ No newline at end of file diff --git a/jackson/README.md b/jackson/README.md index 794ddc04d9..01d9419a27 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -15,7 +15,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Jackson JSON Tutorial](http://www.baeldung.com/jackson) - [Jackson – Working with Maps and nulls](http://www.baeldung.com/jackson-map-null-values-or-null-key) - [Jackson – Decide What Fields Get Serialized/Deserialized](http://www.baeldung.com/jackson-field-serializable-deserializable-or-not) -- [Working with Tree Model Nodes in Jackson](http://www.baeldung.com/jackson-json-node-tree-model) - [Jackson vs Gson](http://www.baeldung.com/jackson-vs-gson) - [XML Serialization and Deserialization with Jackson](http://www.baeldung.com/jackson-xml-serialization-and-deserialization) - [More Jackson Annotations](http://www.baeldung.com/jackson-advanced-annotations) diff --git a/jackson/src/main/resources/node_example.json b/jackson/src/main/resources/node_example.json deleted file mode 100644 index 69d37efbf6..0000000000 --- a/jackson/src/main/resources/node_example.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": - { - "first": "Tatu", - "last": "Saloranta" - }, - - "title": "Jackson founder", - "company": "FasterXML" -} \ No newline at end of file diff --git a/java-collections-maps-2/README.md b/java-collections-maps-2/README.md index 8bcafccfe8..ff84e93ce4 100644 --- a/java-collections-maps-2/README.md +++ b/java-collections-maps-2/README.md @@ -1,2 +1,3 @@ ## Relevant Articles: - [Map of Primitives in Java](https://www.baeldung.com/java-map-primitives) +- [Copying a HashMap in Java](https://www.baeldung.com/java-copy-hashmap) diff --git a/java-dates-2/README.md b/java-dates-2/README.md index a6b5c8e574..35286115d4 100644 --- a/java-dates-2/README.md +++ b/java-dates-2/README.md @@ -1,2 +1,3 @@ ## Relevant Articles: - [Converting Between LocalDate and XMLGregorianCalendar](https://www.baeldung.com/java-localdate-to-xmlgregoriancalendar) +- [Convert Time to Milliseconds in Java](https://www.baeldung.com/java-time-milliseconds) diff --git a/java-ee-8-security-api/app-auth-basic-store-db/pom.xml b/java-ee-8-security-api/app-auth-basic-store-db/pom.xml index cf92fe2ecd..582e82d8bb 100644 --- a/java-ee-8-security-api/app-auth-basic-store-db/pom.xml +++ b/java-ee-8-security-api/app-auth-basic-store-db/pom.xml @@ -53,7 +53,7 @@ com.h2database h2 - ${h2-version} + ${h2.version} jar ${project.build.directory}/liberty/wlp/usr/servers/defaultServer/lib/global @@ -64,8 +64,4 @@ - - - 1.4.197 - diff --git a/java-ee-8-security-api/app-auth-custom-no-store/pom.xml b/java-ee-8-security-api/app-auth-custom-no-store/pom.xml index f9d63f8623..51ee64097a 100644 --- a/java-ee-8-security-api/app-auth-custom-no-store/pom.xml +++ b/java-ee-8-security-api/app-auth-custom-no-store/pom.xml @@ -53,7 +53,7 @@ com.h2database h2 - ${h2-version} + ${h2.version} jar ${project.build.directory}/liberty/wlp/usr/servers/defaultServer/lib/global @@ -64,8 +64,4 @@ - - - 1.4.197 - diff --git a/java-ee-8-security-api/pom.xml b/java-ee-8-security-api/pom.xml index 0cce84e5f2..9b8356714f 100644 --- a/java-ee-8-security-api/pom.xml +++ b/java-ee-8-security-api/pom.xml @@ -72,7 +72,6 @@ 8.0 2.3 18.0.0.1 - 1.4.197 3.2.2 diff --git a/java-numbers/pom.xml b/java-numbers/pom.xml index eb75f85bf0..daed356f66 100644 --- a/java-numbers/pom.xml +++ b/java-numbers/pom.xml @@ -38,7 +38,7 @@ org.openjdk.jmh jmh-generator-annprocess - ${jmh-generator-annprocess.version} + ${jmh-generator.version} org.apache.commons @@ -127,8 +127,6 @@ 1.7.21 1.1.7 - 1.19 - 1.19 2.21.0 3.0.0-M1 diff --git a/java-streams-2/pom.xml b/java-streams-2/pom.xml index 5004249352..3e08e2f432 100644 --- a/java-streams-2/pom.xml +++ b/java-streams-2/pom.xml @@ -18,12 +18,12 @@ org.openjdk.jmh jmh-core - ${jmh.version} + ${jmh-core.version} org.openjdk.jmh jmh-generator-annprocess - ${jmh.version} + ${jmh-generator.version} junit @@ -44,7 +44,6 @@ UTF-8 1.8 1.8 - 1.21 3.11.1 \ No newline at end of file diff --git a/java-streams/pom.xml b/java-streams/pom.xml index 00384eeead..b0c56ecdf9 100644 --- a/java-streams/pom.xml +++ b/java-streams/pom.xml @@ -18,12 +18,12 @@ org.openjdk.jmh jmh-core - ${jmh.version} + ${jmh-core.version} org.openjdk.jmh jmh-generator-annprocess - ${jmh.version} + ${jmh-generator.version} provided @@ -106,7 +106,6 @@ - 1.21 3.5 0.9.0 1.15 diff --git a/java-strings-2/README.MD b/java-strings-2/README.MD new file mode 100644 index 0000000000..edda92221d --- /dev/null +++ b/java-strings-2/README.MD @@ -0,0 +1,4 @@ +## Relevant Articles + +- [Java Localization – Formatting Messages](https://www.baeldung.com/java-localization-messages-formatting) +- [Check If a String Contains a Substring](https://www.baeldung.com/java-string-contains-substring) diff --git a/java-strings-2/pom.xml b/java-strings-2/pom.xml index c314cd8cad..5279cf5777 100755 --- a/java-strings-2/pom.xml +++ b/java-strings-2/pom.xml @@ -83,7 +83,7 @@ org.hamcrest hamcrest-library - ${hamcrest-library.version} + ${org.hamcrest.version} test @@ -136,12 +136,10 @@ 1.10 3.6.1 - 1.19 61.1 27.0.1-jre 4.0.0 5.3.1 - 1.3 1.3.1 1.4 0.4.0 diff --git a/java-strings-2/src/main/java/com/baeldung/localization/App.java b/java-strings-2/src/main/java/com/baeldung/localization/App.java new file mode 100644 index 0000000000..c2b687933d --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/localization/App.java @@ -0,0 +1,21 @@ +package com.baeldung.localization; + +import java.text.ParseException; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +public class App { + + /** + * Runs all available formatter + * @throws ParseException + */ + public static void main(String[] args) { + List locales = Arrays.asList(new Locale[] { Locale.UK, Locale.ITALY, Locale.FRANCE, Locale.forLanguageTag("pl-PL") }); + Localization.run(locales); + JavaSEFormat.run(locales); + ICUFormat.run(locales); + } + +} diff --git a/java-strings-2/src/main/java/com/baeldung/localization/ICUFormat.java b/java-strings-2/src/main/java/com/baeldung/localization/ICUFormat.java new file mode 100644 index 0000000000..f7bc357933 --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/localization/ICUFormat.java @@ -0,0 +1,29 @@ +package com.baeldung.localization; + +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +import com.ibm.icu.text.MessageFormat; + +public class ICUFormat { + + public static String getLabel(Locale locale, Object[] data) { + ResourceBundle bundle = ResourceBundle.getBundle("formats", locale); + String format = bundle.getString("label-icu"); + MessageFormat formatter = new MessageFormat(format, locale); + return formatter.format(data); + } + + public static void run(List locales) { + System.out.println("ICU formatter"); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 0 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 1 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 2 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 3 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 0 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 1 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 2 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 3 }))); + } +} diff --git a/java-strings-2/src/main/java/com/baeldung/localization/JavaSEFormat.java b/java-strings-2/src/main/java/com/baeldung/localization/JavaSEFormat.java new file mode 100644 index 0000000000..c95dfffa13 --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/localization/JavaSEFormat.java @@ -0,0 +1,24 @@ +package com.baeldung.localization; + +import java.text.MessageFormat; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +public class JavaSEFormat { + + public static String getLabel(Locale locale, Object[] data) { + ResourceBundle bundle = ResourceBundle.getBundle("formats", locale); + final String pattern = bundle.getString("label"); + final MessageFormat formatter = new MessageFormat(pattern, locale); + return formatter.format(data); + } + + public static void run(List locales) { + System.out.println("Java formatter"); + final Date date = new Date(System.currentTimeMillis()); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { date, "Alice", 0 }))); + locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { date, "Alice", 2 }))); + } +} diff --git a/java-strings-2/src/main/java/com/baeldung/localization/Localization.java b/java-strings-2/src/main/java/com/baeldung/localization/Localization.java new file mode 100644 index 0000000000..17a6598ce0 --- /dev/null +++ b/java-strings-2/src/main/java/com/baeldung/localization/Localization.java @@ -0,0 +1,18 @@ +package com.baeldung.localization; + +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +public class Localization { + + public static String getLabel(Locale locale) { + final ResourceBundle bundle = ResourceBundle.getBundle("messages", locale); + return bundle.getString("label"); + } + + public static void run(List locales) { + locales.forEach(locale -> System.out.println(getLabel(locale))); + } + +} diff --git a/java-strings-2/src/main/resources/formats_en.properties b/java-strings-2/src/main/resources/formats_en.properties new file mode 100644 index 0000000000..4bea9a74bb --- /dev/null +++ b/java-strings-2/src/main/resources/formats_en.properties @@ -0,0 +1,2 @@ +label=On {0, date, short} {1} has sent you {2, choice, 0#no messages|1#a message|2#two messages|2<{2,number,integer} messages}. +label-icu={0} has sent you {2, plural, =0 {no messages} =1 {a message} other {{2, number, integer} messages}}. diff --git a/java-strings-2/src/main/resources/formats_fr.properties b/java-strings-2/src/main/resources/formats_fr.properties new file mode 100644 index 0000000000..7f509d494e --- /dev/null +++ b/java-strings-2/src/main/resources/formats_fr.properties @@ -0,0 +1,2 @@ +label={0, date, short}, {1}{2, choice, 0# ne|0<} vous a envoy\u00e9 {2, choice, 0#aucun message|1#un message|2#deux messages|2<{2,number,integer} messages}. +label-icu={0} {2, plural, =0 {ne } other {}}vous a envoy\u00e9 {2, plural, =0 {aucun message} =1 {un message} other {{2, number, integer} messages}}. diff --git a/java-strings-2/src/main/resources/formats_it.properties b/java-strings-2/src/main/resources/formats_it.properties new file mode 100644 index 0000000000..fe061ae1b6 --- /dev/null +++ b/java-strings-2/src/main/resources/formats_it.properties @@ -0,0 +1,2 @@ +label={0, date, short} {1} ti ha inviato {2, choice, 0#nessun messagio|1#un messaggio|2#due messaggi|2<{2, number, integer} messaggi}. +label-icu={0} {2, plural, =0 {non } other {}}ti ha inviato {2, plural, =0 {nessun messaggio} =1 {un messaggio} other {{2, number, integer} messaggi}}. diff --git a/java-strings-2/src/main/resources/formats_pl.properties b/java-strings-2/src/main/resources/formats_pl.properties new file mode 100644 index 0000000000..9333ec3396 --- /dev/null +++ b/java-strings-2/src/main/resources/formats_pl.properties @@ -0,0 +1,2 @@ +label=W {0, date, short} {1}{2, choice, 0# nie|0<} wys\u0142a\u0142a ci {2, choice, 0#\u017Cadnych wiadomo\u015Bci|1#wiadomo\u015B\u0107|2#dwie wiadomo\u015Bci|2<{2, number, integer} wiadomo\u015Bci}. +label-icu={0} {2, plural, =0 {nie } other {}}{1, select, male {wys\u0142a\u0142} female {wys\u0142a\u0142a} other {wys\u0142a\u0142o}} ci {2, plural, =0 {\u017Cadnej wiadomo\u015Bci} =1 {wiadomo\u015B\u0107} other {{2, number, integer} wiadomo\u015Bci}}. diff --git a/java-strings-2/src/main/resources/messages_en.properties b/java-strings-2/src/main/resources/messages_en.properties new file mode 100644 index 0000000000..bcbca9483c --- /dev/null +++ b/java-strings-2/src/main/resources/messages_en.properties @@ -0,0 +1 @@ +label=Alice has sent you a message. diff --git a/java-strings-2/src/main/resources/messages_fr.properties b/java-strings-2/src/main/resources/messages_fr.properties new file mode 100644 index 0000000000..15ad031a30 --- /dev/null +++ b/java-strings-2/src/main/resources/messages_fr.properties @@ -0,0 +1 @@ +label=Alice vous a envoy\u00e9 un message. diff --git a/java-strings-2/src/main/resources/messages_it.properties b/java-strings-2/src/main/resources/messages_it.properties new file mode 100644 index 0000000000..93b99a9483 --- /dev/null +++ b/java-strings-2/src/main/resources/messages_it.properties @@ -0,0 +1 @@ +label=Alice ti ha inviato un messaggio. diff --git a/java-strings-2/src/main/resources/messages_pl.properties b/java-strings-2/src/main/resources/messages_pl.properties new file mode 100644 index 0000000000..a64066deea --- /dev/null +++ b/java-strings-2/src/main/resources/messages_pl.properties @@ -0,0 +1 @@ +label=Alice wys\u0142a\u0142a ci wiadomo\u015B\u0107. diff --git a/java-strings-2/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java b/java-strings-2/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java new file mode 100644 index 0000000000..2c8f9b47f3 --- /dev/null +++ b/java-strings-2/src/test/java/com/baeldung/localization/ICUFormatUnitTest.java @@ -0,0 +1,74 @@ +package com.baeldung.localization; + +import static org.junit.Assert.assertEquals; + +import java.util.Locale; + +import org.junit.Test; + +import com.baeldung.localization.ICUFormat; + +public class ICUFormatUnitTest { + + @Test + public void givenInUK_whenAliceSendsNothing_thenCorrectMessage() { + assertEquals("Alice has sent you no messages.", ICUFormat.getLabel(Locale.UK, new Object[] { "Alice", "female", 0 })); + } + + @Test + public void givenInUK_whenAliceSendsOneMessage_thenCorrectMessage() { + assertEquals("Alice has sent you a message.", ICUFormat.getLabel(Locale.UK, new Object[] { "Alice", "female", 1 })); + } + + @Test + public void givenInUK_whenBobSendsSixMessages_thenCorrectMessage() { + assertEquals("Bob has sent you 6 messages.", ICUFormat.getLabel(Locale.UK, new Object[] { "Bob", "male", 6 })); + } + + @Test + public void givenInItaly_whenAliceSendsNothing_thenCorrectMessage() { + assertEquals("Alice non ti ha inviato nessun messaggio.", ICUFormat.getLabel(Locale.ITALY, new Object[] { "Alice", "female", 0 })); + } + + @Test + public void givenInItaly_whenAliceSendsOneMessage_thenCorrectMessage() { + assertEquals("Alice ti ha inviato un messaggio.", ICUFormat.getLabel(Locale.ITALY, new Object[] { "Alice", "female", 1 })); + } + + @Test + public void givenInItaly_whenBobSendsSixMessages_thenCorrectMessage() { + assertEquals("Bob ti ha inviato 6 messaggi.", ICUFormat.getLabel(Locale.ITALY, new Object[] { "Bob", "male", 6 })); + } + + @Test + public void givenInFrance_whenAliceSendsNothing_thenCorrectMessage() { + assertEquals("Alice ne vous a envoyé aucun message.", ICUFormat.getLabel(Locale.FRANCE, new Object[] { "Alice", "female", 0 })); + } + + @Test + public void givenInFrance_whenAliceSendsOneMessage_thenCorrectMessage() { + assertEquals("Alice vous a envoyé un message.", ICUFormat.getLabel(Locale.FRANCE, new Object[] { "Alice", "female", 1 })); + } + + @Test + public void givenInFrance_whenBobSendsSixMessages_thenCorrectMessage() { + assertEquals("Bob vous a envoyé 6 messages.", ICUFormat.getLabel(Locale.FRANCE, new Object[] { "Bob", "male", 6 })); + } + + + @Test + public void givenInPoland_whenAliceSendsNothing_thenCorrectMessage() { + assertEquals("Alice nie wysłała ci żadnej wiadomości.", ICUFormat.getLabel(Locale.forLanguageTag("pl-PL"), new Object[] { "Alice", "female", 0 })); + } + + @Test + public void givenInPoland_whenAliceSendsOneMessage_thenCorrectMessage() { + assertEquals("Alice wysłała ci wiadomość.", ICUFormat.getLabel(Locale.forLanguageTag("pl-PL"), new Object[] { "Alice", "female", 1 })); + } + + @Test + public void givenInPoland_whenBobSendsSixMessages_thenCorrectMessage() { + assertEquals("Bob wysłał ci 6 wiadomości.", ICUFormat.getLabel(Locale.forLanguageTag("pl-PL"), new Object[] { "Bob", "male", 6 })); + } + +} diff --git a/java-strings/pom.xml b/java-strings/pom.xml index 4555b8ad4a..7f66b95355 100755 --- a/java-strings/pom.xml +++ b/java-strings/pom.xml @@ -50,7 +50,7 @@ org.openjdk.jmh jmh-generator-annprocess - ${jmh-core.version} + ${jmh-generator.version} com.ibm.icu @@ -79,7 +79,7 @@ org.hamcrest hamcrest-library - ${hamcrest-library.version} + ${org.hamcrest.version} test @@ -132,12 +132,10 @@ 1.10 3.6.1 - 1.19 61.1 27.0.1-jre 4.0.0 5.3.1 - 1.3 1.3.1 1.4 0.4.0 diff --git a/javax-servlets/pom.xml b/javax-servlets/pom.xml index bf85feb7ce..e3d8a430d9 100644 --- a/javax-servlets/pom.xml +++ b/javax-servlets/pom.xml @@ -48,7 +48,7 @@ javax.servlet.jsp javax.servlet.jsp-api - ${jsp.version} + ${javax.servlet.jsp-api.version} javax.servlet @@ -90,7 +90,5 @@ 1.3.3 2.6 4.0.1 - 1.2 - 2.3.1 diff --git a/jee-7/pom.xml b/jee-7/pom.xml index 62ccb9d313..d389b57cd5 100644 --- a/jee-7/pom.xml +++ b/jee-7/pom.xml @@ -527,10 +527,8 @@ 2.2.14 4.5 2.0.1.Final - 3.1.0 2.1.0.Final 2.8 - 1.2 2.2 20160715 1.0.0.Final @@ -538,7 +536,6 @@ 1.0.0.Final 1.4.2.Final 2.1.1.Final - 1.4.178 2.22.1 diff --git a/jee-7/src/main/java/com/baeldung/singleton/Car.java b/jee-7/src/main/java/com/baeldung/singleton/Car.java new file mode 100644 index 0000000000..0cf7281294 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/singleton/Car.java @@ -0,0 +1,28 @@ +package com.baeldung.singleton; + +public class Car { + + private String type; + private String model; + private boolean serviced = false; + + public Car(String type, String model) { + super(); + this.type = type; + this.model = model; + } + + public boolean isServiced () { + return serviced; + } + + public void setServiced(Boolean serviced) { + this.serviced = serviced; + } + + @Override + public String toString() { + return "Car [type=" + type + ", model=" + model + "]"; + } + +} diff --git a/jee-7/src/main/java/com/baeldung/singleton/CarServiceBean.java b/jee-7/src/main/java/com/baeldung/singleton/CarServiceBean.java new file mode 100644 index 0000000000..b824882d5d --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/singleton/CarServiceBean.java @@ -0,0 +1,23 @@ +package com.baeldung.singleton; + +import java.util.UUID; + +import javax.enterprise.context.Dependent; + +import org.springframework.web.context.annotation.RequestScope; + +@RequestScope +public class CarServiceBean { + + private UUID id = UUID.randomUUID(); + + public UUID getId() { + return this.id; + } + + @Override + public String toString() { + return "CarService [id=" + id + "]"; + } + +} diff --git a/jee-7/src/main/java/com/baeldung/singleton/CarServiceEjbSingleton.java b/jee-7/src/main/java/com/baeldung/singleton/CarServiceEjbSingleton.java new file mode 100644 index 0000000000..1bbffdd61e --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/singleton/CarServiceEjbSingleton.java @@ -0,0 +1,46 @@ +package com.baeldung.singleton; + +import java.util.UUID; + +import javax.ejb.Singleton; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Singleton +public class CarServiceEjbSingleton { + + private static Logger LOG = LoggerFactory.getLogger(CarServiceEjbSingleton.class); + + private UUID id = UUID.randomUUID(); + + private static int serviceQueue; + + public UUID getId() { + return this.id; + } + + @Override + public String toString() { + return "CarServiceEjbSingleton [id=" + id + "]"; + } + + public int service(Car car) { + serviceQueue++; + LOG.info("Car {} is being serviced @ CarServiceEjbSingleton - serviceQueue: {}", car, serviceQueue); + simulateService(car); + serviceQueue--; + LOG.info("Car service for {} is completed - serviceQueue: {}", car, serviceQueue); + return serviceQueue; + } + + private void simulateService(Car car) { + try { + Thread.sleep(100); + car.setServiced(true); + } catch (InterruptedException e) { + LOG.error("CarServiceEjbSingleton::InterruptedException: {}", e); + } + } + +} diff --git a/jee-7/src/main/java/com/baeldung/singleton/CarServiceSingleton.java b/jee-7/src/main/java/com/baeldung/singleton/CarServiceSingleton.java new file mode 100644 index 0000000000..223d139346 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/singleton/CarServiceSingleton.java @@ -0,0 +1,47 @@ +package com.baeldung.singleton; + +import java.util.UUID; + +import javax.inject.Singleton; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Singleton +public class CarServiceSingleton { + + private static Logger LOG = LoggerFactory.getLogger(CarServiceSingleton.class); + + private UUID id = UUID.randomUUID(); + + private static int serviceQueue; + + public UUID getId() { + return this.id; + } + + @Override + public String toString() { + return "CarServiceSingleton [id=" + id + "]"; + } + + public int service(Car car) { + serviceQueue++; + LOG.info("Car {} is being serviced @ CarServiceSingleton - serviceQueue: {}", car, serviceQueue); + simulateService(car); + serviceQueue--; + LOG.info("Car service for {} is completed - serviceQueue: {}", car, serviceQueue); + return serviceQueue; + + } + + private void simulateService(Car car) { + try { + Thread.sleep(100); + car.setServiced(true); + } catch (InterruptedException e) { + LOG.error("CarServiceSingleton::InterruptedException: {}", e); + } + } + +} diff --git a/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java b/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java new file mode 100644 index 0000000000..b828296dca --- /dev/null +++ b/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java @@ -0,0 +1,142 @@ +package com.baeldung.singleton; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.ejb.EJB; +import javax.inject.Inject; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@RunWith(Arquillian.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class CarServiceIntegrationTest { + + public static final Logger LOG = LoggerFactory.getLogger(CarServiceIntegrationTest.class); + + @Deployment + public static JavaArchive createDeployment() { + return ShrinkWrap.create(JavaArchive.class) + .addClasses(CarServiceBean.class, CarServiceSingleton.class, CarServiceEjbSingleton.class, Car.class) + .addAsResource("META-INF/persistence.xml") + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + @Inject + private CarServiceBean carServiceBean; + + @Inject + private CarServiceSingleton carServiceSingleton; + + @EJB + private CarServiceEjbSingleton carServiceEjbSingleton; + + private static Map idMap = new HashMap<>(); + + @Before + public void setUp() { + // populate idMap only on first run + if (idMap.isEmpty()) { + LOG.info("setUp::carServiceBean: {}", carServiceBean.getId()); + idMap.put("carServiceBeanId", carServiceBean.getId()); + + LOG.info("setUp::carServiceSingleton: {}", carServiceSingleton.getId()); + idMap.put("carServiceSingletonId", carServiceSingleton.getId()); + + LOG.info("setUp::carServiceEjbSingleton: {}", carServiceEjbSingleton.getId()); + idMap.put("carServiceEjbSingletonId", carServiceEjbSingleton.getId()); + } + } + + @Test + public void givenRun1_whenGetId_thenSingletonIdEqual() { + int testRun = 1; + + assertNotNull(carServiceBean); + assertNotNull(carServiceSingleton); + assertNotNull(carServiceEjbSingleton); + + UUID carServiceBeanId = carServiceBean.getId(); + assertEquals(idMap.get("carServiceBeanId"), carServiceBeanId); + LOG.info("Test run {}::carServiceBeanId: {}", testRun, carServiceBeanId); + + UUID carServiceSingletonId = carServiceSingleton.getId(); + assertEquals(idMap.get("carServiceSingletonId"), carServiceSingletonId); + LOG.info("Test run {}::carServiceSingletonId: {}", testRun, carServiceSingletonId); + + UUID carServiceEjbSingletonId = carServiceEjbSingleton.getId(); + assertEquals(idMap.get("carServiceEjbSingletonId"), carServiceEjbSingletonId); + LOG.info("Test run {}::carServiceEjbSingletonId: {}", testRun, carServiceEjbSingletonId); + } + + @Test + public void givenRun2_whenGetId_thenSingletonIdEqual() { + int testRun = 2; + + assertNotNull(carServiceBean); + assertNotNull(carServiceSingleton); + assertNotNull(carServiceEjbSingleton); + + UUID carServiceBeanId = carServiceBean.getId(); + assertNotEquals(idMap.get("carServiceBeanId"), carServiceBeanId); + LOG.info("Test run {}::carServiceBeanId: {}", testRun, carServiceBeanId); + + UUID carServiceSingletonId = carServiceSingleton.getId(); + assertEquals(idMap.get("carServiceSingletonId"), carServiceSingletonId); + LOG.info("Test run {}::carServiceSingletonId: {}", testRun, carServiceSingletonId); + + UUID carServiceEjbSingletonId = carServiceEjbSingleton.getId(); + assertEquals(idMap.get("carServiceEjbSingletonId"), carServiceEjbSingletonId); + LOG.info("Test run {}::carServiceEjbSingletonId: {}", testRun, carServiceEjbSingletonId); + } + + @Test + public void givenRun3_whenSingleton_thenNoLocking() { + for (int i = 0; i < 10; i++) { + new Thread(new Runnable() { + @Override + public void run() { + String model = Double.toString(Math.round(Math.random() * 100)); + Car car = new Car("Speedster", model); + int serviceQueue = carServiceSingleton.service(car); + assertTrue(serviceQueue < 10); + } + }).start(); + } + return; + } + + @Test + public void givenRun4_whenEjb_thenLocking() { + for (int i = 0; i < 10; i++) { + new Thread(new Runnable() { + @Override + public void run() { + String model = Double.toString(Math.round(Math.random() * 100)); + Car car = new Car("Speedster", model); + int serviceQueue = carServiceEjbSingleton.service(car); + assertEquals(0, serviceQueue); + } + }).start(); + } + return; + } + +} \ No newline at end of file diff --git a/jhipster-5/README.md b/jhipster-5/README.md new file mode 100644 index 0000000000..0537f5b1a5 --- /dev/null +++ b/jhipster-5/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Creating New APIs and Views in JHipster](https://www.baeldung.com/jhipster-new-apis-and-views) diff --git a/jsf/pom.xml b/jsf/pom.xml index fc6d4a0ee2..19f1265250 100644 --- a/jsf/pom.xml +++ b/jsf/pom.xml @@ -67,7 +67,7 @@ javax.servlet javax.servlet-api provided - ${javax.servlet.version} + ${javax.servlet-api.version} @@ -99,11 +99,6 @@ 2.2.14 3.0.0 - - 3.1.0 - - 1.2 - 2.6 diff --git a/jta/pom.xml b/jta/pom.xml index 6a31733996..b7e39c66e1 100644 --- a/jta/pom.xml +++ b/jta/pom.xml @@ -83,7 +83,6 @@ UTF-8 UTF-8 - 1.8 2.4.1 2.0.4.RELEASE diff --git a/kotlin-libraries/build.gradle b/kotlin-libraries/build.gradle index b244df34b0..afb92de49e 100644 --- a/kotlin-libraries/build.gradle +++ b/kotlin-libraries/build.gradle @@ -7,6 +7,7 @@ version '1.0-SNAPSHOT' buildscript { ext.kotlin_version = '1.2.41' ext.ktor_version = '0.9.2' + ext.khttp_version = '0.1.0' repositories { mavenCentral() @@ -47,11 +48,16 @@ dependencies { compile "io.ktor:ktor-server-netty:$ktor_version" compile "ch.qos.logback:logback-classic:1.2.1" compile "io.ktor:ktor-gson:$ktor_version" + compile "khttp:khttp:$khttp_version" testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile group: 'org.jetbrains.spek', name: 'spek-api', version: '1.1.5' + testCompile group: 'org.jetbrains.spek', name: 'spek-subject-extension', version: '1.1.5' + testCompile group: 'org.jetbrains.spek', name: 'spek-junit-platform-engine', version: '1.1.5' implementation 'com.beust:klaxon:3.0.1' + implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0' } task runServer(type: JavaExec) { main = 'APIServer' classpath = sourceSets.main.runtimeClasspath -} \ No newline at end of file +} diff --git a/kotlin-libraries/pom.xml b/kotlin-libraries/pom.xml index 3d2c7337b0..b75c77f358 100644 --- a/kotlin-libraries/pom.xml +++ b/kotlin-libraries/pom.xml @@ -166,6 +166,12 @@ 2.6 compile + + + io.reactivex.rxjava2 + rxkotlin + 2.3.0 + diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt new file mode 100644 index 0000000000..979ed3f809 --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt @@ -0,0 +1,157 @@ +package com.baeldung.kotlin.rxkotlin + +import io.reactivex.Maybe +import io.reactivex.Observable +import io.reactivex.functions.BiFunction +import io.reactivex.rxkotlin.* +import io.reactivex.subjects.PublishSubject +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse + +class RxKotlinTest { + + @Test + fun whenBooleanArrayToObserver_thenBooleanObserver() { + val observable = listOf(true, false, false).toObservable() + observable.test().assertValues(true, false, false) + } + + @Test + fun whenBooleanArrayToFlowable_thenBooleanFlowable() { + val flowable = listOf(true, false, false).toFlowable() + flowable.buffer(2).test().assertValues(listOf(true, false), listOf(false)) + } + + @Test + fun whenIntArrayToObserver_thenIntObserver() { + val observable = listOf(1, 1, 2, 3).toObservable() + observable.test().assertValues(1, 1, 2, 3) + } + + @Test + fun whenIntArrayToFlowable_thenIntFlowable() { + val flowable = listOf(1, 1, 2, 3).toFlowable() + flowable.buffer(2).test().assertValues(listOf(1, 1), listOf(2, 3)) + } + + @Test + fun whenObservablePairToMap_thenSingleNoDuplicates() { + val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4)) + val observable = list.toObservable() + val map = observable.toMap() + assertEquals(mapOf(Pair("a", 4), Pair("b", 2), Pair("c", 3)), map.blockingGet()) + } + + @Test + fun whenObservablePairToMap_thenSingleWithDuplicates() { + val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4)) + val observable = list.toObservable() + val map = observable.toMultimap() + assertEquals( + mapOf(Pair("a", listOf(1, 4)), Pair("b", listOf(2)), Pair("c", listOf(3))), + map.blockingGet()) + } + + @Test + fun whenMergeAll_thenStream() { + val subject = PublishSubject.create>() + val observable = subject.mergeAll() + val testObserver = observable.test() + subject.onNext(Observable.just("first", "second")) + testObserver.assertValues("first", "second") + subject.onNext(Observable.just("third", "fourth")) + subject.onNext(Observable.just("fifth")) + testObserver.assertValues("first", "second", "third", "fourth", "fifth") + } + + @Test + fun whenConcatAll_thenStream() { + val subject = PublishSubject.create>() + val observable = subject.concatAll() + val testObserver = observable.test() + subject.onNext(Observable.just("first", "second")) + testObserver.assertValues("first", "second") + subject.onNext(Observable.just("third", "fourth")) + subject.onNext(Observable.just("fifth")) + testObserver.assertValues("first", "second", "third", "fourth", "fifth") + } + + @Test + fun whenSwitchLatest_thenStream() { + val subject = PublishSubject.create>() + val observable = subject.switchLatest() + val testObserver = observable.test() + subject.onNext(Observable.just("first", "second")) + testObserver.assertValues("first", "second") + subject.onNext(Observable.just("third", "fourth")) + subject.onNext(Observable.just("fifth")) + testObserver.assertValues("first", "second", "third", "fourth", "fifth") + } + + @Test + fun whenMergeAllMaybes_thenObservable() { + val subject = PublishSubject.create>() + val observable = subject.mergeAllMaybes() + val testObserver = observable.test() + subject.onNext(Maybe.just(1)) + subject.onNext(Maybe.just(2)) + subject.onNext(Maybe.empty()) + testObserver.assertValues(1, 2) + subject.onNext(Maybe.error(Exception(""))) + subject.onNext(Maybe.just(3)) + testObserver.assertValues(1, 2).assertError(Exception::class.java) + } + + @Test + fun whenMerge_thenStream() { + val observables = mutableListOf(Observable.just("first", "second")) + val observable = observables.merge() + observables.add(Observable.just("third", "fourth")) + observables.add(Observable.error(Exception("e"))) + observables.add(Observable.just("fifth")) + + observable.test().assertValues("first", "second", "third", "fourth").assertError(Exception::class.java) + } + + @Test + fun whenMergeDelayError_thenStream() { + val observables = mutableListOf>(Observable.error(Exception("e1"))) + val observable = observables.mergeDelayError() + observables.add(Observable.just("1", "2")) + observables.add(Observable.error(Exception("e2"))) + observables.add(Observable.just("3")) + + observable.test().assertValues("1", "2", "3").assertError(Exception::class.java) + } + + @Test + fun whenCast_thenUniformType() { + val observable = Observable.just(1, 1, 2, 3) + observable.cast().test().assertValues(1, 1, 2, 3) + } + + @Test + fun whenOfType_thenFilter() { + val observable = Observable.just(1, "and", 2, "and") + observable.ofType().test().assertValues(1, 2) + } + + @Test + fun whenFunction_thenCompletable() { + var value = 0 + val completable = { value = 3 }.toCompletable() + assertFalse(completable.test().isCancelled) + assertEquals(3, value) + } + + @Test + fun whenHelper_thenMoreIdiomaticKotlin() { + val zipWith = Observable.just(1).zipWith(Observable.just(2)) { a, b -> a + b } + zipWith.subscribeBy(onNext = { println(it) }) + val zip = Observables.zip(Observable.just(1), Observable.just(2)) { a, b -> a + b } + zip.subscribeBy(onNext = { println(it) }) + val zipOrig = Observable.zip(Observable.just(1), Observable.just(2), BiFunction { a, b -> a + b }) + zipOrig.subscribeBy(onNext = { println(it) }) + } +} diff --git a/libraries-2/README.md b/libraries-2/README.md index 3d5dba80ee..8243b9f82c 100644 --- a/libraries-2/README.md +++ b/libraries-2/README.md @@ -1,3 +1,7 @@ -## Relevant Articles +### Relevant Articles: + +- [A Guide to jBPM with Java](https://www.baeldung.com/jbpm-java) - [Guide to Classgraph Library](https://www.baeldung.com/classgraph) +- [Create a Java Command Line Program with Picocli](https://www.baeldung.com/java-picocli-create-command-line-program) + diff --git a/libraries-apache-commons/pom.xml b/libraries-apache-commons/pom.xml index c7ff918af9..cb5990df22 100644 --- a/libraries-apache-commons/pom.xml +++ b/libraries-apache-commons/pom.xml @@ -95,14 +95,11 @@ 3.6.2 2.5 1.6 - 1.4.196 4.1 - 4.12 2.0.0.0 1.10.L001 3.5.2 3.6 - 1.3 3.6.1 diff --git a/libraries-data/pom.xml b/libraries-data/pom.xml index 85be66c067..3276ebcdbb 100644 --- a/libraries-data/pom.xml +++ b/libraries-data/pom.xml @@ -432,9 +432,7 @@ 1.2.2 4.0.1 - 1.4.196 16.5.1 - 3.7.0 5.0 1.0.0 2.4.0 diff --git a/linkrest/pom.xml b/linkrest/pom.xml index 073a173aff..b3d3bd374e 100644 --- a/linkrest/pom.xml +++ b/linkrest/pom.xml @@ -73,7 +73,6 @@ 2.9 4.0.B1 - 1.4.196 2.25.1 diff --git a/logging-modules/log-mdc/pom.xml b/logging-modules/log-mdc/pom.xml index 3031274d0b..ae658e034e 100644 --- a/logging-modules/log-mdc/pom.xml +++ b/logging-modules/log-mdc/pom.xml @@ -29,13 +29,13 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} provided com.fasterxml.jackson.core jackson-databind - ${jackson.library} + ${jackson.version} @@ -98,12 +98,9 @@ - 1.2.17 2.7 3.3.6 3.3.0.Final - 3.1.0 - 2.9.7 2.4 diff --git a/logging-modules/log4j2/pom.xml b/logging-modules/log4j2/pom.xml index 924abfd346..14420356de 100644 --- a/logging-modules/log4j2/pom.xml +++ b/logging-modules/log4j2/pom.xml @@ -115,8 +115,6 @@ - 2.9.7 - 1.4.193 2.1.1 2.11.0 yyyyMMddHHmmss diff --git a/logging-modules/logback/README.md b/logging-modules/logback/README.md index df55492b69..58dc8ce541 100644 --- a/logging-modules/logback/README.md +++ b/logging-modules/logback/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Get Log Output in JSON](https://www.baeldung.com/java-log-json-output) +- [SLF4J Warning: Class Path Contains Multiple SLF4J Bindings](https://www.baeldung.com/slf4j-classpath-multiple-bindings) diff --git a/logging-modules/logback/pom.xml b/logging-modules/logback/pom.xml index 41a28ffd17..22a89124b5 100644 --- a/logging-modules/logback/pom.xml +++ b/logging-modules/logback/pom.xml @@ -58,7 +58,6 @@ 1.2.3 0.1.5 - 2.9.7 3.3.5 diff --git a/lucene/pom.xml b/lucene/pom.xml index f427cfd8a7..3d1ce61782 100644 --- a/lucene/pom.xml +++ b/lucene/pom.xml @@ -32,8 +32,6 @@ - - 1.16.18 1.0.0.Final diff --git a/parent-spring-5/pom.xml b/parent-spring-5/pom.xml index 3178682d34..84df8cf30a 100644 --- a/parent-spring-5/pom.xml +++ b/parent-spring-5/pom.xml @@ -31,7 +31,6 @@ 5.1.4.RELEASE 5.0.2 - 2.9.6 5.1.4.RELEASE diff --git a/patterns/pom.xml b/patterns/pom.xml index bf302a7a74..875af67d55 100644 --- a/patterns/pom.xml +++ b/patterns/pom.xml @@ -51,7 +51,6 @@ - 3.1.0 3.0.0 9.4.0.v20161208 diff --git a/performance-tests/pom.xml b/performance-tests/pom.xml index 7d77c2a0e3..d7738780bf 100644 --- a/performance-tests/pom.xml +++ b/performance-tests/pom.xml @@ -46,12 +46,12 @@ org.openjdk.jmh jmh-core - ${jmh.version} + ${jmh-core.version} org.openjdk.jmh jmh-generator-annprocess - ${jmh.version} + ${jmh-generator.version} @@ -85,7 +85,6 @@ 1.2.0.Final 1.1.0 1.6.0.1 - 1.20 1.2.0.Final diff --git a/persistence-modules/README.md b/persistence-modules/README.md index 2fbaf25f2f..e9a7d625cc 100644 --- a/persistence-modules/README.md +++ b/persistence-modules/README.md @@ -5,7 +5,6 @@ ### Relevant Articles: - [Introduction to Hibernate Search](http://www.baeldung.com/hibernate-search) -- [Bootstrapping Hibernate 5 with Spring](http://www.baeldung.com/hibernate-5-spring) - [Introduction to Lettuce – the Java Redis Client](http://www.baeldung.com/java-redis-lettuce) - [A Guide to Jdbi](http://www.baeldung.com/jdbi) - [Pessimistic Locking in JPA](http://www.baeldung.com/jpa-pessimistic-locking) @@ -13,3 +12,6 @@ - [Spring Data with Reactive Cassandra](https://www.baeldung.com/spring-data-cassandra-reactive) - [Spring Data JPA – Derived Delete Methods](https://www.baeldung.com/spring-data-jpa-deleteby) - [Difference Between save() and saveAndFlush() in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-save-saveandflush) +- [Spring Boot with Hibernate](https://www.baeldung.com/spring-boot-hibernate) +- [Persisting Maps with Hibernate](https://www.baeldung.com/hibernate-persisting-maps) +- [Difference Between @Size, @Length, and @Column(length=value)](https://www.baeldung.com/jpa-size-length-column-differences) diff --git a/persistence-modules/core-java-persistence/README.md b/persistence-modules/core-java-persistence/README.md index 26bd4bf00f..1187cc15c4 100644 --- a/persistence-modules/core-java-persistence/README.md +++ b/persistence-modules/core-java-persistence/README.md @@ -8,3 +8,4 @@ - [Introduction to the JDBC RowSet Interface in Java](http://www.baeldung.com/java-jdbc-rowset) - [A Simple Guide to Connection Pooling in Java](https://www.baeldung.com/java-connection-pooling) - [Guide to the JDBC ResultSet Interface](https://www.baeldung.com/jdbc-resultset) +- [Types of SQL Joins](https://www.baeldung.com/sql-joins) diff --git a/persistence-modules/core-java-persistence/pom.xml b/persistence-modules/core-java-persistence/pom.xml index 2ad2083fec..2760489ce1 100644 --- a/persistence-modules/core-java-persistence/pom.xml +++ b/persistence-modules/core-java-persistence/pom.xml @@ -30,7 +30,7 @@ com.h2database h2 - ${h2database.version} + ${h2.version} org.apache.commons @@ -73,7 +73,6 @@ 42.2.5.jre7 8.0.15 3.10.0 - 1.4.197 2.4.0 3.2.0 0.9.5.2 diff --git a/persistence-modules/deltaspike/pom.xml b/persistence-modules/deltaspike/pom.xml index 9a4669102a..4dcef07695 100644 --- a/persistence-modules/deltaspike/pom.xml +++ b/persistence-modules/deltaspike/pom.xml @@ -317,7 +317,6 @@ 2.6 1.1.3 1.2.5.Final-redhat-1 - 1.4.197 3.5 diff --git a/persistence-modules/flyway/pom.xml b/persistence-modules/flyway/pom.xml index eb827f5675..99549ee3fc 100644 --- a/persistence-modules/flyway/pom.xml +++ b/persistence-modules/flyway/pom.xml @@ -65,7 +65,6 @@ 5.0.2 5.0.2 - 1.4.195 diff --git a/persistence-modules/hibernate-mapping/README.md b/persistence-modules/hibernate-mapping/README.md new file mode 100644 index 0000000000..223d93e1ed --- /dev/null +++ b/persistence-modules/hibernate-mapping/README.md @@ -0,0 +1,4 @@ + +### Relevant Articles: + +- [Persisting Maps with Hibernate](https://www.baeldung.com/hibernate-persisting-maps) diff --git a/persistence-modules/hibernate-mapping/pom.xml b/persistence-modules/hibernate-mapping/pom.xml index fdc82a5275..6bab3c5b1f 100644 --- a/persistence-modules/hibernate-mapping/pom.xml +++ b/persistence-modules/hibernate-mapping/pom.xml @@ -29,7 +29,7 @@ com.h2database h2 - ${h2database.version} + ${h2.version} @@ -61,7 +61,6 @@ 5.3.7.Final - 1.4.196 3.8.0 5.3.3.Final 2.2.5 diff --git a/persistence-modules/hibernate5/pom.xml b/persistence-modules/hibernate5/pom.xml index c7f08e50d5..8799317e9c 100644 --- a/persistence-modules/hibernate5/pom.xml +++ b/persistence-modules/hibernate5/pom.xml @@ -30,7 +30,7 @@ com.h2database h2 - ${h2database.version} + ${h2.version} org.hibernate @@ -104,9 +104,7 @@ 5.3.7.Final 6.0.6 2.2.3 - 1.4.196 3.8.0 - 2.9.7 1.21 diff --git a/persistence-modules/influxdb/pom.xml b/persistence-modules/influxdb/pom.xml index 8e1aeebe6d..a8ecaadd62 100644 --- a/persistence-modules/influxdb/pom.xml +++ b/persistence-modules/influxdb/pom.xml @@ -33,7 +33,6 @@ 2.8 - 1.16.18 diff --git a/persistence-modules/java-jpa/README.md b/persistence-modules/java-jpa/README.md index 5be1015942..34d03b3259 100644 --- a/persistence-modules/java-jpa/README.md +++ b/persistence-modules/java-jpa/README.md @@ -2,8 +2,9 @@ - [A Guide to SqlResultSetMapping](http://www.baeldung.com/jpa-sql-resultset-mapping) - [A Guide to Stored Procedures with JPA](http://www.baeldung.com/jpa-stored-procedures) -- [Fixing the JPA error “java.lang.String cannot be cast to [Ljava.lang.String;”]](https://www.baeldung.com/jpa-error-java-lang-string-cannot-be-cast) +- [Fixing the JPA error “java.lang.String cannot be cast to Ljava.lang.String;”](https://www.baeldung.com/jpa-error-java-lang-string-cannot-be-cast) - [JPA Entity Graph](https://www.baeldung.com/jpa-entity-graph) - [JPA 2.2 Support for Java 8 Date/Time Types](https://www.baeldung.com/jpa-java-time) - [Converting Between LocalDate and SQL Date](https://www.baeldung.com/java-convert-localdate-sql-date) - [Combining JPA And/Or Criteria Predicates](https://www.baeldung.com/jpa-and-or-criteria-predicates) +- [Types of JPA Queries](https://www.baeldung.com/jpa-queries) diff --git a/persistence-modules/java-jpa/pom.xml b/persistence-modules/java-jpa/pom.xml index fa47d6bd9c..f23040fbdc 100644 --- a/persistence-modules/java-jpa/pom.xml +++ b/persistence-modules/java-jpa/pom.xml @@ -49,7 +49,6 @@ 5.4.0.Final - 1.4.197 2.7.4-RC1 42.2.5 diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/basicannotation/Course.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/basicannotation/Course.java new file mode 100644 index 0000000000..cc5a83420c --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/basicannotation/Course.java @@ -0,0 +1,33 @@ +package com.baeldung.jpa.basicannotation; + +import javax.persistence.Basic; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; + +@Entity +public class Course { + + @Id + private int id; + + @Basic(optional = false, fetch = FetchType.LAZY) + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} + diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/jpadefaultvalues/application/User.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/defaultvalues/User.java similarity index 93% rename from persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/jpadefaultvalues/application/User.java rename to persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/defaultvalues/User.java index e271c01815..436c708d40 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/jpadefaultvalues/application/User.java +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/defaultvalues/User.java @@ -1,4 +1,4 @@ -package com.baeldung.jpadefaultvalues.application; +package com.baeldung.jpa.defaultvalues; import javax.persistence.Column; import javax.persistence.Entity; @@ -9,7 +9,6 @@ import javax.persistence.Id; public class User { @Id - @GeneratedValue private Long id; @Column(columnDefinition = "varchar(255) default 'John Snow'") diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/defaultvalues/UserRepository.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/defaultvalues/UserRepository.java new file mode 100644 index 0000000000..52f9807cfb --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/defaultvalues/UserRepository.java @@ -0,0 +1,36 @@ +package com.baeldung.jpa.defaultvalues; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +public class UserRepository { + + private EntityManagerFactory emf = null; + + public UserRepository() { + emf = Persistence.createEntityManagerFactory("entity-default-values"); + } + + public User find(Long id) { + EntityManager entityManager = emf.createEntityManager(); + User user = entityManager.find(User.class, id); + entityManager.close(); + return user; + } + + public void save(User user, Long id) { + user.setId(id); + + EntityManager entityManager = emf.createEntityManager(); + entityManager.getTransaction().begin(); + entityManager.persist(user); + entityManager.getTransaction().commit(); + entityManager.close(); + } + + public void clean() { + emf.close(); + } + +} diff --git a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml index 5422afa4a3..21a757f490 100644 --- a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml +++ b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml @@ -1,133 +1,149 @@ - - - - - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.sqlresultsetmapping.ScheduledDay - com.baeldung.sqlresultsetmapping.Employee - true - - - - - - - - - - - - - - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.jpa.stringcast.Message - true - - - - - - - - - - - - - - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.jpa.model.Car - true - - - - - - - - - - - - com.baeldung.jpa.entitygraph.model.Post - com.baeldung.jpa.entitygraph.model.User - com.baeldung.jpa.entitygraph.model.Comment - true - - - - - - - - - - - - - org.eclipse.persistence.jpa.PersistenceProvider - com.baeldung.jpa.datetime.JPA22DateTimeEntity - true - - - - - - - - - - - - - - - - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.jpa.criteria.entity.Item - true - - - - - - - - - - - - - - - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.jpa.querytypes.UserEntity - true - - - - - - - - - - - - - - \ No newline at end of file + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.sqlresultsetmapping.ScheduledDay + com.baeldung.sqlresultsetmapping.Employee + true + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.stringcast.Message + true + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.model.Car + true + + + + + + + + + + + + com.baeldung.jpa.entitygraph.model.Post + com.baeldung.jpa.entitygraph.model.User + com.baeldung.jpa.entitygraph.model.Comment + true + + + + + + + + + + + + + org.eclipse.persistence.jpa.PersistenceProvider + com.baeldung.jpa.datetime.JPA22DateTimeEntity + true + + + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.criteria.entity.Item + true + + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.querytypes.UserEntity + true + + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.defaultvalues.User + true + + + + + + + + + + + + + diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/basicannotation/BasicAnnotationIntegrationTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/basicannotation/BasicAnnotationIntegrationTest.java new file mode 100644 index 0000000000..8580aa6602 --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/basicannotation/BasicAnnotationIntegrationTest.java @@ -0,0 +1,56 @@ +package com.baeldung.jpa.basicannotation; + +import org.hibernate.PropertyValueException; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.Test; + +import java.io.IOException; + +public class BasicAnnotationIntegrationTest { + + private static EntityManager entityManager; + private static EntityManagerFactory entityManagerFactory; + + @BeforeClass + public void setup() { + entityManagerFactory = Persistence.createEntityManagerFactory("java-jpa-scheduled-day"); + entityManager = entityManagerFactory.createEntityManager(); + } + + @Test + public void givenACourse_whenCourseNamePresent_shouldPersist() { + Course course = new Course(); + course.setName("Computers"); + + entityManager.persist(course); + entityManager.flush(); + entityManager.clear(); + + } + + @Test(expected = PropertyValueException.class) + public void givenACourse_whenCourseNameAbsent_shouldFail() { + Course course = new Course(); + + entityManager.persist(course); + entityManager.flush(); + entityManager.clear(); + } + + @AfterClass + public void destroy() { + + if (entityManager != null) { + entityManager.close(); + } + if (entityManagerFactory != null) { + entityManagerFactory.close(); + } + } +} diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/jpadefaultvalues/application/UserDefaultValuesUnitTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/defautlvalues/UserDefaultValuesUnitTest.java similarity index 59% rename from persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/jpadefaultvalues/application/UserDefaultValuesUnitTest.java rename to persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/defautlvalues/UserDefaultValuesUnitTest.java index 52a5c4dcd6..dc41ff51f2 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/jpadefaultvalues/application/UserDefaultValuesUnitTest.java +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/defautlvalues/UserDefaultValuesUnitTest.java @@ -1,31 +1,31 @@ -package com.baeldung.jpadefaultvalues.application; +package com.baeldung.jpa.defaultvalues; -import com.baeldung.jpadefaultvalues.application.User; -import com.baeldung.jpadefaultvalues.application.UserRepository; +import com.baeldung.jpa.defaultvalues.User; +import com.baeldung.jpa.defaultvalues.UserRepository; import org.junit.Test; import org.junit.Ignore; -import org.junit.runner.RunWith; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.AfterClass; +import org.junit.BeforeClass; import static org.junit.Assert.*; -@RunWith(SpringRunner.class) -@SpringBootTest public class UserDefaultValuesUnitTest { - @Autowired - private UserRepository userRepository; + private static UserRepository userRepository = null; + + @BeforeClass + public static void once() { + userRepository = new UserRepository(); + } @Test @Ignore // SQL default values are also defined public void saveUser_shouldSaveWithDefaultFieldValues() { User user = new User(); - user = userRepository.save(user); + userRepository.save(user, 1L); + user = userRepository.find(1L); assertEquals(user.getName(), "John Snow"); assertEquals(25, (int) user.getAge()); assertFalse(user.getLocked()); @@ -36,8 +36,9 @@ public class UserDefaultValuesUnitTest { public void saveUser_shouldSaveWithNullName() { User user = new User(); user.setName(null); - user = userRepository.save(user); + userRepository.save(user, 2L); + user = userRepository.find(2L); assertNull(user.getName()); assertEquals(25, (int) user.getAge()); assertFalse(user.getLocked()); @@ -46,11 +47,17 @@ public class UserDefaultValuesUnitTest { @Test public void saveUser_shouldSaveWithDefaultSqlValues() { User user = new User(); - user = userRepository.save(user); + userRepository.save(user, 3L); + user = userRepository.find(3L); assertEquals(user.getName(), "John Snow"); assertEquals(25, (int) user.getAge()); assertFalse(user.getLocked()); } + @AfterClass + public static void destroy() { + userRepository.clean(); + } + } diff --git a/persistence-modules/java-mongodb/README.md b/persistence-modules/java-mongodb/README.md index ded2b220f1..6d31467db3 100644 --- a/persistence-modules/java-mongodb/README.md +++ b/persistence-modules/java-mongodb/README.md @@ -2,3 +2,4 @@ - [A Guide to MongoDB with Java](http://www.baeldung.com/java-mongodb) - [A Simple Tagging Implementation with MongoDB](http://www.baeldung.com/mongodb-tagging) +- [MongoDB BSON Guide](https://www.baeldung.com/mongodb-bson) diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml index 67a5c36fed..ba3baf6636 100644 --- a/persistence-modules/pom.xml +++ b/persistence-modules/pom.xml @@ -55,5 +55,6 @@ spring-hibernate-5 spring-hibernate4 spring-jpa + spring-persistence-simple diff --git a/persistence-modules/spring-boot-persistence/pom.xml b/persistence-modules/spring-boot-persistence/pom.xml index ca7c7306e7..e283759c75 100644 --- a/persistence-modules/spring-boot-persistence/pom.xml +++ b/persistence-modules/spring-boot-persistence/pom.xml @@ -79,10 +79,8 @@ UTF-8 - 1.8 8.0.12 9.0.10 - 1.4.197 2.23.0 2.0.1.Final diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/jpadefaultvalues/application/Application.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/jpadefaultvalues/application/Application.java deleted file mode 100644 index 3b96f68583..0000000000 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/jpadefaultvalues/application/Application.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.jpadefaultvalues.application; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ApplicationContext; - -@SpringBootApplication -public class Application { - private static ApplicationContext applicationContext; - - public static void main(String[] args) { - applicationContext = SpringApplication.run(Application.class, args); - } -} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/jpadefaultvalues/application/UserRepository.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/jpadefaultvalues/application/UserRepository.java deleted file mode 100644 index ca0e4c4d71..0000000000 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/jpadefaultvalues/application/UserRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.jpadefaultvalues.application; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface UserRepository extends JpaRepository { -} diff --git a/persistence-modules/spring-data-cassandra-reactive/pom.xml b/persistence-modules/spring-data-cassandra-reactive/pom.xml index bc8f49862d..5a34d90c9f 100644 --- a/persistence-modules/spring-data-cassandra-reactive/pom.xml +++ b/persistence-modules/spring-data-cassandra-reactive/pom.xml @@ -52,7 +52,6 @@ UTF-8 UTF-8 - 1.8 2.1.2.RELEASE diff --git a/persistence-modules/spring-data-eclipselink/pom.xml b/persistence-modules/spring-data-eclipselink/pom.xml index 618fa83ee5..61c28dc26f 100644 --- a/persistence-modules/spring-data-eclipselink/pom.xml +++ b/persistence-modules/spring-data-eclipselink/pom.xml @@ -67,7 +67,6 @@ 1.5.9.RELEASE 2.7.0 - 1.4.196 diff --git a/persistence-modules/spring-data-jpa-2/README.md b/persistence-modules/spring-data-jpa-2/README.md index 41381ab82a..393d15d6f1 100644 --- a/persistence-modules/spring-data-jpa-2/README.md +++ b/persistence-modules/spring-data-jpa-2/README.md @@ -1,6 +1,14 @@ -========= - -## Spring Data JPA Example Project - -### Relevant Articles: -- [Spring Data JPA – Derived Delete Methods](https://www.baeldung.com/spring-data-jpa-deleteby) +========= + +## Spring Data JPA Example Project + +### Relevant Articles: +- [Spring Data JPA – Derived Delete Methods](https://www.baeldung.com/spring-data-jpa-deleteby) +- [JPA Join Types](https://www.baeldung.com/jpa-join-types) +- [Case Insensitive Queries with Spring Data Repository](https://www.baeldung.com/spring-data-case-insensitive-queries) +- [The Exists Query in Spring Data](https://www.baeldung.com/spring-data-exists-query) +- [Spring Data JPA Repository Populators](https://www.baeldung.com/spring-data-jpa-repository-populators) +- [Spring Data JPA and Null Parameters](https://www.baeldung.com/spring-data-jpa-null-parameters) +- [Spring Data JPA Projections](https://www.baeldung.com/spring-data-jpa-projections) +- [JPA @Embedded And @Embeddable](https://www.baeldung.com/jpa-embedded-embeddable) +- [Spring Data JPA Delete and Relationships](https://www.baeldung.com/spring-data-jpa-delete) diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/entity/User.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/entity/User.java new file mode 100644 index 0000000000..e6d38f775b --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/entity/User.java @@ -0,0 +1,70 @@ +package com.baeldung.derivedquery.entity; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.ZonedDateTime; + +@Table(name = "users") +@Entity +public class User { + + @Id + @GeneratedValue + private Integer id; + private String name; + private Integer age; + private ZonedDateTime birthDate; + private Boolean active; + + public User() { + } + + public User(String name, Integer age, ZonedDateTime birthDate, Boolean active) { + this.name = name; + this.age = age; + this.birthDate = birthDate; + this.active = active; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public ZonedDateTime getBirthDate() { + return birthDate; + } + + public void setBirthDate(ZonedDateTime birthDate) { + this.birthDate = birthDate; + } + + public Boolean getActive() { + return active; + } + + public void setActive(Boolean active) { + this.active = active; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java new file mode 100644 index 0000000000..a23855d96d --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java @@ -0,0 +1,60 @@ +package com.baeldung.derivedquery.repository; + +import com.baeldung.derivedquery.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.time.ZonedDateTime; +import java.util.Collection; +import java.util.List; + +public interface UserRepository extends JpaRepository { + + List findByName(String name); + + List findByNameIs(String name); + + List findByNameEquals(String name); + + List findByNameIsNull(); + + List findByNameNot(String name); + + List findByNameIsNot(String name); + + List findByNameStartingWith(String name); + + List findByNameEndingWith(String name); + + List findByNameContaining(String name); + + List findByNameLike(String name); + + List findByAgeLessThan(Integer age); + + List findByAgeLessThanEqual(Integer age); + + List findByAgeGreaterThan(Integer age); + + List findByAgeGreaterThanEqual(Integer age); + + List findByAgeBetween(Integer startAge, Integer endAge); + + List findByBirthDateAfter(ZonedDateTime birthDate); + + List findByBirthDateBefore(ZonedDateTime birthDate); + + List findByActiveTrue(); + + List findByActiveFalse(); + + List findByAgeIn(Collection ages); + + List findByNameOrBirthDate(String name, ZonedDateTime birthDate); + + List findByNameOrBirthDateAndActive(String name, ZonedDateTime birthDate, Boolean active); + + List findByNameOrderByName(String name); + + List findByNameOrderByNameDesc(String name); + +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryTest.java new file mode 100644 index 0000000000..188ed5d4d0 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryTest.java @@ -0,0 +1,172 @@ +package com.baeldung.derivedquery.repository; + +import com.baeldung.Application; +import com.baeldung.derivedquery.entity.User; +import com.baeldung.derivedquery.repository.UserRepository; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.List; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class UserRepositoryTest { + + private static final String USER_NAME_ADAM = "Adam"; + private static final String USER_NAME_EVE = "Eve"; + private static final ZonedDateTime BIRTHDATE = ZonedDateTime.now(); + + @Autowired + private UserRepository userRepository; + + @Before + public void setUp() { + + User user1 = new User(USER_NAME_ADAM, 25, BIRTHDATE, true); + User user2 = new User(USER_NAME_ADAM, 20, BIRTHDATE, false); + User user3 = new User(USER_NAME_EVE, 20, BIRTHDATE, true); + User user4 = new User(null, 30, BIRTHDATE, false); + + userRepository.saveAll(Arrays.asList(user1, user2, user3, user4)); + } + + @After + public void tearDown() { + + userRepository.deleteAll(); + } + + @Test + public void whenFindByName_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByName(USER_NAME_ADAM).size()); + } + + @Test + public void whenFindByNameIsNull_thenReturnsCorrectResult() { + + assertEquals(1, userRepository.findByNameIsNull().size()); + } + + @Test + public void whenFindByNameNot_thenReturnsCorrectResult() { + + assertEquals(USER_NAME_EVE, userRepository.findByNameNot(USER_NAME_ADAM).get(0).getName()); + } + + @Test + public void whenFindByNameStartingWith_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByNameStartingWith("A").size()); + } + + @Test + public void whenFindByNameEndingWith_thenReturnsCorrectResult() { + + assertEquals(1, userRepository.findByNameEndingWith("e").size()); + } + + @Test + public void whenByNameContaining_thenReturnsCorrectResult() { + + assertEquals(1, userRepository.findByNameContaining("v").size()); + } + + + @Test + public void whenByNameLike_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByNameEndingWith("%d%m").size()); + } + + @Test + public void whenByAgeLessThan_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByAgeLessThan(25).size()); + } + + + @Test + public void whenByAgeLessThanEqual_thenReturnsCorrectResult() { + + assertEquals(3, userRepository.findByAgeLessThanEqual(25).size()); + } + + @Test + public void whenByAgeGreaterThan_thenReturnsCorrectResult() { + + assertEquals(1, userRepository.findByAgeGreaterThan(25).size()); + } + + @Test + public void whenByAgeGreaterThanEqual_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByAgeGreaterThanEqual(25).size()); + } + + @Test + public void whenByAgeBetween_thenReturnsCorrectResult() { + + assertEquals(4, userRepository.findByAgeBetween(20, 30).size()); + } + + @Test + public void whenByBirthDateAfter_thenReturnsCorrectResult() { + + final ZonedDateTime yesterday = BIRTHDATE.minusDays(1); + assertEquals(4, userRepository.findByBirthDateAfter(yesterday).size()); + } + + @Test + public void whenByBirthDateBefore_thenReturnsCorrectResult() { + + final ZonedDateTime yesterday = BIRTHDATE.minusDays(1); + assertEquals(0, userRepository.findByBirthDateBefore(yesterday).size()); + } + + @Test + public void whenByActiveTrue_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByActiveTrue().size()); + } + + @Test + public void whenByActiveFalse_thenReturnsCorrectResult() { + + assertEquals(2, userRepository.findByActiveFalse().size()); + } + + + @Test + public void whenByAgeIn_thenReturnsCorrectResult() { + + final List ages = Arrays.asList(20, 25); + assertEquals(3, userRepository.findByAgeIn(ages).size()); + } + + @Test + public void whenByNameOrBirthDate() { + + assertEquals(4, userRepository.findByNameOrBirthDate(USER_NAME_ADAM, BIRTHDATE).size()); + } + + @Test + public void whenByNameOrBirthDateAndActive() { + + assertEquals(3, userRepository.findByNameOrBirthDateAndActive(USER_NAME_ADAM, BIRTHDATE, false).size()); + } + + @Test + public void whenByNameOrderByName() { + + assertEquals(2, userRepository.findByNameOrderByName(USER_NAME_ADAM).size()); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa/README.md b/persistence-modules/spring-data-jpa/README.md index 4e390c2faf..e85d8a8487 100644 --- a/persistence-modules/spring-data-jpa/README.md +++ b/persistence-modules/spring-data-jpa/README.md @@ -6,7 +6,6 @@ - [Spring JPA – Multiple Databases](http://www.baeldung.com/spring-data-jpa-multiple-databases) - [Spring Data JPA – Adding a Method in All Repositories](http://www.baeldung.com/spring-data-jpa-method-in-all-repositories) - [An Advanced Tagging Implementation with JPA](http://www.baeldung.com/jpa-tagging-advanced) -- [Spring Data JPA @Query](http://www.baeldung.com/spring-data-jpa-query) - [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations) - [Spring Data Java 8 Support](http://www.baeldung.com/spring-data-java-8) - [A Simple Tagging Implementation with JPA](http://www.baeldung.com/jpa-tagging) diff --git a/persistence-modules/spring-hibernate-3/pom.xml b/persistence-modules/spring-hibernate-3/pom.xml index 6c1bdace30..ec35f35bb3 100644 --- a/persistence-modules/spring-hibernate-3/pom.xml +++ b/persistence-modules/spring-hibernate-3/pom.xml @@ -91,7 +91,6 @@ 3.6.10.Final 5.1.40 8.5.8 - 1.4.193 19.0 3.5 diff --git a/persistence-modules/spring-hibernate-5/pom.xml b/persistence-modules/spring-hibernate-5/pom.xml index 832cf8dca7..16e55cb0c0 100644 --- a/persistence-modules/spring-hibernate-5/pom.xml +++ b/persistence-modules/spring-hibernate-5/pom.xml @@ -143,7 +143,6 @@ 9.0.0.M26 1.1 2.3.4 - 1.4.195 21.0 diff --git a/persistence-modules/spring-hibernate4/README.md b/persistence-modules/spring-hibernate4/README.md index f2553ad229..6f8d83aa9d 100644 --- a/persistence-modules/spring-hibernate4/README.md +++ b/persistence-modules/spring-hibernate4/README.md @@ -4,7 +4,6 @@ ### Relevant Articles: - [Guide to Hibernate 4 with Spring](http://www.baeldung.com/hibernate-4-spring) -- [The DAO with Spring and Hibernate](http://www.baeldung.com/persistence-layer-with-spring-and-hibernate) - [Hibernate Pagination](http://www.baeldung.com/hibernate-pagination) - [Sorting with Hibernate](http://www.baeldung.com/hibernate-sort) - [Stored Procedures with Hibernate](http://www.baeldung.com/stored-procedures-with-hibernate-tutorial) diff --git a/persistence-modules/spring-hibernate4/pom.xml b/persistence-modules/spring-hibernate4/pom.xml index fad84870df..4289c9c3d5 100644 --- a/persistence-modules/spring-hibernate4/pom.xml +++ b/persistence-modules/spring-hibernate4/pom.xml @@ -160,7 +160,6 @@ 8.5.8 1.1 2.3.4 - 1.4.193 5.3.3.Final diff --git a/persistence-modules/spring-jpa/README.md b/persistence-modules/spring-jpa/README.md index 2f2a27e4ac..e856e4808e 100644 --- a/persistence-modules/spring-jpa/README.md +++ b/persistence-modules/spring-jpa/README.md @@ -4,8 +4,6 @@ ### Relevant Articles: -- [A Guide to JPA with Spring](https://www.baeldung.com/the-persistence-layer-with-spring-and-jpa) -- [Transactions with Spring and JPA](https://www.baeldung.com/transaction-configuration-with-jpa-and-spring) - [The DAO with JPA and Spring](http://www.baeldung.com/spring-dao-jpa) - [JPA Pagination](http://www.baeldung.com/jpa-pagination) - [Sorting with JPA](http://www.baeldung.com/jpa-sort) diff --git a/persistence-modules/spring-jpa/pom.xml b/persistence-modules/spring-jpa/pom.xml index 3daba6cd55..0fdffad8db 100644 --- a/persistence-modules/spring-jpa/pom.xml +++ b/persistence-modules/spring-jpa/pom.xml @@ -93,7 +93,7 @@ javax.servlet jstl - ${javax.servlet.jstl.version} + ${jstl.version} javax.servlet @@ -163,10 +163,8 @@ 5.2.17.Final 6.0.6 2.1.5.RELEASE - 1.4.195 - 1.2 2.5 diff --git a/persistence-modules/spring-persistence-simple/.gitignore b/persistence-modules/spring-persistence-simple/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/README.md b/persistence-modules/spring-persistence-simple/README.md new file mode 100644 index 0000000000..c656efaa3b --- /dev/null +++ b/persistence-modules/spring-persistence-simple/README.md @@ -0,0 +1,24 @@ +========= + +## Spring Persistence Example Project + + +### Relevant Articles: +- [A Guide to JPA with Spring](https://www.baeldung.com/the-persistence-layer-with-spring-and-jpa) +- [Bootstrapping Hibernate 5 with Spring](http://www.baeldung.com/hibernate-5-spring) +- [The DAO with Spring and Hibernate](http://www.baeldung.com/persistence-layer-with-spring-and-hibernate) +- [DAO with Spring and Generics](https://www.baeldung.com/simplifying-the-data-access-layer-with-spring-and-java-generics) +- [Transactions with Spring and JPA](https://www.baeldung.com/transaction-configuration-with-jpa-and-spring) +- [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) +- [Spring Data JPA @Query](http://www.baeldung.com/spring-data-jpa-query) + + +### Eclipse Config +After importing the project into Eclipse, you may see the following error: +"No persistence xml file found in project" + +This can be ignored: +- Project -> Properties -> Java Persistance -> JPA -> Error/Warnings -> Select Ignore on "No persistence xml file found in project" +Or: +- Eclipse -> Preferences - Validation - disable the "Build" execution of the JPA Validator + diff --git a/persistence-modules/spring-persistence-simple/pom.xml b/persistence-modules/spring-persistence-simple/pom.xml new file mode 100644 index 0000000000..5f48b267b5 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/pom.xml @@ -0,0 +1,160 @@ + + 4.0.0 + spring-persistence-simple + 0.1-SNAPSHOT + spring-persistence-simple + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../../ + + + + + + org.springframework + spring-orm + ${org.springframework.version} + + + commons-logging + commons-logging + + + + + org.springframework + spring-context + ${org.springframework.version} + + + + + org.hibernate + hibernate-core + ${hibernate.version} + + + javax.transaction + jta + ${jta.version} + + + org.hibernate + hibernate-entitymanager + ${hibernate.version} + + + mysql + mysql-connector-java + ${mysql-connector-java.version} + runtime + + + org.springframework.data + spring-data-jpa + ${spring-data-jpa.version} + + + com.h2database + h2 + ${h2.version} + + + + org.apache.tomcat + tomcat-dbcp + ${tomcat-dbcp.version} + + + + + + com.google.guava + guava + ${guava.version} + + + org.assertj + assertj-core + ${assertj.version} + + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + test + + + + org.springframework + spring-test + ${org.springframework.version} + test + + + com.querydsl + querydsl-jpa + ${querydsl.version} + + + com.querydsl + querydsl-apt + ${querydsl.version} + + + + + spring-persistence-simple + + + src/main/resources + true + + + + + com.mysema.maven + apt-maven-plugin + 1.1.3 + + + generate-sources + + process + + + target/generated-sources + com.querydsl.apt.jpa.JPAAnnotationProcessor + + + + + + + + + + 5.1.6.RELEASE + + + 5.4.2.Final + 6.0.6 + 2.1.6.RELEASE + 9.0.0.M26 + 1.1 + 4.2.1 + + + 21.0 + 3.5 + 3.8.0 + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/BarHibernateDAO.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/BarHibernateDAO.java new file mode 100644 index 0000000000..5fc932b256 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/BarHibernateDAO.java @@ -0,0 +1,39 @@ +package com.baeldung.hibernate.bootstrap; + +import com.baeldung.hibernate.bootstrap.model.TestEntity; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.springframework.beans.factory.annotation.Autowired; + +public abstract class BarHibernateDAO { + + @Autowired + private SessionFactory sessionFactory; + + public TestEntity findEntity(int id) { + + return getCurrentSession().find(TestEntity.class, 1); + } + + public void createEntity(TestEntity entity) { + + getCurrentSession().save(entity); + } + + public void createEntity(int id, String newDescription) { + + TestEntity entity = findEntity(id); + entity.setDescription(newDescription); + getCurrentSession().save(entity); + } + + public void deleteEntity(int id) { + + TestEntity entity = findEntity(id); + getCurrentSession().delete(entity); + } + + protected Session getCurrentSession() { + return sessionFactory.getCurrentSession(); + } +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateConf.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateConf.java new file mode 100644 index 0000000000..150e3778af --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateConf.java @@ -0,0 +1,61 @@ +package com.baeldung.hibernate.bootstrap; + +import com.google.common.base.Preconditions; +import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.orm.hibernate5.HibernateTransactionManager; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-h2.properties" }) +public class HibernateConf { + + @Autowired + private Environment env; + + @Bean + public LocalSessionFactoryBean sessionFactory() { + final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + sessionFactory.setDataSource(dataSource()); + sessionFactory.setPackagesToScan(new String[] { "com.baeldung.hibernate.bootstrap.model" }); + sessionFactory.setHibernateProperties(hibernateProperties()); + + return sessionFactory; + } + + @Bean + public DataSource dataSource() { + final BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager hibernateTransactionManager() { + final HibernateTransactionManager transactionManager = new HibernateTransactionManager(); + transactionManager.setSessionFactory(sessionFactory().getObject()); + return transactionManager; + } + + private final Properties hibernateProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + + return hibernateProperties; + } +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateXMLConf.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateXMLConf.java new file mode 100644 index 0000000000..b3e979478f --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateXMLConf.java @@ -0,0 +1,24 @@ +package com.baeldung.hibernate.bootstrap; + +import com.google.common.base.Preconditions; +import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.orm.hibernate5.HibernateTransactionManager; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@EnableTransactionManagement +@ImportResource({ "classpath:hibernate5Configuration.xml" }) +public class HibernateXMLConf { + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/model/TestEntity.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/model/TestEntity.java new file mode 100644 index 0000000000..cae41db831 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/model/TestEntity.java @@ -0,0 +1,29 @@ +package com.baeldung.hibernate.bootstrap.model; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class TestEntity { + + private int id; + + private String description; + + @Id + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java new file mode 100644 index 0000000000..5a6c76a93a --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java @@ -0,0 +1,14 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; + +import com.google.common.base.Preconditions; + +public abstract class AbstractDao implements IOperations { + + protected Class clazz; + + protected final void setClazz(final Class clazzToSet) { + clazz = Preconditions.checkNotNull(clazzToSet); + } +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java new file mode 100644 index 0000000000..e406f896dc --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java @@ -0,0 +1,60 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import com.google.common.base.Preconditions; + +@SuppressWarnings("unchecked") +public abstract class AbstractHibernateDao extends AbstractDao implements IOperations { + + @Autowired + protected SessionFactory sessionFactory; + + // API + + @Override + public T findOne(final long id) { + return (T) getCurrentSession().get(clazz, id); + } + + @Override + public List findAll() { + return getCurrentSession().createQuery("from " + clazz.getName()).list(); + } + + @Override + public T create(final T entity) { + Preconditions.checkNotNull(entity); + getCurrentSession().saveOrUpdate(entity); + return entity; + } + + @Override + public T update(final T entity) { + Preconditions.checkNotNull(entity); + return (T) getCurrentSession().merge(entity); + } + + @Override + public void delete(final T entity) { + Preconditions.checkNotNull(entity); + getCurrentSession().delete(entity); + } + + @Override + public void deleteById(final long entityId) { + final T entity = findOne(entityId); + Preconditions.checkState(entity != null); + delete(entity); + } + + protected Session getCurrentSession() { + return sessionFactory.getCurrentSession(); + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java new file mode 100644 index 0000000000..18b16fa033 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java @@ -0,0 +1,13 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Repository; + +@Repository +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +public class GenericHibernateDao extends AbstractHibernateDao implements IGenericDao { + // +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java new file mode 100644 index 0000000000..5bcebed761 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java @@ -0,0 +1,14 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; + +import org.baeldung.persistence.dao.AbstractJpaDAO; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Repository; + +@Repository +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +public class GenericJpaDao extends AbstractJpaDAO implements IGenericDao { + // +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java new file mode 100644 index 0000000000..8d8af18394 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java @@ -0,0 +1,7 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; + +public interface IGenericDao extends IOperations { + // +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IOperations.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IOperations.java new file mode 100644 index 0000000000..34c5e0f616 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IOperations.java @@ -0,0 +1,20 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; +import java.util.List; + +public interface IOperations { + + T findOne(final long id); + + List findAll(); + + T create(final T entity); + + T update(final T entity); + + void delete(final T entity); + + void deleteById(final long entityId); + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java new file mode 100644 index 0000000000..2d940527e1 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java @@ -0,0 +1,20 @@ +package com.baeldung.persistence.dao.impl; + +import org.baeldung.persistence.dao.IFooDao; +import org.baeldung.persistence.model.Foo; +import org.springframework.stereotype.Repository; + +import com.baeldung.persistence.dao.common.AbstractHibernateDao; + +@Repository +public class FooDao extends AbstractHibernateDao implements IFooDao { + + public FooDao() { + super(); + + setClazz(Foo.class); + } + + // API + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceConfig.java new file mode 100644 index 0000000000..c454ab3b54 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceConfig.java @@ -0,0 +1,118 @@ +package org.baeldung.config; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; +import org.baeldung.persistence.dao.IFooDao; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.hibernate5.HibernateTransactionManager; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.JpaVendorAdapter; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.baeldung.persistence.dao.impl.FooDao; +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories(basePackages = { "com.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager") +@EnableJpaAuditing +@PropertySource({ "classpath:persistence-mysql.properties" }) +@ComponentScan({ "com.baeldung.persistence" }) +public class PersistenceConfig { + + @Autowired + private Environment env; + + public PersistenceConfig() { + super(); + } + + @Bean + public LocalSessionFactoryBean sessionFactory() { + final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + sessionFactory.setDataSource(restDataSource()); + sessionFactory.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + sessionFactory.setHibernateProperties(hibernateProperties()); + + return sessionFactory; + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); + emf.setDataSource(restDataSource()); + emf.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + + final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + emf.setJpaVendorAdapter(vendorAdapter); + emf.setJpaProperties(hibernateProperties()); + + return emf; + } + + @Bean + public DataSource restDataSource() { + final BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager hibernateTransactionManager() { + final HibernateTransactionManager transactionManager = new HibernateTransactionManager(); + transactionManager.setSessionFactory(sessionFactory().getObject()); + return transactionManager; + } + + @Bean + public PlatformTransactionManager jpaTransactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + @Bean + public IFooDao fooHibernateDao() { + return new FooDao(); + } + + private final Properties hibernateProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + + hibernateProperties.setProperty("hibernate.show_sql", "true"); + // hibernateProperties.setProperty("hibernate.format_sql", "true"); + // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); + + // Envers properties + hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix")); + + return hibernateProperties; + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceJPAConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceJPAConfig.java new file mode 100644 index 0000000000..ec0d4bca3c --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceJPAConfig.java @@ -0,0 +1,87 @@ +package org.baeldung.config; + +import java.util.Properties; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-h2.properties" }) +@ComponentScan({ "org.baeldung.persistence" }) +@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao") +public class PersistenceJPAConfig { + + @Autowired + private Environment env; + + public PersistenceJPAConfig() { + super(); + } + + // beans + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" }); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(additionalProperties()); + + return em; + } + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(emf); + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "false"); + + + return hibernateProperties; + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/AbstractJpaDAO.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/AbstractJpaDAO.java new file mode 100644 index 0000000000..decca35c08 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/AbstractJpaDAO.java @@ -0,0 +1,47 @@ +package org.baeldung.persistence.dao; + +import java.io.Serializable; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +public abstract class AbstractJpaDAO { + + private Class clazz; + + @PersistenceContext + private EntityManager entityManager; + + public final void setClazz(final Class clazzToSet) { + this.clazz = clazzToSet; + } + + public T findOne(final long id) { + return entityManager.find(clazz, id); + } + + @SuppressWarnings("unchecked") + public List findAll() { + return entityManager.createQuery("from " + clazz.getName()).getResultList(); + } + + public T create(final T entity) { + entityManager.persist(entity); + return entity; + } + + public T update(final T entity) { + return entityManager.merge(entity); + } + + public void delete(final T entity) { + entityManager.remove(entity); + } + + public void deleteById(final long entityId) { + final T entity = findOne(entityId); + delete(entity); + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/FooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/FooDao.java new file mode 100644 index 0000000000..77978c5cf2 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/FooDao.java @@ -0,0 +1,17 @@ +package org.baeldung.persistence.dao; + +import org.baeldung.persistence.model.Foo; +import org.springframework.stereotype.Repository; + +@Repository +public class FooDao extends AbstractJpaDAO implements IFooDao { + + public FooDao() { + super(); + + setClazz(Foo.class); + } + + // API + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/IFooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/IFooDao.java new file mode 100644 index 0000000000..ba188b9b3a --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/IFooDao.java @@ -0,0 +1,21 @@ +package org.baeldung.persistence.dao; + +import java.util.List; + +import org.baeldung.persistence.model.Foo; + +public interface IFooDao { + + Foo findOne(long id); + + List findAll(); + + Foo create(Foo entity); + + Foo update(Foo entity); + + void delete(Foo entity); + + void deleteById(long entityId); + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Bar.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Bar.java new file mode 100644 index 0000000000..b602e57562 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Bar.java @@ -0,0 +1,102 @@ +package org.baeldung.persistence.model; + +import java.io.Serializable; +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OrderBy; + +@Entity +public class Bar implements Serializable { + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + @Column(nullable = false) + private String name; + + @OneToMany(mappedBy = "bar", fetch = FetchType.EAGER, cascade = CascadeType.ALL) + @OrderBy("name ASC") + List fooList; + + public Bar() { + super(); + } + + public Bar(final String name) { + super(); + + this.name = name; + } + + // API + + public long getId() { + return id; + } + + public void setId(final long id) { + + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public List getFooList() { + return fooList; + } + + public void setFooList(final List fooList) { + this.fooList = fooList; + } + + // + + @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(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Bar other = (Bar) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Bar [name=").append(name).append("]"); + return builder.toString(); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Foo.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Foo.java new file mode 100644 index 0000000000..30635e9ef2 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Foo.java @@ -0,0 +1,104 @@ +package org.baeldung.persistence.model; + +import java.io.Serializable; + +import javax.persistence.Cacheable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.NamedNativeQueries; +import javax.persistence.NamedNativeQuery; + +import org.hibernate.annotations.CacheConcurrencyStrategy; + +@Entity +@Cacheable +@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) +@NamedNativeQueries({ @NamedNativeQuery(name = "callGetAllFoos", query = "CALL GetAllFoos()", resultClass = Foo.class), @NamedNativeQuery(name = "callGetFoosByName", query = "CALL GetFoosByName(:fooName)", resultClass = Foo.class) }) +public class Foo implements Serializable { + + private static final long serialVersionUID = 1L; + + public Foo() { + super(); + } + + public Foo(final String name) { + super(); + + this.name = name; + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "ID") + private Long id; + @Column(name = "NAME") + private String name; + + @ManyToOne(targetEntity = Bar.class, fetch = FetchType.EAGER) + @JoinColumn(name = "BAR_ID") + private Bar bar; + + public Bar getBar() { + return bar; + } + + public void setBar(final Bar bar) { + this.bar = bar; + } + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.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(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Foo other = (Foo) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Foo [name=").append(name).append("]"); + return builder.toString(); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/service/FooService.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/service/FooService.java new file mode 100644 index 0000000000..6d1bb0adbe --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/service/FooService.java @@ -0,0 +1,36 @@ +package org.baeldung.persistence.service; + +import java.util.List; + +import org.baeldung.persistence.dao.IFooDao; +import org.baeldung.persistence.model.Foo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class FooService { + + @Autowired + private IFooDao dao; + + public FooService() { + super(); + } + + // API + + public void create(final Foo entity) { + dao.create(entity); + } + + public Foo findOne(final long id) { + return dao.findOne(id); + } + + public List findAll() { + return dao.findAll(); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/config/PersistenceConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/config/PersistenceConfig.java new file mode 100644 index 0000000000..067bac2018 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/config/PersistenceConfig.java @@ -0,0 +1,85 @@ +package org.baeldung.spring.data.persistence.config; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-${envTarget:h2}.properties" }) +@ComponentScan({ "org.baeldung.spring.data.persistence" }) +// @ImportResource("classpath*:springDataPersistenceConfig.xml") +@EnableJpaRepositories(basePackages = "org.baeldung.spring.data.persistence.dao") +public class PersistenceConfig { + + @Autowired + private Environment env; + + public PersistenceConfig() { + super(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "org.baeldung.spring.data.persistence.model" }); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + // vendorAdapter.set + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(additionalProperties()); + + return em; + } + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager transactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); + + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); + return hibernateProperties; + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/IFooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/IFooDao.java new file mode 100644 index 0000000000..2f74096e14 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/IFooDao.java @@ -0,0 +1,11 @@ +package org.baeldung.spring.data.persistence.dao; + +import org.baeldung.spring.data.persistence.model.Foo; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +public interface IFooDao extends JpaRepository { + + @Query("SELECT f FROM Foo f WHERE LOWER(f.name) = LOWER(:name)") + Foo retrieveByName(@Param("name") String name); +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepository.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepository.java new file mode 100644 index 0000000000..4d01376af7 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepository.java @@ -0,0 +1,98 @@ +package org.baeldung.spring.data.persistence.dao.user; + +import java.time.LocalDate; +import java.util.Collection; +import java.util.List; +import java.util.stream.Stream; + +import org.baeldung.spring.data.persistence.model.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface UserRepository extends JpaRepository, UserRepositoryCustom { + + Stream findAllByName(String name); + + @Query("SELECT u FROM User u WHERE u.status = 1") + Collection findAllActiveUsers(); + + @Query("select u from User u where u.email like '%@gmail.com'") + List findUsersWithGmailAddress(); + + @Query(value = "SELECT * FROM Users u WHERE u.status = 1", nativeQuery = true) + Collection findAllActiveUsersNative(); + + @Query("SELECT u FROM User u WHERE u.status = ?1") + User findUserByStatus(Integer status); + + @Query(value = "SELECT * FROM Users u WHERE u.status = ?1", nativeQuery = true) + User findUserByStatusNative(Integer status); + + @Query("SELECT u FROM User u WHERE u.status = ?1 and u.name = ?2") + User findUserByStatusAndName(Integer status, String name); + + @Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name") + User findUserByStatusAndNameNamedParams(@Param("status") Integer status, @Param("name") String name); + + @Query(value = "SELECT * FROM Users u WHERE u.status = :status AND u.name = :name", nativeQuery = true) + User findUserByStatusAndNameNamedParamsNative(@Param("status") Integer status, @Param("name") String name); + + @Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name") + User findUserByUserStatusAndUserName(@Param("status") Integer userStatus, @Param("name") String userName); + + @Query("SELECT u FROM User u WHERE u.name like ?1%") + User findUserByNameLike(String name); + + @Query("SELECT u FROM User u WHERE u.name like :name%") + User findUserByNameLikeNamedParam(@Param("name") String name); + + @Query(value = "SELECT * FROM users u WHERE u.name LIKE ?1%", nativeQuery = true) + User findUserByNameLikeNative(String name); + + @Query(value = "SELECT u FROM User u") + List findAllUsers(Sort sort); + + @Query(value = "SELECT u FROM User u ORDER BY id") + Page findAllUsersWithPagination(Pageable pageable); + + @Query(value = "SELECT * FROM Users ORDER BY id", countQuery = "SELECT count(*) FROM Users", nativeQuery = true) + Page findAllUsersWithPaginationNative(Pageable pageable); + + @Modifying + @Query("update User u set u.status = :status where u.name = :name") + int updateUserSetStatusForName(@Param("status") Integer status, @Param("name") String name); + + @Modifying + @Query(value = "UPDATE Users u SET u.status = ? WHERE u.name = ?", nativeQuery = true) + int updateUserSetStatusForNameNative(Integer status, String name); + + @Query(value = "INSERT INTO Users (name, age, email, status, active) VALUES (:name, :age, :email, :status, :active)", nativeQuery = true) + @Modifying + void insertUser(@Param("name") String name, @Param("age") Integer age, @Param("email") String email, @Param("status") Integer status, @Param("active") boolean active); + + @Modifying + @Query(value = "UPDATE Users u SET status = ? WHERE u.name = ?", nativeQuery = true) + int updateUserSetStatusForNameNativePostgres(Integer status, String name); + + @Query(value = "SELECT u FROM User u WHERE u.name IN :names") + List findUserByNameList(@Param("names") Collection names); + + void deleteAllByCreationDateAfter(LocalDate date); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query("update User u set u.active = false where u.lastLoginDate < :date") + void deactivateUsersNotLoggedInSince(@Param("date") LocalDate date); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query("delete User u where u.active = false") + int deleteDeactivatedUsers(); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query(value = "alter table USERS add column deleted int(1) not null default 0", nativeQuery = true) + void addDeletedColumn(); +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java new file mode 100644 index 0000000000..1a874fb5e5 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java @@ -0,0 +1,14 @@ +package org.baeldung.spring.data.persistence.dao.user; + +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; + +import org.baeldung.spring.data.persistence.model.User; + +public interface UserRepositoryCustom { + List findUserByEmails(Set emails); + + List findAllUsersByPredicates(Collection> predicates); +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java new file mode 100644 index 0000000000..c28050401c --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java @@ -0,0 +1,57 @@ +package org.baeldung.spring.data.persistence.dao.user; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.baeldung.spring.data.persistence.model.User; + +public class UserRepositoryCustomImpl implements UserRepositoryCustom { + + @PersistenceContext + private EntityManager entityManager; + + @Override + public List findUserByEmails(Set emails) { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + CriteriaQuery query = cb.createQuery(User.class); + Root user = query.from(User.class); + + Path emailPath = user.get("email"); + + List predicates = new ArrayList<>(); + for (String email : emails) { + + predicates.add(cb.like(emailPath, email)); + + } + query.select(user) + .where(cb.or(predicates.toArray(new Predicate[predicates.size()]))); + + return entityManager.createQuery(query) + .getResultList(); + } + + @Override + public List findAllUsersByPredicates(Collection> predicates) { + List allUsers = entityManager.createQuery("select u from User u", User.class).getResultList(); + Stream allUsersStream = allUsers.stream(); + for (java.util.function.Predicate predicate : predicates) { + allUsersStream = allUsersStream.filter(predicate); + } + + return allUsersStream.collect(Collectors.toList()); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Foo.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Foo.java new file mode 100644 index 0000000000..8f316ac55b --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Foo.java @@ -0,0 +1,83 @@ +package org.baeldung.spring.data.persistence.model; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Foo implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + @Column(nullable = false) + private String name; + + public Foo() { + super(); + } + + public Foo(final String name) { + super(); + + this.name = name; + } + + // API + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.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(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Foo other = (Foo) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Foo [name=").append(name).append("]"); + return builder.toString(); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Possession.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Possession.java new file mode 100644 index 0000000000..da64e78552 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Possession.java @@ -0,0 +1,86 @@ +package org.baeldung.spring.data.persistence.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table +public class Possession { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + private String name; + + public Possession() { + super(); + } + + public Possession(final String name) { + super(); + + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + (int) (id ^ (id >>> 32)); + 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; + } + final Possession other = (Possession) obj; + if (id != other.id) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Possesion [id=").append(id).append(", name=").append(name).append("]"); + return builder.toString(); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/User.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/User.java new file mode 100644 index 0000000000..486ed046e5 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/User.java @@ -0,0 +1,132 @@ +package org.baeldung.spring.data.persistence.model; + +import javax.persistence.*; + +import java.time.LocalDate; +import java.util.List; +import java.util.Objects; + +@Entity +@Table(name = "users") +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + private String name; + private LocalDate creationDate; + private LocalDate lastLoginDate; + private boolean active; + private int age; + @Column(unique = true, nullable = false) + private String email; + private Integer status; + @OneToMany + List possessionList; + + public User() { + super(); + } + + public User(String name, LocalDate creationDate,String email, Integer status) { + this.name = name; + this.creationDate = creationDate; + this.email = email; + this.status = status; + this.active = true; + } + + public int getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(final String email) { + this.email = email; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public int getAge() { + return age; + } + + public void setAge(final int age) { + this.age = age; + } + + public LocalDate getCreationDate() { + return creationDate; + } + + public List getPossessionList() { + return possessionList; + } + + public void setPossessionList(List possessionList) { + this.possessionList = possessionList; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("User [name=").append(name).append(", id=").append(id).append("]"); + return builder.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return id == user.id && + age == user.age && + Objects.equals(name, user.name) && + Objects.equals(creationDate, user.creationDate) && + Objects.equals(email, user.email) && + Objects.equals(status, user.status); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, creationDate, age, email, status); + } + + public LocalDate getLastLoginDate() { + return lastLoginDate; + } + + public void setLastLoginDate(LocalDate lastLoginDate) { + this.lastLoginDate = lastLoginDate; + } + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } + +} \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/IFooService.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/IFooService.java new file mode 100644 index 0000000000..26d0171551 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/IFooService.java @@ -0,0 +1,11 @@ +package org.baeldung.spring.data.persistence.service; + +import org.baeldung.spring.data.persistence.model.Foo; + +import com.baeldung.persistence.dao.common.IOperations; + +public interface IFooService extends IOperations { + + Foo retrieveByName(String name); + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/common/AbstractService.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/common/AbstractService.java new file mode 100644 index 0000000000..cf28d5e5c6 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/common/AbstractService.java @@ -0,0 +1,56 @@ +package org.baeldung.spring.data.persistence.service.common; + +import java.io.Serializable; +import java.util.List; + +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.persistence.dao.common.IOperations; +import com.google.common.collect.Lists; + +@Transactional +public abstract class AbstractService implements IOperations { + + // read - one + + @Override + @Transactional(readOnly = true) + public T findOne(final long id) { + return getDao().findById(id).orElse(null); + } + + // read - all + + @Override + @Transactional(readOnly = true) + public List findAll() { + return Lists.newArrayList(getDao().findAll()); + } + + // write + + @Override + public T create(final T entity) { + return getDao().save(entity); + } + + @Override + public T update(final T entity) { + return getDao().save(entity); + } + + @Override + public void delete(T entity) { + getDao().delete(entity); + } + + @Override + public void deleteById(long entityId) { + T entity = findOne(entityId); + delete(entity); + } + + protected abstract PagingAndSortingRepository getDao(); + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/impl/FooService.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/impl/FooService.java new file mode 100644 index 0000000000..b7ed496df1 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/impl/FooService.java @@ -0,0 +1,38 @@ +package org.baeldung.spring.data.persistence.service.impl; + + +import org.baeldung.spring.data.persistence.model.Foo; +import org.baeldung.spring.data.persistence.dao.IFooDao; +import org.baeldung.spring.data.persistence.service.IFooService; +import org.baeldung.spring.data.persistence.service.common.AbstractService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class FooService extends AbstractService implements IFooService { + + @Autowired + private IFooDao dao; + + public FooService() { + super(); + } + + // API + + @Override + protected PagingAndSortingRepository getDao() { + return dao; + } + + // custom methods + + @Override + public Foo retrieveByName(final String name) { + return dao.retrieveByName(name); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/util/IDUtil.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/util/IDUtil.java new file mode 100644 index 0000000000..85ab623e5f --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/util/IDUtil.java @@ -0,0 +1,33 @@ +package org.baeldung.util; + +import java.util.Random; + +public final class IDUtil { + + private IDUtil() { + throw new AssertionError(); + } + + // API + + public static String randomPositiveLongAsString() { + return Long.toString(randomPositiveLong()); + } + + public static String randomNegativeLongAsString() { + return Long.toString(randomNegativeLong()); + } + + public static long randomPositiveLong() { + long id = new Random().nextLong() * 10000; + id = (id < 0) ? (-1 * id) : id; + return id; + } + + private static long randomNegativeLong() { + long id = new Random().nextLong() * 10000; + id = (id > 0) ? (-1 * id) : id; + return id; + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml new file mode 100644 index 0000000000..bbb61cb3e0 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + ${hibernate.hbm2ddl.auto} + ${hibernate.dialect} + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Configuration.xml b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Configuration.xml new file mode 100644 index 0000000000..cb6cf0aa5c --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Configuration.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + ${hibernate.hbm2ddl.auto} + ${hibernate.dialect} + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml b/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml new file mode 100644 index 0000000000..ec0dc2469a --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence-h2.properties b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-h2.properties new file mode 100644 index 0000000000..716a96fde3 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-h2.properties @@ -0,0 +1,13 @@ +# jdbc.X +jdbc.driverClassName=org.h2.Driver +jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +jdbc.user=sa +jdbc.pass= + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=true +hibernate.hbm2ddl.auto=create-drop +hibernate.cache.use_second_level_cache=true +hibernate.cache.use_query_cache=true +hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties new file mode 100644 index 0000000000..b3cfd31f46 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties @@ -0,0 +1,13 @@ +# jdbc.X +jdbc.driverClassName=com.mysql.cj.jdbc.Driver +jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate5_01?createDatabaseIfNotExist=true +jdbc.eventGeneratedId=tutorialuser +jdbc.pass=tutorialmy5ql + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.MySQL5Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create-drop + +# envers.X +envers.audit_table_suffix=_audit_log diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml b/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml new file mode 100644 index 0000000000..6304fa0a65 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + ${hibernate.hbm2ddl.auto} + ${hibernate.dialect} + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/springDataPersistenceConfig.xml b/persistence-modules/spring-persistence-simple/src/main/resources/springDataPersistenceConfig.xml new file mode 100644 index 0000000000..d6d0ec6e47 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/springDataPersistenceConfig.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/stored_procedure.sql b/persistence-modules/spring-persistence-simple/src/main/resources/stored_procedure.sql new file mode 100644 index 0000000000..9cedb75c37 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/main/resources/stored_procedure.sql @@ -0,0 +1,20 @@ +DELIMITER // + CREATE PROCEDURE GetFoosByName(IN fooName VARCHAR(255)) + LANGUAGE SQL + DETERMINISTIC + SQL SECURITY DEFINER + BEGIN + SELECT * FROM foo WHERE name = fooName; + END // +DELIMITER ; + + +DELIMITER // + CREATE PROCEDURE GetAllFoos() + LANGUAGE SQL + DETERMINISTIC + SQL SECURITY DEFINER + BEGIN + SELECT * FROM foo; + END // +DELIMITER ; \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java new file mode 100644 index 0000000000..c41423643a --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java @@ -0,0 +1,185 @@ +package com.baeldung.hibernate.bootstrap; + +import com.baeldung.hibernate.bootstrap.model.TestEntity; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.Commit; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.test.context.transaction.TestTransaction; +import org.springframework.transaction.annotation.Transactional; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { HibernateConf.class }) +@Transactional +public class HibernateBootstrapIntegrationTest { + + @Autowired + private SessionFactory sessionFactory; + + @Test + public void whenBootstrapHibernateSession_thenNoException() { + + Session session = sessionFactory.getCurrentSession(); + + TestEntity newEntity = new TestEntity(); + newEntity.setId(1); + session.save(newEntity); + + TestEntity searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + } + + @Test + public void whenProgrammaticTransactionCommit_thenEntityIsInDatabase() { + assertTrue(TestTransaction.isActive()); + + //Save an entity and commit. + Session session = sessionFactory.getCurrentSession(); + + TestEntity newEntity = new TestEntity(); + newEntity.setId(1); + session.save(newEntity); + + TestEntity searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + assertTrue(TestTransaction.isFlaggedForRollback()); + + TestTransaction.flagForCommit(); + TestTransaction.end(); + + assertFalse(TestTransaction.isFlaggedForRollback()); + assertFalse(TestTransaction.isActive()); + + //Check that the entity is still there in a new transaction, + //then delete it, but don't commit. + TestTransaction.start(); + + assertTrue(TestTransaction.isFlaggedForRollback()); + assertTrue(TestTransaction.isActive()); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + + session.delete(searchEntity); + session.flush(); + + TestTransaction.end(); + + assertFalse(TestTransaction.isActive()); + + //Check that the entity is still there in a new transaction, + //then delete it and commit. + TestTransaction.start(); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + + session.delete(searchEntity); + session.flush(); + + assertTrue(TestTransaction.isActive()); + + TestTransaction.flagForCommit(); + TestTransaction.end(); + + assertFalse(TestTransaction.isActive()); + + //Check that the entity is no longer there in a new transaction. + TestTransaction.start(); + + assertTrue(TestTransaction.isActive()); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNull(searchEntity); + } + + @Test + @Commit + public void givenTransactionCommitDefault_whenProgrammaticTransactionCommit_thenEntityIsInDatabase() { + assertTrue(TestTransaction.isActive()); + + //Save an entity and commit. + Session session = sessionFactory.getCurrentSession(); + + TestEntity newEntity = new TestEntity(); + newEntity.setId(1); + session.save(newEntity); + + TestEntity searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + assertFalse(TestTransaction.isFlaggedForRollback()); + + TestTransaction.end(); + + assertFalse(TestTransaction.isFlaggedForRollback()); + assertFalse(TestTransaction.isActive()); + + //Check that the entity is still there in a new transaction, + //then delete it, but don't commit. + TestTransaction.start(); + + assertFalse(TestTransaction.isFlaggedForRollback()); + assertTrue(TestTransaction.isActive()); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + + session.delete(searchEntity); + session.flush(); + + TestTransaction.flagForRollback(); + TestTransaction.end(); + + assertFalse(TestTransaction.isActive()); + + //Check that the entity is still there in a new transaction, + //then delete it and commit. + TestTransaction.start(); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + + session.delete(searchEntity); + session.flush(); + + assertTrue(TestTransaction.isActive()); + + TestTransaction.end(); + + assertFalse(TestTransaction.isActive()); + + //Check that the entity is no longer there in a new transaction. + TestTransaction.start(); + + assertTrue(TestTransaction.isActive()); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNull(searchEntity); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateXMLBootstrapIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateXMLBootstrapIntegrationTest.java new file mode 100644 index 0000000000..5b811ad576 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateXMLBootstrapIntegrationTest.java @@ -0,0 +1,36 @@ +package com.baeldung.hibernate.bootstrap; + +import com.baeldung.hibernate.bootstrap.model.TestEntity; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { HibernateXMLConf.class }) +@Transactional +public class HibernateXMLBootstrapIntegrationTest { + + @Autowired + private SessionFactory sessionFactory; + + @Test + public void whenBootstrapHibernateSession_thenNoException() { + + Session session = sessionFactory.getCurrentSession(); + + TestEntity newEntity = new TestEntity(); + newEntity.setId(1); + session.save(newEntity); + + TestEntity searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java new file mode 100644 index 0000000000..76c34affb9 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java @@ -0,0 +1,157 @@ +package org.baeldung.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.lessThan; +import static org.junit.Assert.assertThat; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +import org.baeldung.config.PersistenceJPAConfig; +import org.baeldung.persistence.model.Foo; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class FooPaginationPersistenceIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private FooService fooService; + + @Before + public final void before() { + final int minimalNumberOfEntities = 25; + if (fooService.findAll().size() <= minimalNumberOfEntities) { + for (int i = 0; i < minimalNumberOfEntities; i++) { + fooService.create(new Foo(randomAlphabetic(6))); + } + } + } + + // tests + + @Test + public final void whenContextIsBootstrapped_thenNoExceptions() { + // + } + + @SuppressWarnings("unchecked") + @Test + public final void givenEntitiesExist_whenRetrievingFirstPage_thenCorrect() { + final int pageSize = 10; + + final Query query = entityManager.createQuery("From Foo"); + configurePagination(query, 1, pageSize); + + // When + final List fooList = query.getResultList(); + + // Then + assertThat(fooList, hasSize(pageSize)); + } + + @SuppressWarnings("unchecked") + @Test + public final void givenEntitiesExist_whenRetrievingLastPage_thenCorrect() { + final int pageSize = 10; + final Query queryTotal = entityManager.createQuery("Select count(f.id) from Foo f"); + final long countResult = (long) queryTotal.getSingleResult(); + + final Query query = entityManager.createQuery("Select f from Foo as f order by f.id"); + final int lastPage = (int) ((countResult / pageSize) + 1); + configurePagination(query, lastPage, pageSize); + final List fooList = query.getResultList(); + + // Then + assertThat(fooList, hasSize(lessThan(pageSize + 1))); + } + + @SuppressWarnings("unchecked") + @Test + public final void givenEntitiesExist_whenRetrievingPage_thenCorrect() { + final int pageSize = 10; + + final Query queryIds = entityManager.createQuery("Select f.id from Foo f order by f.name"); + final List fooIds = queryIds.getResultList(); + + final Query query = entityManager.createQuery("Select f from Foo as f where f.id in :ids"); + query.setParameter("ids", fooIds.subList(0, pageSize)); + + final List fooList = query.getResultList(); + + // Then + assertThat(fooList, hasSize(pageSize)); + } + + @Test + public final void givenEntitiesExist_whenRetrievingPageViaCriteria_thenCorrect() { + final int pageSize = 10; + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class); + final Root from = criteriaQuery.from(Foo.class); + final CriteriaQuery select = criteriaQuery.select(from); + final TypedQuery typedQuery = entityManager.createQuery(select); + typedQuery.setFirstResult(0); + typedQuery.setMaxResults(pageSize); + final List fooList = typedQuery.getResultList(); + + // Then + assertThat(fooList, hasSize(pageSize)); + } + + @Test + public final void givenEntitiesExist_whenRetrievingPageViaCriteria_thenNoExceptions() { + int pageNumber = 1; + final int pageSize = 10; + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + + final CriteriaQuery countQuery = criteriaBuilder.createQuery(Long.class); + countQuery.select(criteriaBuilder.count(countQuery.from(Foo.class))); + final Long count = entityManager.createQuery(countQuery).getSingleResult(); + + final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class); + final Root from = criteriaQuery.from(Foo.class); + final CriteriaQuery select = criteriaQuery.select(from); + + TypedQuery typedQuery; + while (pageNumber < count.intValue()) { + typedQuery = entityManager.createQuery(select); + typedQuery.setFirstResult(pageNumber - 1); + typedQuery.setMaxResults(pageSize); + System.out.println("Current page: " + typedQuery.getResultList()); + pageNumber += pageSize; + } + + } + + // UTIL + + final int determineLastPage(final int pageSize, final long countResult) { + return (int) (countResult / pageSize) + 1; + } + + final void configurePagination(final Query query, final int pageNumber, final int pageSize) { + query.setFirstResult((pageNumber - 1) * pageSize); + query.setMaxResults(pageSize); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java new file mode 100644 index 0000000000..e1b53c8ded --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java @@ -0,0 +1,69 @@ +package org.baeldung.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; + +import org.baeldung.config.PersistenceJPAConfig; +import org.baeldung.persistence.model.Foo; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class FooServicePersistenceIntegrationTest { + + @Autowired + private FooService service; + + // tests + + @Test + public final void whenContextIsBootstrapped_thenNoExceptions() { + // + } + + @Test + public final void whenEntityIsCreated_thenNoExceptions() { + service.create(new Foo(randomAlphabetic(6))); + } + + @Test(expected = DataIntegrityViolationException.class) + public final void whenInvalidEntityIsCreated_thenDataException() { + service.create(new Foo(randomAlphabetic(2048))); + } + + @Test(expected = DataIntegrityViolationException.class) + public final void whenEntityWithLongNameIsCreated_thenDataException() { + service.create(new Foo(randomAlphabetic(2048))); + } + + @Test(expected = InvalidDataAccessApiUsageException.class) + public final void whenSameEntityIsCreatedTwice_thenDataException() { + final Foo entity = new Foo(randomAlphabetic(8)); + service.create(entity); + service.create(entity); + } + + @Test(expected = DataAccessException.class) + public final void temp_whenInvalidEntityIsCreated_thenDataException() { + service.create(new Foo(randomAlphabetic(2048))); + } + + @Test + public final void whenEntityIsCreated_thenFound() { + final Foo fooEntity = new Foo("abc"); + service.create(fooEntity); + final Foo found = service.findOne(fooEntity.getId()); + Assert.assertNotNull(found); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingIntegrationTest.java new file mode 100644 index 0000000000..40249b4b30 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingIntegrationTest.java @@ -0,0 +1,118 @@ +package org.baeldung.persistence.service; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +import org.baeldung.config.PersistenceJPAConfig; +import org.baeldung.persistence.model.Bar; +import org.baeldung.persistence.model.Foo; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class) +@DirtiesContext +@SuppressWarnings("unchecked") +public class FooServiceSortingIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + // tests + + @Test + public final void whenSortingByOneAttributeDefaultOrder_thenPrintSortedResult() { + final String jql = "Select f from Foo as f order by f.id"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + } + } + + @Test + public final void whenSortingByOneAttributeSetOrder_thenSortedPrintResult() { + final String jql = "Select f from Foo as f order by f.id desc"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + } + } + + @Test + public final void whenSortingByTwoAttributes_thenPrintSortedResult() { + final String jql = "Select f from Foo as f order by f.name asc, f.id desc"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + } + } + + @Test + public final void whenSortingFooByBar_thenBarsSorted() { + final String jql = "Select f from Foo as f order by f.name, f.bar.id"; + final Query barJoinQuery = entityManager.createQuery(jql); + final List fooList = barJoinQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName()); + if (foo.getBar() != null) { + System.out.print("-------BarId:" + foo.getBar().getId()); + } + } + } + + @Test + public final void whenSortinfBar_thenPrintBarsSortedWithFoos() { + final String jql = "Select b from Bar as b order by b.id"; + final Query barQuery = entityManager.createQuery(jql); + final List barList = barQuery.getResultList(); + for (final Bar bar : barList) { + System.out.println("Bar Id:" + bar.getId()); + for (final Foo foo : bar.getFooList()) { + System.out.println("FooName:" + foo.getName()); + } + } + } + + @Test + public final void whenSortingFooWithCriteria_thenPrintSortedFoos() { + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class); + final Root from = criteriaQuery.from(Foo.class); + final CriteriaQuery select = criteriaQuery.select(from); + criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name"))); + final TypedQuery typedQuery = entityManager.createQuery(select); + final List fooList = typedQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "--------Id:" + foo.getId()); + } + } + + @Test + public final void whenSortingFooWithCriteriaAndMultipleAttributes_thenPrintSortedFoos() { + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class); + final Root from = criteriaQuery.from(Foo.class); + final CriteriaQuery select = criteriaQuery.select(from); + criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")), criteriaBuilder.desc(from.get("id"))); + final TypedQuery typedQuery = entityManager.createQuery(select); + final List fooList = typedQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + } + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java new file mode 100644 index 0000000000..c530003ac1 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java @@ -0,0 +1,64 @@ +package org.baeldung.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.junit.Assert.assertNull; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import org.baeldung.config.PersistenceJPAConfig; +import org.baeldung.persistence.model.Foo; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class FooServiceSortingWitNullsManualIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private FooService service; + + // tests + + @SuppressWarnings("unchecked") + @Test + public final void whenSortingByStringNullLast_thenLastNull() { + service.create(new Foo()); + service.create(new Foo(randomAlphabetic(6))); + + final String jql = "Select f from Foo as f order by f.name desc NULLS LAST"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + assertNull(fooList.get(fooList.toArray().length - 1).getName()); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName()); + } + } + + @SuppressWarnings("unchecked") + @Test + public final void whenSortingByStringNullFirst_thenFirstNull() { + service.create(new Foo()); + + final String jql = "Select f from Foo as f order by f.name desc NULLS FIRST"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + assertNull(fooList.get(0).getName()); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName()); + } + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooStoredProceduresLiveTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooStoredProceduresLiveTest.java new file mode 100644 index 0000000000..ded32e362e --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooStoredProceduresLiveTest.java @@ -0,0 +1,123 @@ +package org.baeldung.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.baeldung.config.PersistenceConfig; +import org.baeldung.persistence.model.Foo; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.exception.SQLGrammarException; +import org.hibernate.query.NativeQuery; +import org.hibernate.query.Query; +import org.junit.After; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class FooStoredProceduresLiveTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(FooStoredProceduresLiveTest.class); + + @Autowired + private SessionFactory sessionFactory; + + @Autowired + private FooService fooService; + + private Session session; + + @Before + public final void before() { + session = sessionFactory.openSession(); + Assume.assumeTrue(getAllFoosExists()); + Assume.assumeTrue(getFoosByNameExists()); + } + + private boolean getFoosByNameExists() { + try { + @SuppressWarnings("unchecked") + NativeQuery sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class); + sqlQuery.list(); + return true; + } catch (SQLGrammarException e) { + LOGGER.error("WARNING : GetFoosByName() Procedure is may be missing ", e); + return false; + } + } + + private boolean getAllFoosExists() { + try { + @SuppressWarnings("unchecked") + NativeQuery sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class); + sqlQuery.list(); + return true; + } catch (SQLGrammarException e) { + LOGGER.error("WARNING : GetAllFoos() Procedure is may be missing ", e); + return false; + } + } + + @After + public final void after() { + session.close(); + } + + @Test + public final void getAllFoosUsingStoredProcedures() { + + fooService.create(new Foo(randomAlphabetic(6))); + + // Stored procedure getAllFoos using createSQLQuery + @SuppressWarnings("unchecked") + NativeQuery sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class); + List allFoos = sqlQuery.list(); + for (Foo foo : allFoos) { + LOGGER.info("getAllFoos() SQL Query result : {}", foo.getName()); + } + assertEquals(allFoos.size(), fooService.findAll().size()); + + // Stored procedure getAllFoos using a Named Query + @SuppressWarnings("unchecked") + Query namedQuery = session.getNamedQuery("callGetAllFoos"); + List allFoos2 = namedQuery.list(); + for (Foo foo : allFoos2) { + LOGGER.info("getAllFoos() NamedQuery result : {}", foo.getName()); + } + assertEquals(allFoos2.size(), fooService.findAll().size()); + } + + @Test + public final void getFoosByNameUsingStoredProcedures() { + + fooService.create(new Foo("NewFooName")); + + // Stored procedure getFoosByName using createSQLQuery() + @SuppressWarnings("unchecked") + Query sqlQuery = session.createSQLQuery("CALL GetFoosByName(:fooName)").addEntity(Foo.class).setParameter("fooName", "NewFooName"); + List allFoosByName = sqlQuery.list(); + for (Foo foo : allFoosByName) { + LOGGER.info("getFoosByName() using SQL Query : found => {}", foo.toString()); + } + + // Stored procedure getFoosByName using getNamedQuery() + @SuppressWarnings("unchecked") + Query namedQuery = session.getNamedQuery("callGetFoosByName").setParameter("fooName", "NewFooName"); + List allFoosByName2 = namedQuery.list(); + for (Foo foo : allFoosByName2) { + LOGGER.info("getFoosByName() using Native Query : found => {}", foo.toString()); + } + + } +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCommon.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCommon.java new file mode 100644 index 0000000000..8f119a04e0 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCommon.java @@ -0,0 +1,561 @@ +package org.baeldung.spring.data.persistence.dao.user; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import javax.persistence.EntityManager; +import javax.persistence.Query; + +import org.baeldung.spring.data.persistence.config.PersistenceConfig; +import org.baeldung.spring.data.persistence.model.User; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.JpaSort; +import org.springframework.data.mapping.PropertyReferenceException; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.transaction.annotation.Transactional; + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class UserRepositoryCommon { + + final String USER_EMAIL = "email@example.com"; + final String USER_EMAIL2 = "email2@example.com"; + final String USER_EMAIL3 = "email3@example.com"; + final String USER_EMAIL4 = "email4@example.com"; + final Integer INACTIVE_STATUS = 0; + final Integer ACTIVE_STATUS = 1; + final String USER_EMAIL5 = "email5@example.com"; + final String USER_EMAIL6 = "email6@example.com"; + final String USER_NAME_ADAM = "Adam"; + final String USER_NAME_PETER = "Peter"; + + @Autowired + protected UserRepository userRepository; + @Autowired + private EntityManager entityManager; + + @Test + @Transactional + public void givenUsersWithSameNameInDB_WhenFindAllByName_ThenReturnStreamOfUsers() { + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_ADAM); + user2.setEmail(USER_EMAIL2); + userRepository.save(user2); + + User user3 = new User(); + user3.setName(USER_NAME_ADAM); + user3.setEmail(USER_EMAIL3); + userRepository.save(user3); + + User user4 = new User(); + user4.setName("SAMPLE"); + user4.setEmail(USER_EMAIL4); + userRepository.save(user4); + + try (Stream foundUsersStream = userRepository.findAllByName(USER_NAME_ADAM)) { + assertThat(foundUsersStream.count()).isEqualTo(3l); + } + } + + @Test + public void givenUsersInDB_WhenFindAllWithQueryAnnotation_ThenReturnCollectionWithActiveUsers() { + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + user1.setStatus(ACTIVE_STATUS); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_ADAM); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User user3 = new User(); + user3.setName(USER_NAME_ADAM); + user3.setEmail(USER_EMAIL3); + user3.setStatus(INACTIVE_STATUS); + userRepository.save(user3); + + Collection allActiveUsers = userRepository.findAllActiveUsers(); + + assertThat(allActiveUsers.size()).isEqualTo(2); + } + + @Test + public void givenUsersInDB_WhenFindAllWithQueryAnnotationNative_ThenReturnCollectionWithActiveUsers() { + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + user1.setStatus(ACTIVE_STATUS); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_ADAM); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User user3 = new User(); + user3.setName(USER_NAME_ADAM); + user3.setEmail(USER_EMAIL3); + user3.setStatus(INACTIVE_STATUS); + userRepository.save(user3); + + Collection allActiveUsers = userRepository.findAllActiveUsersNative(); + + assertThat(allActiveUsers.size()).isEqualTo(2); + } + + @Test + public void givenUserInDB_WhenFindUserByStatusWithQueryAnnotation_ThenReturnActiveUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByStatus(ACTIVE_STATUS); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUserInDB_WhenFindUserByStatusWithQueryAnnotationNative_ThenReturnActiveUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByStatusNative(ACTIVE_STATUS); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationIndexedParams_ThenReturnOneUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User userByStatus = userRepository.findUserByStatusAndName(ACTIVE_STATUS, USER_NAME_ADAM); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationNamedParams_ThenReturnOneUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User userByStatus = userRepository.findUserByStatusAndNameNamedParams(ACTIVE_STATUS, USER_NAME_ADAM); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationNativeNamedParams_ThenReturnOneUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User userByStatus = userRepository.findUserByStatusAndNameNamedParamsNative(ACTIVE_STATUS, USER_NAME_ADAM); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationNamedParamsCustomNames_ThenReturnOneUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + user2.setStatus(ACTIVE_STATUS); + userRepository.save(user2); + + User userByStatus = userRepository.findUserByUserStatusAndUserName(ACTIVE_STATUS, USER_NAME_ADAM); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByNameLikeWithQueryAnnotationIndexedParams_ThenReturnUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByNameLike("Ad"); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByNameLikeWithQueryAnnotationNamedParams_ThenReturnUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByNameLikeNamedParam("Ad"); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindUserByNameLikeWithQueryAnnotationNative_ThenReturnUser() { + User user = new User(); + user.setName(USER_NAME_ADAM); + user.setEmail(USER_EMAIL); + user.setStatus(ACTIVE_STATUS); + userRepository.save(user); + + User userByStatus = userRepository.findUserByNameLikeNative("Ad"); + + assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindAllWithSortByName_ThenReturnUsersSorted() { + userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); + + List usersSortByName = userRepository.findAll(new Sort(Sort.Direction.ASC, "name")); + + assertThat(usersSortByName.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test(expected = PropertyReferenceException.class) + public void givenUsersInDB_WhenFindAllSortWithFunction_ThenThrowException() { + userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); + + userRepository.findAll(new Sort(Sort.Direction.ASC, "name")); + + List usersSortByNameLength = userRepository.findAll(Sort.by("LENGTH(name)")); + + assertThat(usersSortByNameLength.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindAllSortWithFunctionQueryAnnotationJPQL_ThenReturnUsersSorted() { + userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); + + userRepository.findAllUsers(Sort.by("name")); + + List usersSortByNameLength = userRepository.findAllUsers(JpaSort.unsafe("LENGTH(name)")); + + assertThat(usersSortByNameLength.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); + } + + @Test + public void givenUsersInDB_WhenFindAllWithPageRequestQueryAnnotationJPQL_ThenReturnPageOfUsers() { + userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); + userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL4, INACTIVE_STATUS)); + userRepository.save(new User("SAMPLE2", LocalDate.now(), USER_EMAIL5, INACTIVE_STATUS)); + userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL6, INACTIVE_STATUS)); + + Page usersPage = userRepository.findAllUsersWithPagination(PageRequest.of(1, 3)); + + assertThat(usersPage.getContent() + .get(0) + .getName()).isEqualTo("SAMPLE1"); + } + + @Test + public void givenUsersInDB_WhenFindAllWithPageRequestQueryAnnotationNative_ThenReturnPageOfUsers() { + userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); + userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL4, INACTIVE_STATUS)); + userRepository.save(new User("SAMPLE2", LocalDate.now(), USER_EMAIL5, INACTIVE_STATUS)); + userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL6, INACTIVE_STATUS)); + + Page usersSortByNameLength = userRepository.findAllUsersWithPaginationNative(PageRequest.of(1, 3)); + + assertThat(usersSortByNameLength.getContent() + .get(0) + .getName()).isEqualTo(USER_NAME_PETER); + } + + @Test + @Transactional + public void givenUsersInDB_WhenUpdateStatusForNameModifyingQueryAnnotationJPQL_ThenModifyMatchingUsers() { + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL4, ACTIVE_STATUS)); + + int updatedUsersSize = userRepository.updateUserSetStatusForName(INACTIVE_STATUS, "SAMPLE"); + + assertThat(updatedUsersSize).isEqualTo(2); + } + + @Test + public void givenUsersInDB_WhenFindByEmailsWithDynamicQuery_ThenReturnCollection() { + + User user1 = new User(); + user1.setEmail(USER_EMAIL); + userRepository.save(user1); + + User user2 = new User(); + user2.setEmail(USER_EMAIL2); + userRepository.save(user2); + + User user3 = new User(); + user3.setEmail(USER_EMAIL3); + userRepository.save(user3); + + Set emails = new HashSet<>(); + emails.add(USER_EMAIL2); + emails.add(USER_EMAIL3); + + Collection usersWithEmails = userRepository.findUserByEmails(emails); + + assertThat(usersWithEmails.size()).isEqualTo(2); + } + + @Test + public void givenUsersInDBWhenFindByNameListReturnCollection() { + + User user1 = new User(); + user1.setName(USER_NAME_ADAM); + user1.setEmail(USER_EMAIL); + userRepository.save(user1); + + User user2 = new User(); + user2.setName(USER_NAME_PETER); + user2.setEmail(USER_EMAIL2); + userRepository.save(user2); + + List names = Arrays.asList(USER_NAME_ADAM, USER_NAME_PETER); + + List usersWithNames = userRepository.findUserByNameList(names); + + assertThat(usersWithNames.size()).isEqualTo(2); + } + + + @Test + @Transactional + public void whenInsertedWithQuery_ThenUserIsPersisted() { + userRepository.insertUser(USER_NAME_ADAM, 1, USER_EMAIL, ACTIVE_STATUS, true); + userRepository.insertUser(USER_NAME_PETER, 1, USER_EMAIL2, ACTIVE_STATUS, true); + + User userAdam = userRepository.findUserByNameLike(USER_NAME_ADAM); + User userPeter = userRepository.findUserByNameLike(USER_NAME_PETER); + + assertThat(userAdam).isNotNull(); + assertThat(userAdam.getEmail()).isEqualTo(USER_EMAIL); + assertThat(userPeter).isNotNull(); + assertThat(userPeter.getEmail()).isEqualTo(USER_EMAIL2); + } + + + @Test + @Transactional + public void givenTwoUsers_whenFindByNameUsr01_ThenUserUsr01() { + User usr01 = new User("usr01", LocalDate.now(), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.now(), "usr02@baeldung.com", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + try (Stream users = userRepository.findAllByName("usr01")) { + assertTrue(users.allMatch(usr -> usr.equals(usr01))); + } + } + + @Test + @Transactional + public void givenTwoUsers_whenFindByNameUsr00_ThenNoUsers() { + User usr01 = new User("usr01", LocalDate.now(), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.now(), "usr02@baeldung.com", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + try (Stream users = userRepository.findAllByName("usr00")) { + assertEquals(0, users.count()); + } + } + + @Test + public void givenTwoUsers_whenFindUsersWithGmailAddress_ThenUserUsr02() { + User usr01 = new User("usr01", LocalDate.now(), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.now(), "usr02@gmail.com", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + List users = userRepository.findUsersWithGmailAddress(); + assertEquals(1, users.size()); + assertEquals(usr02, users.get(0)); + } + + @Test + @Transactional + public void givenTwoUsers_whenDeleteAllByCreationDateAfter_ThenOneUserRemains() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.com", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + userRepository.deleteAllByCreationDateAfter(LocalDate.of(2018, 5, 1)); + + List users = userRepository.findAll(); + + assertEquals(1, users.size()); + assertEquals(usr01, users.get(0)); + } + + @Test + public void givenTwoUsers_whenFindAllUsersByPredicates_ThenUserUsr01() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.org", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + List> predicates = new ArrayList<>(); + predicates.add(usr -> usr.getCreationDate().isAfter(LocalDate.of(2017, 12, 31))); + predicates.add(usr -> usr.getEmail().endsWith(".com")); + + List users = userRepository.findAllUsersByPredicates(predicates); + + assertEquals(1, users.size()); + assertEquals(usr01, users.get(0)); + } + + @Test + @Transactional + public void givenTwoUsers_whenDeactivateUsersNotLoggedInSince_ThenUserUsr02Deactivated() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + usr01.setLastLoginDate(LocalDate.now()); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.org", 1); + usr02.setLastLoginDate(LocalDate.of(2018, 7, 20)); + + userRepository.save(usr01); + userRepository.save(usr02); + + userRepository.deactivateUsersNotLoggedInSince(LocalDate.of(2018, 8, 1)); + + List users = userRepository.findAllUsers(Sort.by(Sort.Order.asc("name"))); + assertTrue(users.get(0).isActive()); + assertFalse(users.get(1).isActive()); + } + + @Test + @Transactional + public void givenTwoUsers_whenDeleteDeactivatedUsers_ThenUserUsr02Deleted() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + usr01.setLastLoginDate(LocalDate.now()); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.com", 0); + usr02.setLastLoginDate(LocalDate.of(2018, 7, 20)); + usr02.setActive(false); + + userRepository.save(usr01); + userRepository.save(usr02); + + int deletedUsersCount = userRepository.deleteDeactivatedUsers(); + + List users = userRepository.findAll(); + assertEquals(1, users.size()); + assertEquals(usr01, users.get(0)); + assertEquals(1, deletedUsersCount); + } + + @Test + @Transactional + public void givenTwoUsers_whenAddDeletedColumn_ThenUsersHaveDeletedColumn() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + usr01.setLastLoginDate(LocalDate.now()); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.org", 1); + usr02.setLastLoginDate(LocalDate.of(2018, 7, 20)); + usr02.setActive(false); + + userRepository.save(usr01); + userRepository.save(usr02); + + userRepository.addDeletedColumn(); + + Query nativeQuery = entityManager.createNativeQuery("select deleted from USERS where NAME = 'usr01'"); + assertEquals(0, nativeQuery.getResultList().get(0)); + } + + @After + public void cleanUp() { + userRepository.deleteAll(); + } +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryIntegrationTest.java new file mode 100644 index 0000000000..b9b644f7e0 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryIntegrationTest.java @@ -0,0 +1,38 @@ +package org.baeldung.spring.data.persistence.dao.user; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalDate; + +import org.baeldung.spring.data.persistence.config.PersistenceConfig; +import org.baeldung.spring.data.persistence.model.User; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.transaction.annotation.Transactional; + +/** + * Created by adam. + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class UserRepositoryIntegrationTest extends UserRepositoryCommon { + + @Test + @Transactional + public void givenUsersInDBWhenUpdateStatusForNameModifyingQueryAnnotationNativeThenModifyMatchingUsers() { + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL4, ACTIVE_STATUS)); + userRepository.flush(); + + int updatedUsersSize = userRepository.updateUserSetStatusForNameNative(INACTIVE_STATUS, "SAMPLE"); + + assertThat(updatedUsersSize).isEqualTo(2); + } +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/service/AbstractServicePersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/service/AbstractServicePersistenceIntegrationTest.java new file mode 100644 index 0000000000..acc73dfaf8 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/service/AbstractServicePersistenceIntegrationTest.java @@ -0,0 +1,256 @@ +package org.baeldung.spring.data.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; + +import java.io.Serializable; +import java.util.List; + +import org.baeldung.spring.data.persistence.model.Foo; +import org.baeldung.util.IDUtil; +import org.hamcrest.Matchers; +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.dao.DataAccessException; + +import com.baeldung.persistence.dao.common.IOperations; + +public abstract class AbstractServicePersistenceIntegrationTest { + + // tests + + // find - one + + @Test + /**/public final void givenResourceDoesNotExist_whenResourceIsRetrieved_thenNoResourceIsReceived() { + // When + final Foo createdResource = getApi().findOne(IDUtil.randomPositiveLong()); + + // Then + assertNull(createdResource); + } + + @Test + public void givenResourceExists_whenResourceIsRetrieved_thenNoExceptions() { + final Foo existingResource = persistNewEntity(); + getApi().findOne(existingResource.getId()); + } + + @Test + public void givenResourceDoesNotExist_whenResourceIsRetrieved_thenNoExceptions() { + getApi().findOne(IDUtil.randomPositiveLong()); + } + + @Test + public void givenResourceExists_whenResourceIsRetrieved_thenTheResultIsNotNull() { + final Foo existingResource = persistNewEntity(); + final Foo retrievedResource = getApi().findOne(existingResource.getId()); + assertNotNull(retrievedResource); + } + + @Test + public void givenResourceExists_whenResourceIsRetrieved_thenResourceIsRetrievedCorrectly() { + final Foo existingResource = persistNewEntity(); + final Foo retrievedResource = getApi().findOne(existingResource.getId()); + assertEquals(existingResource, retrievedResource); + } + + // find - one - by name + + // find - all + + @Test + /**/public void whenAllResourcesAreRetrieved_thenNoExceptions() { + getApi().findAll(); + } + + @Test + /**/public void whenAllResourcesAreRetrieved_thenTheResultIsNotNull() { + final List resources = getApi().findAll(); + + assertNotNull(resources); + } + + @Test + /**/public void givenAtLeastOneResourceExists_whenAllResourcesAreRetrieved_thenRetrievedResourcesAreNotEmpty() { + persistNewEntity(); + + // When + final List allResources = getApi().findAll(); + + // Then + assertThat(allResources, not(Matchers. empty())); + } + + @Test + /**/public void givenAnResourceExists_whenAllResourcesAreRetrieved_thenTheExistingResourceIsIndeedAmongThem() { + final Foo existingResource = persistNewEntity(); + + final List resources = getApi().findAll(); + + assertThat(resources, hasItem(existingResource)); + } + + @Test + /**/public void whenAllResourcesAreRetrieved_thenResourcesHaveIds() { + persistNewEntity(); + + // When + final List allResources = getApi().findAll(); + + // Then + for (final Foo resource : allResources) { + assertNotNull(resource.getId()); + } + } + + // create + + @Test(expected = RuntimeException.class) + /**/public void whenNullResourceIsCreated_thenException() { + getApi().create(null); + } + + @Test + /**/public void whenResourceIsCreated_thenNoExceptions() { + persistNewEntity(); + } + + @Test + /**/public void whenResourceIsCreated_thenResourceIsRetrievable() { + final Foo existingResource = persistNewEntity(); + + assertNotNull(getApi().findOne(existingResource.getId())); + } + + @Test + /**/public void whenResourceIsCreated_thenSavedResourceIsEqualToOriginalResource() { + final Foo originalResource = createNewEntity(); + final Foo savedResource = getApi().create(originalResource); + + assertEquals(originalResource, savedResource); + } + + @Test(expected = RuntimeException.class) + public void whenResourceWithFailedConstraintsIsCreated_thenException() { + final Foo invalidResource = createNewEntity(); + invalidate(invalidResource); + + getApi().create(invalidResource); + } + + /** + * -- specific to the persistence engine + */ + @Test(expected = DataAccessException.class) + @Ignore("Hibernate simply ignores the id silently and still saved (tracking this)") + public void whenResourceWithIdIsCreated_thenDataAccessException() { + final Foo resourceWithId = createNewEntity(); + resourceWithId.setId(IDUtil.randomPositiveLong()); + + getApi().create(resourceWithId); + } + + // update + + @Test(expected = RuntimeException.class) + /**/public void whenNullResourceIsUpdated_thenException() { + getApi().update(null); + } + + @Test + /**/public void givenResourceExists_whenResourceIsUpdated_thenNoExceptions() { + // Given + final Foo existingResource = persistNewEntity(); + + // When + getApi().update(existingResource); + } + + /** + * - can also be the ConstraintViolationException which now occurs on the update operation will not be translated; as a consequence, it will be a TransactionSystemException + */ + @Test(expected = RuntimeException.class) + public void whenResourceIsUpdatedWithFailedConstraints_thenException() { + final Foo existingResource = persistNewEntity(); + invalidate(existingResource); + + getApi().update(existingResource); + } + + @Test + /**/public void givenResourceExists_whenResourceIsUpdated_thenUpdatesArePersisted() { + // Given + final Foo existingResource = persistNewEntity(); + + // When + change(existingResource); + getApi().update(existingResource); + + final Foo updatedResource = getApi().findOne(existingResource.getId()); + + // Then + assertEquals(existingResource, updatedResource); + } + + // delete + + // @Test(expected = RuntimeException.class) + // public void givenResourceDoesNotExists_whenResourceIsDeleted_thenException() { + // // When + // getApi().delete(IDUtil.randomPositiveLong()); + // } + // + // @Test(expected = RuntimeException.class) + // public void whenResourceIsDeletedByNegativeId_thenException() { + // // When + // getApi().delete(IDUtil.randomNegativeLong()); + // } + // + // @Test + // public void givenResourceExists_whenResourceIsDeleted_thenNoExceptions() { + // // Given + // final Foo existingResource = persistNewEntity(); + // + // // When + // getApi().delete(existingResource.getId()); + // } + // + // @Test + // /**/public final void givenResourceExists_whenResourceIsDeleted_thenResourceNoLongerExists() { + // // Given + // final Foo existingResource = persistNewEntity(); + // + // // When + // getApi().delete(existingResource.getId()); + // + // // Then + // assertNull(getApi().findOne(existingResource.getId())); + // } + + // template method + + protected Foo createNewEntity() { + return new Foo(randomAlphabetic(6)); + } + + protected abstract IOperations getApi(); + + private final void invalidate(final Foo entity) { + entity.setName(null); + } + + private final void change(final Foo entity) { + entity.setName(randomAlphabetic(6)); + } + + protected Foo persistNewEntity() { + return getApi().create(createNewEntity()); + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/service/FooServicePersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/service/FooServicePersistenceIntegrationTest.java new file mode 100644 index 0000000000..8184a2320a --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/service/FooServicePersistenceIntegrationTest.java @@ -0,0 +1,77 @@ +package org.baeldung.spring.data.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.junit.Assert.assertNotNull; + +import org.baeldung.spring.data.persistence.model.Foo; +import org.baeldung.spring.data.persistence.config.PersistenceConfig; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.baeldung.persistence.dao.common.IOperations; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class FooServicePersistenceIntegrationTest extends AbstractServicePersistenceIntegrationTest { + + @Autowired + private IFooService service; + + // tests + + @Test + public final void whenContextIsBootstrapped_thenNoExceptions() { + // + } + + @Test + public final void whenEntityIsCreated_thenNoExceptions() { + service.create(new Foo(randomAlphabetic(6))); + } + + @Test(expected = DataIntegrityViolationException.class) + public final void whenInvalidEntityIsCreated_thenDataException() { + service.create(new Foo()); + } + + @Test(expected = DataIntegrityViolationException.class) + public final void whenEntityWithLongNameIsCreated_thenDataException() { + service.create(new Foo(randomAlphabetic(2048))); + } + + // custom Query method + + @Test + public final void givenUsingCustomQuery_whenRetrievingEntity_thenFound() { + final String name = randomAlphabetic(6); + service.create(new Foo(name)); + + final Foo retrievedByName = service.retrieveByName(name); + assertNotNull(retrievedByName); + } + + // work in progress + + @Test(expected = InvalidDataAccessApiUsageException.class) + @Ignore("Right now, persist has saveOrUpdate semantics, so this will no longer fail") + public final void whenSameEntityIsCreatedTwice_thenDataException() { + final Foo entity = new Foo(randomAlphabetic(8)); + service.create(entity); + service.create(entity); + } + + // API + + @Override + protected final IOperations getApi() { + return service; + } + +} diff --git a/persistence-modules/spring-persistence-simple/src/test/resources/.gitignore b/persistence-modules/spring-persistence-simple/src/test/resources/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/resources/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2af980325e..9298c8ad17 100644 --- a/pom.xml +++ b/pom.xml @@ -608,6 +608,7 @@ spring-5-reactive-security spring-5-security spring-5-security-oauth + spring-5-security-cognito spring-activiti spring-akka @@ -634,7 +635,6 @@ spring-boot-custom-starter spring-boot-disable-console-logging - spring-boot-exceptions spring-boot-jasypt spring-boot-keycloak spring-boot-logging-log4j2 @@ -819,6 +819,7 @@ spring-5-reactive-security spring-5-security spring-5-security-oauth + spring-5-security-cognito spring-activiti spring-akka spring-all @@ -832,7 +833,6 @@ spring-boot-camel spring-boot-client spring-boot-custom-starter - spring-boot-exceptions greeter-spring-boot-autoconfigure greeter-spring-boot-sample-app persistence-modules/spring-boot-h2/spring-boot-h2-database @@ -1271,7 +1271,7 @@ spring-5-reactive-security spring-5-security spring-5-security-oauth - + spring-5-security-cognito spring-activiti spring-akka spring-all @@ -1295,7 +1295,6 @@ spring-boot-ctx-fluent spring-boot-custom-starter spring-boot-disable-console-logging - spring-boot-exceptions spring-boot-jasypt spring-boot-keycloak @@ -1560,5 +1559,6 @@ 3.8 1.16.12 + 1.4.197 diff --git a/ratpack/pom.xml b/ratpack/pom.xml index a4389275b6..7c145eff91 100644 --- a/ratpack/pom.xml +++ b/ratpack/pom.xml @@ -61,7 +61,7 @@ com.h2database h2 - ${h2database.version} + ${h2.version} org.apache.httpcomponents @@ -90,7 +90,6 @@ 1.5.4 4.5.3 4.4.6 - 1.4.193 1.5.12 diff --git a/rule-engines/easy-rules/pom.xml b/rule-engines/easy-rules/pom.xml index 5b88ce4e94..369451c56c 100644 --- a/rule-engines/easy-rules/pom.xml +++ b/rule-engines/easy-rules/pom.xml @@ -10,6 +10,7 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT + ../.. @@ -23,4 +24,4 @@ 3.0.0 - \ No newline at end of file + diff --git a/rule-engines/openl-tablets/pom.xml b/rule-engines/openl-tablets/pom.xml index 3bd6055fc9..b19ec8d3f1 100644 --- a/rule-engines/openl-tablets/pom.xml +++ b/rule-engines/openl-tablets/pom.xml @@ -10,6 +10,7 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT + ../.. @@ -29,4 +30,4 @@ 5.19.4 - \ No newline at end of file + diff --git a/rule-engines/rulebook/pom.xml b/rule-engines/rulebook/pom.xml index 90b5e55417..5e0b900bd9 100644 --- a/rule-engines/rulebook/pom.xml +++ b/rule-engines/rulebook/pom.xml @@ -10,6 +10,7 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT + ../.. @@ -24,4 +25,4 @@ 0.6.2 - \ No newline at end of file + diff --git a/rxjava/pom.xml b/rxjava/pom.xml index 596a5196da..85106d1127 100644 --- a/rxjava/pom.xml +++ b/rxjava/pom.xml @@ -62,7 +62,6 @@ 1.0.0 1.1.1 1.7.0 - 1.4.196 \ No newline at end of file diff --git a/software-security/sql-injection-samples/pom.xml b/software-security/sql-injection-samples/pom.xml index 0a28a96a07..b12b479614 100644 --- a/software-security/sql-injection-samples/pom.xml +++ b/software-security/sql-injection-samples/pom.xml @@ -17,6 +17,7 @@ + org.springframework.boot spring-boot-starter-jdbc @@ -53,6 +54,11 @@ hibernate-jpamodelgen + + + org.springframework.boot + spring-boot-devtools + @@ -64,8 +70,4 @@ - - 1.8 - - \ No newline at end of file diff --git a/spring-4/pom.xml b/spring-4/pom.xml index eb64c1839f..59b74782ec 100644 --- a/spring-4/pom.xml +++ b/spring-4/pom.xml @@ -88,8 +88,6 @@ com.baeldung.flips.ApplicationConfig 1.0.1 - 1.16.18 - 1.4.197 diff --git a/spring-5-reactive-oauth/pom.xml b/spring-5-reactive-oauth/pom.xml index ff076985e4..06ce817a02 100644 --- a/spring-5-reactive-oauth/pom.xml +++ b/spring-5-reactive-oauth/pom.xml @@ -69,7 +69,6 @@ UTF-8 UTF-8 - 1.8 2.1.0.RELEASE diff --git a/spring-5-security-cognito/README.md b/spring-5-security-cognito/README.md new file mode 100644 index 0000000000..0825882c05 --- /dev/null +++ b/spring-5-security-cognito/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Authenticating with Amazon Cognito Using Spring Security](https://www.baeldung.com/spring-security-oauth-cognito) diff --git a/spring-5-security-cognito/pom.xml b/spring-5-security-cognito/pom.xml new file mode 100644 index 0000000000..c7314d6f9f --- /dev/null +++ b/spring-5-security-cognito/pom.xml @@ -0,0 +1,74 @@ + + 4.0.0 + com.baeldung + spring-5-security-cognito + 0.0.1-SNAPSHOT + spring-5-security-cognito + jar + spring 5 security oauth cognito sample project + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity5 + + + + + org.springframework.security.oauth.boot + spring-security-oauth2-autoconfigure + ${oauth-auto.version} + + + org.springframework.security + spring-security-oauth2-client + + + org.springframework.security + spring-security-oauth2-jose + + + + org.springframework + spring-test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + + + 2.1.0.RELEASE + 2.1.0.RELEASE + com.baeldung.cognito.SpringCognitoApplication + + + diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java b/spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java similarity index 91% rename from spring-5-security-oauth/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java rename to spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java index ae03e0a802..6841fa7a65 100644 --- a/spring-5-security-oauth/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java +++ b/spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java @@ -6,7 +6,7 @@ import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration -@PropertySource("cognito/application_cognito.yml") +@PropertySource("cognito/application-cognito.yml") public class CognitoWebConfiguration implements WebMvcConfigurer { @Override diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java b/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java similarity index 88% rename from spring-5-security-oauth/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java rename to spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java index 7f7b751cd9..eebe6d8f45 100644 --- a/spring-5-security-oauth/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java +++ b/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java @@ -5,7 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.PropertySource; @SpringBootApplication -@PropertySource("cognito/application_cognito.yml") +@PropertySource("cognito/application-cognito.yml") public class SpringCognitoApplication { public static void main(String[] args) { diff --git a/spring-5-security-oauth/src/main/resources/cognito/application_cognito.yml b/spring-5-security-cognito/src/main/resources/cognito/application-cognito.yml similarity index 100% rename from spring-5-security-oauth/src/main/resources/cognito/application_cognito.yml rename to spring-5-security-cognito/src/main/resources/cognito/application-cognito.yml diff --git a/spring-5-security-oauth/src/main/resources/cognito/home.html b/spring-5-security-cognito/src/main/resources/cognito/home.html similarity index 100% rename from spring-5-security-oauth/src/main/resources/cognito/home.html rename to spring-5-security-cognito/src/main/resources/cognito/home.html diff --git a/spring-5-security-oauth/src/main/resources/cognito/style.css b/spring-5-security-cognito/src/main/resources/cognito/style.css similarity index 100% rename from spring-5-security-oauth/src/main/resources/cognito/style.css rename to spring-5-security-cognito/src/main/resources/cognito/style.css diff --git a/spring-5-security-cognito/src/main/resources/logback.xml b/spring-5-security-cognito/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-5-security-cognito/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/spring-5-webflux/README.md b/spring-5-webflux/README.md index 4345c8746b..e84ee863bf 100644 --- a/spring-5-webflux/README.md +++ b/spring-5-webflux/README.md @@ -2,4 +2,4 @@ - [Spring Boot Reactor Netty Configuration](https://www.baeldung.com/spring-boot-reactor-netty) - [How to Return 404 with Spring WebFlux](https://www.baeldung.com/spring-webflux-404) -- [WebClient request with parameters](https://www.baeldung.com/webclient-request-with-parameters) +- [Spring WebClient Requests with Parameters](https://www.baeldung.com/webflux-webclient-parameters) diff --git a/spring-activiti/pom.xml b/spring-activiti/pom.xml index 3d67a2ab7b..e0196e807d 100644 --- a/spring-activiti/pom.xml +++ b/spring-activiti/pom.xml @@ -59,7 +59,6 @@ UTF-8 UTF-8 6.0.0 - 1.8 diff --git a/spring-boot-angular-ecommerce/pom.xml b/spring-boot-angular-ecommerce/pom.xml index a5296eade8..510e6c6ec3 100644 --- a/spring-boot-angular-ecommerce/pom.xml +++ b/spring-boot-angular-ecommerce/pom.xml @@ -75,7 +75,6 @@ UTF-8 UTF-8 - 1.8 2.0.3.RELEASE 2.0.4.RELEASE diff --git a/spring-boot-crud/pom.xml b/spring-boot-crud/pom.xml index 73635b0a1c..15ff6c5d11 100644 --- a/spring-boot-crud/pom.xml +++ b/spring-boot-crud/pom.xml @@ -60,7 +60,6 @@ UTF-8 - 1.8 \ No newline at end of file diff --git a/spring-boot-data/README.md b/spring-boot-data/README.md index d93b8c3e93..3fd1d17994 100644 --- a/spring-boot-data/README.md +++ b/spring-boot-data/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Formatting JSON Dates in Spring Boot](https://www.baeldung.com/spring-boot-formatting-json-dates) +- [Rendering Exceptions in JSON with Spring](https://www.baeldung.com/spring-exceptions-json) diff --git a/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/CustomException.java b/spring-boot-data/src/main/java/com/baeldung/jsonexception/CustomException.java similarity index 100% rename from spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/CustomException.java rename to spring-boot-data/src/main/java/com/baeldung/jsonexception/CustomException.java diff --git a/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/ErrorHandler.java b/spring-boot-data/src/main/java/com/baeldung/jsonexception/ErrorHandler.java similarity index 73% rename from spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/ErrorHandler.java rename to spring-boot-data/src/main/java/com/baeldung/jsonexception/ErrorHandler.java index a890dfa3a2..9f82c4fc57 100644 --- a/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/ErrorHandler.java +++ b/spring-boot-data/src/main/java/com/baeldung/jsonexception/ErrorHandler.java @@ -1,13 +1,11 @@ package com.baeldung.jsonexception; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; -@ControllerAdvice -@ResponseBody +@RestControllerAdvice public class ErrorHandler { @ExceptionHandler(CustomException.class) diff --git a/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/MainController.java b/spring-boot-data/src/main/java/com/baeldung/jsonexception/MainController.java similarity index 100% rename from spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/MainController.java rename to spring-boot-data/src/main/java/com/baeldung/jsonexception/MainController.java diff --git a/spring-boot-exceptions/src/test/java/com/baeldung/jsonexception/MainControllerIntegrationTest.java b/spring-boot-data/src/test/java/com/baeldung/jsonexception/MainControllerIntegrationTest.java similarity index 100% rename from spring-boot-exceptions/src/test/java/com/baeldung/jsonexception/MainControllerIntegrationTest.java rename to spring-boot-data/src/test/java/com/baeldung/jsonexception/MainControllerIntegrationTest.java diff --git a/spring-boot-exceptions/README.md b/spring-boot-exceptions/README.md new file mode 100644 index 0000000000..bbc272aec4 --- /dev/null +++ b/spring-boot-exceptions/README.md @@ -0,0 +1,4 @@ + +### Relevant Articles: + +- [Rendering Exceptions in JSON with Spring](https://www.baeldung.com/spring-exceptions-json) diff --git a/spring-boot-exceptions/pom.xml b/spring-boot-exceptions/pom.xml deleted file mode 100644 index 105f60e295..0000000000 --- a/spring-boot-exceptions/pom.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - 4.0.0 - - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../parent-boot-2 - - - com.baeldung - spring-boot-exceptions - 0.0.4-SNAPSHOT - pass-exception-to-client-json-spring-boot - Baeldung article code on how to pass exceptions to client in JSON format using Spring Boot - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-test - test - - - - diff --git a/spring-boot-exceptions/src/main/resources/application.properties b/spring-boot-exceptions/src/main/resources/application.properties deleted file mode 100644 index 8b13789179..0000000000 --- a/spring-boot-exceptions/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/spring-boot-exceptions/src/main/resources/static/.gitignore b/spring-boot-exceptions/src/main/resources/static/.gitignore deleted file mode 100644 index 5e7d2734cf..0000000000 --- a/spring-boot-exceptions/src/main/resources/static/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore diff --git a/spring-boot-exceptions/src/main/resources/templates/.gitignore b/spring-boot-exceptions/src/main/resources/templates/.gitignore deleted file mode 100644 index 5e7d2734cf..0000000000 --- a/spring-boot-exceptions/src/main/resources/templates/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore diff --git a/spring-boot-ops/README.md b/spring-boot-ops/README.md index d5063f14e5..5be5c974d3 100644 --- a/spring-boot-ops/README.md +++ b/spring-boot-ops/README.md @@ -11,4 +11,4 @@ - [Comparing Embedded Servlet Containers in Spring Boot](http://www.baeldung.com/spring-boot-servlet-containers) - [Programmatically Restarting a Spring Boot Application](https://www.baeldung.com/java-restart-spring-boot-app) - [Spring Properties File Outside jar](https://www.baeldung.com/spring-properties-file-outside-jar) - + - [EnvironmentPostProcessor in Spring Boot](https://www.baeldung.com/spring-boot-environmentpostprocessor) diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index b28192cf62..6f365bd465 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -16,3 +16,4 @@ Module for the articles that are part of the Spring REST E-book: - [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring) - [Testing REST with multiple MIME types](http://www.baeldung.com/testing-rest-api-with-multiple-media-types) - [Testing Web APIs with Postman Collections](https://www.baeldung.com/postman-testing-collections) +- [Spring Boot Consuming and Producing JSON](https://www.baeldung.com/spring-boot-json) diff --git a/spring-boot-testing/README.MD b/spring-boot-testing/README.MD index 144c3581f7..99d7db5743 100644 --- a/spring-boot-testing/README.MD +++ b/spring-boot-testing/README.MD @@ -5,3 +5,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Testing with Spring and Spock](https://www.baeldung.com/spring-spock-testing) - [Exclude Auto-Configuration Classes in Spring Boot Tests](https://www.baeldung.com/spring-boot-exclude-auto-configuration-test) +- [Setting the Log Level in Spring Boot when Testing](https://www.baeldung.com/spring-boot-testing-log-level) diff --git a/spring-boot-vue/pom.xml b/spring-boot-vue/pom.xml index 4e47a98d6f..5d19f01d1e 100644 --- a/spring-boot-vue/pom.xml +++ b/spring-boot-vue/pom.xml @@ -47,7 +47,6 @@ UTF-8 UTF-8 - 1.8 diff --git a/spring-boot/README.MD b/spring-boot/README.MD index c0392d38de..d7af3f4614 100644 --- a/spring-boot/README.MD +++ b/spring-boot/README.MD @@ -36,3 +36,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Injecting Git Information Into Spring](https://www.baeldung.com/spring-git-information) - [Validation in Spring Boot](https://www.baeldung.com/spring-boot-bean-validation) - [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar) +- [Entity To DTO Conversion for a Spring REST API](https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application) diff --git a/spring-cloud-data-flow/README.MD b/spring-cloud-data-flow/README.MD index 17d0ec6286..9e5cef19af 100644 --- a/spring-cloud-data-flow/README.MD +++ b/spring-cloud-data-flow/README.MD @@ -1,3 +1,4 @@ ### Relevant Articles: - [Batch Processing with Spring Cloud Data Flow](http://www.baeldung.com/spring-cloud-data-flow-batch-processing) - [Getting Started with Stream Processing with Spring Cloud Data Flow](http://www.baeldung.com/spring-cloud-data-flow-stream-processing) +- [Spring Cloud Data Flow With Apache Spark](https://www.baeldung.com/spring-cloud-data-flow-spark) diff --git a/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml b/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml index 456caf480c..409db34829 100644 --- a/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml +++ b/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml @@ -63,7 +63,6 @@ UTF-8 UTF-8 - 1.8 Greenwich.RELEASE diff --git a/spring-cloud-data-flow/etl/customer-transform/pom.xml b/spring-cloud-data-flow/etl/customer-transform/pom.xml index b7376f7bd4..66f1d5e0d7 100644 --- a/spring-cloud-data-flow/etl/customer-transform/pom.xml +++ b/spring-cloud-data-flow/etl/customer-transform/pom.xml @@ -55,7 +55,6 @@ UTF-8 UTF-8 - 1.8 Greenwich.RELEASE diff --git a/spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer/pom.xml b/spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer/pom.xml index 8ecda40d0a..afd045189c 100644 --- a/spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer/pom.xml +++ b/spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer/pom.xml @@ -50,7 +50,6 @@ UTF-8 UTF-8 - 1.8 1.2.2.RELEASE 1.5.9.RELEASE diff --git a/spring-cloud/spring-cloud-contract/spring-cloud-contract-producer/pom.xml b/spring-cloud/spring-cloud-contract/spring-cloud-contract-producer/pom.xml index 47759a818a..07429687c7 100644 --- a/spring-cloud/spring-cloud-contract/spring-cloud-contract-producer/pom.xml +++ b/spring-cloud/spring-cloud-contract/spring-cloud-contract-producer/pom.xml @@ -64,7 +64,6 @@ UTF-8 UTF-8 - 1.8 Edgware.SR1 1.5.9.RELEASE diff --git a/spring-cloud/spring-cloud-eureka/pom.xml b/spring-cloud/spring-cloud-eureka/pom.xml index 924981765c..e8e3d67805 100644 --- a/spring-cloud/spring-cloud-eureka/pom.xml +++ b/spring-cloud/spring-cloud-eureka/pom.xml @@ -32,8 +32,8 @@ - 2.0.1.RELEASE - Finchley.SR2 + 2.1.2.RELEASE + Greenwich.RELEASE diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml index 85fa6606d2..04a5bd3e58 100644 --- a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml @@ -19,12 +19,10 @@ org.springframework.cloud spring-cloud-starter-netflix-eureka-client - ${spring-cloud-starter-eureka.version} org.springframework.boot spring-boot-starter-web - ${spring-boot.version} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml index 84ba1e28fe..acc436c574 100644 --- a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml @@ -18,23 +18,19 @@ org.springframework.cloud - spring-cloud-starter-feign - ${spring-cloud-starter-feign.version} + spring-cloud-starter-openfeign org.springframework.cloud spring-cloud-starter-netflix-eureka-client - ${spring-cloud-starter-eureka.version} org.springframework.boot spring-boot-starter-web - ${spring-boot.version} org.springframework.boot spring-boot-starter-thymeleaf - ${spring-boot.version} @@ -49,8 +45,4 @@ - - - 1.0.0-SNAPSHOT - diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml index f51f6d229d..95edba29f9 100644 --- a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml @@ -19,7 +19,6 @@ org.springframework.cloud spring-cloud-starter-netflix-eureka-server - ${spring-cloud-starter-eureka.version} diff --git a/spring-cloud/spring-cloud-functions/pom.xml b/spring-cloud/spring-cloud-functions/pom.xml index 4d03e07e89..7a44e4ae0f 100644 --- a/spring-cloud/spring-cloud-functions/pom.xml +++ b/spring-cloud/spring-cloud-functions/pom.xml @@ -85,7 +85,6 @@ UTF-8 UTF-8 - 1.8 1.0.1.RELEASE 2.0.2 2.0.4.RELEASE diff --git a/spring-cloud/spring-cloud-kubernetes/README.md b/spring-cloud/spring-cloud-kubernetes/README.md index 2387758626..32bcbc59b8 100644 --- a/spring-cloud/spring-cloud-kubernetes/README.md +++ b/spring-cloud/spring-cloud-kubernetes/README.md @@ -2,3 +2,4 @@ - [Running Spring Boot Applications With Minikube](https://www.baeldung.com/spring-boot-minikube) - [Self-Healing Applications with Kubernetes and Spring Boot](https://www.baeldung.com/spring-boot-kubernetes-self-healing-apps) +- [Guide to Spring Cloud Kubernetes](https://www.baeldung.com/spring-cloud-kubernetes) diff --git a/spring-cloud/spring-cloud-kubernetes/client-service/pom.xml b/spring-cloud/spring-cloud-kubernetes/client-service/pom.xml index a4de796ee3..41e09fa13b 100644 --- a/spring-cloud/spring-cloud-kubernetes/client-service/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/client-service/pom.xml @@ -88,7 +88,6 @@ - 1.8 Finchley.SR2 1.0.0.RELEASE diff --git a/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml b/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml index 012a81bd8d..293b215918 100644 --- a/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml @@ -44,7 +44,6 @@ UTF-8 UTF-8 - 1.8 1.5.17.RELEASE diff --git a/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml b/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml index 2b2e57a19c..07589e65b6 100644 --- a/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml @@ -44,7 +44,6 @@ UTF-8 UTF-8 - 1.8 1.5.17.RELEASE diff --git a/spring-cloud/spring-cloud-kubernetes/travel-agency-service/pom.xml b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/pom.xml index 19eea2612c..0d7639b179 100755 --- a/spring-cloud/spring-cloud-kubernetes/travel-agency-service/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/pom.xml @@ -68,7 +68,6 @@ - 1.8 Finchley.SR2 diff --git a/spring-cloud/spring-cloud-vault/pom.xml b/spring-cloud/spring-cloud-vault/pom.xml index 3466f657be..9a1be3f5c0 100644 --- a/spring-cloud/spring-cloud-vault/pom.xml +++ b/spring-cloud/spring-cloud-vault/pom.xml @@ -68,7 +68,6 @@ UTF-8 UTF-8 - 1.8 Greenwich.RELEASE diff --git a/spring-cloud/spring-cloud-zuul/pom.xml b/spring-cloud/spring-cloud-zuul/pom.xml index 08990357d6..5d44ae9590 100644 --- a/spring-cloud/spring-cloud-zuul/pom.xml +++ b/spring-cloud/spring-cloud-zuul/pom.xml @@ -70,7 +70,6 @@ UTF-8 UTF-8 - 1.8 Finchley.SR1 2.0.6.RELEASE diff --git a/spring-exceptions/pom.xml b/spring-exceptions/pom.xml index 16f6286606..ff28ac89bb 100644 --- a/spring-exceptions/pom.xml +++ b/spring-exceptions/pom.xml @@ -179,7 +179,6 @@ 4.3.4.RELEASE 4.2.0.RELEASE 3.21.0-GA - 1.2 5.2.5.Final @@ -189,7 +188,6 @@ 5.3.3.Final - 3.1.0 2.2 diff --git a/spring-freemarker/pom.xml b/spring-freemarker/pom.xml index 40558476ef..be34f84495 100644 --- a/spring-freemarker/pom.xml +++ b/spring-freemarker/pom.xml @@ -35,7 +35,7 @@ javax.servlet javax.servlet-api - ${servletapi.version} + ${javax.servlet-api.version} provided @@ -57,7 +57,6 @@ 5.0.8.RELEASE 2.3.28 - 3.1.0 false 1.5.10.RELEASE diff --git a/spring-kafka/pom.xml b/spring-kafka/pom.xml index b76d4f10c0..2fb4c776fe 100644 --- a/spring-kafka/pom.xml +++ b/spring-kafka/pom.xml @@ -34,7 +34,6 @@ 2.2.2.RELEASE - 2.9.7 \ No newline at end of file diff --git a/spring-mvc-forms-jsp/pom.xml b/spring-mvc-forms-jsp/pom.xml index e0539c3216..20912e71e5 100644 --- a/spring-mvc-forms-jsp/pom.xml +++ b/spring-mvc-forms-jsp/pom.xml @@ -100,9 +100,6 @@ 2.6 - 1.2 - 2.3.1 - 3.1.0 6.0.10.Final 1.3.3 5.2.5.Final diff --git a/spring-mvc-simple-2/README.md b/spring-mvc-simple-2/README.md new file mode 100644 index 0000000000..6dfe789be4 --- /dev/null +++ b/spring-mvc-simple-2/README.md @@ -0,0 +1,2 @@ +## Relevant articles: +- [How to Read HTTP Headers in Spring REST Controllers](https://www.baeldung.com/spring-rest-http-headers) diff --git a/spring-mvc-simple/README.md b/spring-mvc-simple/README.md index cd4ad5aba2..755e0932fc 100644 --- a/spring-mvc-simple/README.md +++ b/spring-mvc-simple/README.md @@ -8,4 +8,3 @@ - [Guide to Spring Email](http://www.baeldung.com/spring-email) - [Request Method Not Supported (405) in Spring](https://www.baeldung.com/spring-request-method-not-supported-405) - [Spring @RequestParam Annotation](https://www.baeldung.com/spring-request-param) -- [Validating RequestParams and PathVariables in Spring](https://www.baeldung.com/spring-validate-requestparam-pathvariable) diff --git a/spring-mvc-simple/pom.xml b/spring-mvc-simple/pom.xml index cdd4a9e13a..a767cf3c37 100644 --- a/spring-mvc-simple/pom.xml +++ b/spring-mvc-simple/pom.xml @@ -163,9 +163,7 @@ 1.8 1.8 3.2.0 - 3.7.0 2.21.0 - 1.2 2.3.2-b02 4.0.0 6.0.10.Final @@ -177,7 +175,6 @@ 1.2.5 1.0.2 1.9.0 - 2.9.7 1.4.9 5.1.0 20180130 diff --git a/spring-mvc-velocity/pom.xml b/spring-mvc-velocity/pom.xml index 60ac8b9c2f..df19b67e8e 100644 --- a/spring-mvc-velocity/pom.xml +++ b/spring-mvc-velocity/pom.xml @@ -110,8 +110,6 @@ 4.4.5 4.5.2 - - 3.1.0 1.7 2.0 2.9.0 diff --git a/spring-mvc-webflow/pom.xml b/spring-mvc-webflow/pom.xml index e1a279a787..c8de990da0 100644 --- a/spring-mvc-webflow/pom.xml +++ b/spring-mvc-webflow/pom.xml @@ -90,9 +90,6 @@ 2.5.0.RELEASE - 3.1.0 - 1.2 - 4.4.5 4.5.2 diff --git a/spring-mvc-xml/README.md b/spring-mvc-xml/README.md index 216517f52d..c8ec074d17 100644 --- a/spring-mvc-xml/README.md +++ b/spring-mvc-xml/README.md @@ -15,3 +15,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Exploring SpringMVC’s Form Tag Library](http://www.baeldung.com/spring-mvc-form-tags) - [web.xml vs Initializer with Spring](http://www.baeldung.com/spring-xml-vs-java-config) - [A Java Web Application Without a web.xml](https://www.baeldung.com/java-web-app-without-web-xml) +- [Validating RequestParams and PathVariables in Spring](https://www.baeldung.com/spring-validate-requestparam-pathvariable) \ No newline at end of file diff --git a/spring-mvc-xml/pom.xml b/spring-mvc-xml/pom.xml index beea8e5ee2..46af321d1b 100644 --- a/spring-mvc-xml/pom.xml +++ b/spring-mvc-xml/pom.xml @@ -1,4 +1,5 @@ - 4.0.0 0.1-SNAPSHOT @@ -20,12 +21,6 @@ org.springframework spring-web ${org.springframework.version} - - - commons-logging - commons-logging - - org.springframework @@ -50,7 +45,7 @@ - org.hibernate + org.hibernate.validator hibernate-validator ${hibernate-validator.version} @@ -84,6 +79,11 @@ + + org.glassfish + javax.el + 3.0.1-b08 + org.springframework.boot diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java index 7925fa451d..09c34ccc80 100644 --- a/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java @@ -5,8 +5,10 @@ import java.util.ResourceBundle; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.support.MessageSourceResourceBundle; import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -15,6 +17,7 @@ import org.springframework.web.servlet.view.JstlView; //@EnableWebMvc //@Configuration +@ComponentScan("com.baeldung.spring") public class ClientWebConfigJava implements WebMvcConfigurer { public ClientWebConfigJava() { @@ -51,4 +54,9 @@ public class ClientWebConfigJava implements WebMvcConfigurer { return bean; } + + @Bean + public MethodValidationPostProcessor methodValidationPostProcessor() { + return new MethodValidationPostProcessor(); + } } \ No newline at end of file diff --git a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java index 318a15d8f7..c4332dd879 100644 --- a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java +++ b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java @@ -12,12 +12,13 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import com.baeldung.spring.ClientWebConfig; +import com.baeldung.spring.ClientWebConfigJava; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = ClientWebConfig.class) +@ContextConfiguration(classes = ClientWebConfigJava.class) @WebAppConfiguration public class RequestAndPathVariableValidationControllerIntegrationTest { diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md index e0d3a70626..b7b006d75e 100644 --- a/spring-rest-full/README.md +++ b/spring-rest-full/README.md @@ -9,7 +9,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [Integration Testing with the Maven Cargo plugin](http://www.baeldung.com/integration-testing-with-the-maven-cargo-plugin) -- [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) - [Project Configuration with Spring](http://www.baeldung.com/project-configuration-with-spring) - [Metrics for your Spring REST API](http://www.baeldung.com/spring-rest-api-metrics) - [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic) diff --git a/spring-rest-full/pom.xml b/spring-rest-full/pom.xml index ee6e5dbe3e..a85393b7a8 100644 --- a/spring-rest-full/pom.xml +++ b/spring-rest-full/pom.xml @@ -8,10 +8,10 @@ war - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 @@ -129,6 +129,7 @@ org.javassist javassist + ${javassist.version} mysql @@ -287,6 +288,7 @@ 19.0 3.5 + 3.25.0-GA 1.6.1 diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java b/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java index 059516eeba..ceefbbe0e3 100644 --- a/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java +++ b/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java @@ -17,7 +17,7 @@ public abstract class AbstractService implements IOperat @Override @Transactional(readOnly = true) public T findOne(final long id) { - return getDao().findOne(id); + return getDao().findById(id).orElse(null); } // read - all diff --git a/spring-rest-full/src/main/java/org/baeldung/spring/Application.java b/spring-rest-full/src/main/java/org/baeldung/spring/Application.java index 950e2085a6..ca72a4ef56 100644 --- a/spring-rest-full/src/main/java/org/baeldung/spring/Application.java +++ b/spring-rest-full/src/main/java/org/baeldung/spring/Application.java @@ -7,7 +7,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.context.request.RequestContextListener; diff --git a/spring-rest-full/src/main/java/org/baeldung/spring/WebConfig.java b/spring-rest-full/src/main/java/org/baeldung/spring/WebConfig.java index 86cb93175a..a0db08d93d 100644 --- a/spring-rest-full/src/main/java/org/baeldung/spring/WebConfig.java +++ b/spring-rest-full/src/main/java/org/baeldung/spring/WebConfig.java @@ -6,13 +6,13 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration @ComponentScan("org.baeldung.web") @EnableWebMvc -public class WebConfig extends WebMvcConfigurerAdapter { +public class WebConfig implements WebMvcConfigurer { public WebConfig() { super(); @@ -29,7 +29,6 @@ public class WebConfig extends WebMvcConfigurerAdapter { // API @Override public void addViewControllers(final ViewControllerRegistry registry) { - super.addViewControllers(registry); registry.addViewController("/graph.html"); registry.addViewController("/homepage.html"); } diff --git a/spring-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java b/spring-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java index 89e3a22d45..4dcec17b9e 100644 --- a/spring-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java +++ b/spring-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java @@ -6,16 +6,18 @@ import java.util.Date; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.endpoint.MetricReaderPublicMetrics; -import org.springframework.boot.actuate.metrics.Metric; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; + @Service public class ActuatorMetricService implements IActuatorMetricService { @Autowired - private MetricReaderPublicMetrics publicMetrics; + private MeterRegistry publicMetrics; private final List> statusMetricsByMinute; private final List statusList; @@ -68,7 +70,7 @@ public class ActuatorMetricService implements IActuatorMetricService { private void exportMetrics() { final ArrayList lastMinuteStatuses = initializeStatuses(statusList.size()); - for (final Metric counterMetric : publicMetrics.metrics()) { + for (final Meter counterMetric : publicMetrics.getMeters()) { updateMetrics(counterMetric, lastMinuteStatuses); } @@ -83,17 +85,17 @@ public class ActuatorMetricService implements IActuatorMetricService { return counterList; } - private void updateMetrics(final Metric counterMetric, final ArrayList statusCount) { + private void updateMetrics(final Meter counterMetric, final ArrayList statusCount) { String status = ""; int index = -1; int oldCount = 0; - if (counterMetric.getName().contains("counter.status.")) { - status = counterMetric.getName().substring(15, 18); // example 404, 200 + if (counterMetric.getId().getName().contains("counter.status.")) { + status = counterMetric.getId().getName().substring(15, 18); // example 404, 200 appendStatusIfNotExist(status, statusCount); index = statusList.indexOf(status); oldCount = statusCount.get(index) == null ? 0 : statusCount.get(index); - statusCount.set(index, counterMetric.getValue().intValue() + oldCount); + statusCount.set(index, (int)((Counter) counterMetric).count() + oldCount); } } diff --git a/spring-rest-full/src/main/java/org/baeldung/web/metric/CustomActuatorMetricService.java b/spring-rest-full/src/main/java/org/baeldung/web/metric/CustomActuatorMetricService.java index 852a9fae99..cf30686e52 100644 --- a/spring-rest-full/src/main/java/org/baeldung/web/metric/CustomActuatorMetricService.java +++ b/spring-rest-full/src/main/java/org/baeldung/web/metric/CustomActuatorMetricService.java @@ -6,20 +6,18 @@ import java.util.Date; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.actuate.metrics.CounterService; -import org.springframework.boot.actuate.metrics.Metric; -import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository; -import org.springframework.boot.actuate.metrics.repository.MetricRepository; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.search.Search; + @Service public class CustomActuatorMetricService implements ICustomActuatorMetricService { - private MetricRepository repo; - @Autowired - private CounterService counter; + private MeterRegistry registry; private final List> statusMetricsByMinute; private final List statusList; @@ -27,7 +25,6 @@ public class CustomActuatorMetricService implements ICustomActuatorMetricService public CustomActuatorMetricService() { super(); - repo = new InMemoryMetricRepository(); statusMetricsByMinute = new ArrayList>(); statusList = new ArrayList(); } @@ -36,9 +33,10 @@ public class CustomActuatorMetricService implements ICustomActuatorMetricService @Override public void increaseCount(final int status) { - counter.increment("status." + status); - if (!statusList.contains("counter.status." + status)) { - statusList.add("counter.status." + status); + String counterName = "counter.status." + status; + registry.counter(counterName).increment(1); + if (!statusList.contains(counterName)) { + statusList.add(counterName); } } @@ -78,17 +76,16 @@ public class CustomActuatorMetricService implements ICustomActuatorMetricService @Scheduled(fixedDelay = 60000) private void exportMetrics() { - Metric metric; final ArrayList statusCount = new ArrayList(); for (final String status : statusList) { - metric = repo.findOne(status); - if (metric != null) { - statusCount.add(metric.getValue().intValue()); - repo.reset(status); + Search search = registry.find(status); + if (search != null) { + Counter counter = search.counter(); + statusCount.add(counter != null ? ((int) counter.count()) : 0); + registry.remove(counter); } else { statusCount.add(0); } - } statusMetricsByMinute.add(statusCount); } diff --git a/spring-rest-full/src/main/resources/application.properties b/spring-rest-full/src/main/resources/application.properties index 6c7461f12c..52d93b4cff 100644 --- a/spring-rest-full/src/main/resources/application.properties +++ b/spring-rest-full/src/main/resources/application.properties @@ -1,3 +1,3 @@ server.port=8082 -server.context-path=/spring-rest-full +server.servlet.context-path=/spring-rest-full endpoints.metrics.enabled=true \ No newline at end of file diff --git a/spring-security-cache-control/pom.xml b/spring-security-cache-control/pom.xml index c630774849..e68f92d2ee 100644 --- a/spring-security-cache-control/pom.xml +++ b/spring-security-cache-control/pom.xml @@ -65,8 +65,4 @@ - - 3.1.0 - - \ No newline at end of file diff --git a/spring-security-mvc-boot/pom.xml b/spring-security-mvc-boot/pom.xml index 00d8f032c2..4c25dc01e8 100644 --- a/spring-security-mvc-boot/pom.xml +++ b/spring-security-mvc-boot/pom.xml @@ -234,10 +234,8 @@ 1.1.2 - 1.2 1.6.1 2.6.11 - 1.8 diff --git a/spring-security-mvc-custom/pom.xml b/spring-security-mvc-custom/pom.xml index 7c60a8e18a..4e932f3245 100644 --- a/spring-security-mvc-custom/pom.xml +++ b/spring-security-mvc-custom/pom.xml @@ -94,7 +94,7 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} provided @@ -192,14 +192,9 @@ - - 3.1.0 - 1.2 - 19.0 3.5 - 2.9.7 2.6 diff --git a/spring-security-mvc-digest-auth/pom.xml b/spring-security-mvc-digest-auth/pom.xml index 33b3b5ff31..cf1de1730d 100644 --- a/spring-security-mvc-digest-auth/pom.xml +++ b/spring-security-mvc-digest-auth/pom.xml @@ -94,7 +94,7 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} provided @@ -194,10 +194,6 @@ 4.2.6.RELEASE - - 1.2 - 3.1.0 - 19.0 3.5 diff --git a/spring-security-mvc-login/pom.xml b/spring-security-mvc-login/pom.xml index 048297bbd4..02ed0e36f2 100644 --- a/spring-security-mvc-login/pom.xml +++ b/spring-security-mvc-login/pom.xml @@ -94,7 +94,7 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} provided @@ -174,16 +174,9 @@ - - - - 3.1.0 - 1.2 - 2.6 1.6.1 - \ No newline at end of file diff --git a/spring-security-mvc-persisted-remember-me/pom.xml b/spring-security-mvc-persisted-remember-me/pom.xml index d10565255d..5e987dcb77 100644 --- a/spring-security-mvc-persisted-remember-me/pom.xml +++ b/spring-security-mvc-persisted-remember-me/pom.xml @@ -198,7 +198,6 @@ 4.2.6.RELEASE - 1.4.193 9.4.1212 diff --git a/spring-security-mvc-session/pom.xml b/spring-security-mvc-session/pom.xml index 03c75b99e2..c0e1527a24 100644 --- a/spring-security-mvc-session/pom.xml +++ b/spring-security-mvc-session/pom.xml @@ -94,7 +94,7 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} provided @@ -171,8 +171,6 @@ 3.0.2 - 1.2 - 3.1.0 2.6 diff --git a/spring-security-mvc-socket/README.md b/spring-security-mvc-socket/README.md index 6c2ad7b985..d3f28af387 100644 --- a/spring-security-mvc-socket/README.md +++ b/spring-security-mvc-socket/README.md @@ -8,3 +8,4 @@ To login, use credentials from the data.sql file in src/main/resource, eg: user/ ### Relevant Articles: - [Intro to Security and WebSockets](http://www.baeldung.com/spring-security-websockets) - [Spring WebSockets: Build an User Chat](https://www.baeldung.com/spring-websockets-send-message-to-user) +- [REST vs WebSockets](https://www.baeldung.com/rest-vs-websockets) diff --git a/spring-security-mvc-socket/pom.xml b/spring-security-mvc-socket/pom.xml index b83f10d9fe..f1d28355fd 100644 --- a/spring-security-mvc-socket/pom.xml +++ b/spring-security-mvc-socket/pom.xml @@ -188,7 +188,6 @@ 1.11.3.RELEASE 1.4.196 1.2.3 - 2.9.7 \ No newline at end of file diff --git a/spring-security-react/pom.xml b/spring-security-react/pom.xml index eaf10791bc..c7b7c85be8 100644 --- a/spring-security-react/pom.xml +++ b/spring-security-react/pom.xml @@ -72,7 +72,7 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} provided @@ -167,10 +167,6 @@ 4.3.6.RELEASE 4.2.1.RELEASE - - 3.1.0 - 1.2 - 19.0 3.5 diff --git a/spring-security-rest-basic-auth/pom.xml b/spring-security-rest-basic-auth/pom.xml index 3c7f8eaa2b..8a90247386 100644 --- a/spring-security-rest-basic-auth/pom.xml +++ b/spring-security-rest-basic-auth/pom.xml @@ -142,7 +142,7 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} provided @@ -275,10 +275,6 @@ 4.4.11 4.5.8 - - 1.2 - 3.1.0 - 19.0 diff --git a/spring-security-rest/pom.xml b/spring-security-rest/pom.xml index b6039ce9d3..af38c1ffef 100644 --- a/spring-security-rest/pom.xml +++ b/spring-security-rest/pom.xml @@ -267,10 +267,7 @@ - 3.1.0 1.1.0.Final - 1.2 - 2.9.7 26.0-jre diff --git a/spring-security-sso/README.md b/spring-security-sso/README.md index d0c1b2f7cf..88e3fbb2f7 100644 --- a/spring-security-sso/README.md +++ b/spring-security-sso/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Simple Single Sign-On with Spring Security OAuth2](http://www.baeldung.com/sso-spring-security-oauth2) +- [Spring Security Kerberos Integration](https://www.baeldung.com/spring-security-kerberos-integration) diff --git a/spring-security-sso/spring-security-sso-kerberos/README.md b/spring-security-sso/spring-security-sso-kerberos/README.md new file mode 100644 index 0000000000..0227d9ac70 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/README.md @@ -0,0 +1,4 @@ +## Relevant articles: + +- [Introduction to SPNEGO/Kerberos Authentication in Spring](https://www.baeldung.com/spring-security-kerberos) +- [Spring Security Kerberos Integration](https://www.baeldung.com/spring-security-kerberos-integration) diff --git a/spring-session/spring-session-jdbc/pom.xml b/spring-session/spring-session-jdbc/pom.xml index b46b549ce2..432715bc0e 100644 --- a/spring-session/spring-session-jdbc/pom.xml +++ b/spring-session/spring-session-jdbc/pom.xml @@ -48,8 +48,4 @@ - - 1.4.197 - - \ No newline at end of file diff --git a/spring-static-resources/pom.xml b/spring-static-resources/pom.xml index fc2b3336bc..f01e807919 100644 --- a/spring-static-resources/pom.xml +++ b/spring-static-resources/pom.xml @@ -199,14 +199,10 @@ 1.8.9 2.3.2-b02 - - 2.9.6 - 6.0.10.Final 4.1.0 2.10 - 1.2 4.0.1 1 diff --git a/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml b/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml index 320745b6e5..cfbc90155c 100644 --- a/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml +++ b/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml @@ -158,27 +158,27 @@ com.fasterxml.jackson.core jackson-core - ${jackson-version} + ${jackson.version} com.fasterxml.jackson.core jackson-annotations - ${jackson-version} + ${jackson.version} com.fasterxml.jackson.core jackson-databind - ${jackson-version} + ${jackson.version} com.fasterxml.jackson.jaxrs jackson-jaxrs-json-provider - ${jackson-version} + ${jackson.version} com.fasterxml.jackson.datatype jackson-datatype-joda - ${jackson-version} + ${jackson.version} joda-time @@ -190,7 +190,6 @@ 1.5.15 4.3.9.RELEASE - 2.9.7 2.9.9 2.2 1.5 diff --git a/spring-userservice/pom.xml b/spring-userservice/pom.xml index e562171103..e6e8553c80 100644 --- a/spring-userservice/pom.xml +++ b/spring-userservice/pom.xml @@ -176,7 +176,7 @@ javax.servlet.jsp.jstl jstl-api - ${jstl-api.version} + ${jstl.version} org.springframework.boot @@ -191,7 +191,7 @@ javax.servlet javax.servlet-api - ${javax.servlet.version} + ${javax.servlet-api.version} @@ -225,15 +225,12 @@ 5.2.10.Final 5.1.40 1.10.5.RELEASE - 1.4.193 10.13.1.1 5.3.3.Final 2.2.5 1.1.2 - 1.2 - 3.1.0 19.0 diff --git a/spring-webflux-amqp/pom.xml b/spring-webflux-amqp/pom.xml index a8346458a0..88f5eff403 100755 --- a/spring-webflux-amqp/pom.xml +++ b/spring-webflux-amqp/pom.xml @@ -1,62 +1,76 @@ - 4.0.0 - org.baeldung.spring - spring-webflux-amqp - 1.0.0-SNAPSHOT - spring-webflux-amqp - jar - Spring WebFlux AMQP Sample + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + org.baeldung.spring + spring-webflux-amqp + 1.0.0-SNAPSHOT + spring-webflux-amqp + jar + Spring WebFlux AMQP Sample - - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../parent-boot-2 - + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + - - - org.springframework.boot - spring-boot-starter-amqp - - - org.springframework.boot - spring-boot-starter-webflux - + + + + + org.springframework.boot + spring-boot-dependencies + + 2.1.3.RELEASE + pom + import + + + - - org.springframework.boot - spring-boot-configuration-processor - true - + + + org.springframework.boot + spring-boot-starter-amqp + + + org.springframework.boot + spring-boot-starter-webflux + - - org.springframework.boot - spring-boot-starter-test - test - + + org.springframework.boot + spring-boot-configuration-processor + true + - - io.projectreactor - reactor-test - test - + + org.springframework.boot + spring-boot-starter-test + test + - - org.springframework.boot - spring-boot-starter-integration - - + + io.projectreactor + reactor-test + test + - - - - org.springframework.boot - spring-boot-maven-plugin - - - + + org.springframework.boot + spring-boot-starter-integration + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + diff --git a/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/SpringWebfluxAmqpApplication.java b/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/SpringWebfluxAmqpApplication.java index 30614e7ee6..8a31299333 100755 --- a/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/SpringWebfluxAmqpApplication.java +++ b/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/SpringWebfluxAmqpApplication.java @@ -3,6 +3,12 @@ package org.baeldung.spring.amqp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.web.filter.reactive.HiddenHttpMethodFilter; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilterChain; + +import reactor.core.publisher.Mono; @SpringBootApplication @EnableConfigurationProperties(DestinationsConfig.class) @@ -12,4 +18,19 @@ public class SpringWebfluxAmqpApplication { SpringApplication.run(SpringWebfluxAmqpApplication.class, args); } + + /** + * This is a workaround for https://github.com/spring-projects/spring-framework/issues/21094 + * @return + */ + @Bean + public HiddenHttpMethodFilter hiddenHttpMethodFilter() { + return new HiddenHttpMethodFilter() { + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + return chain.filter(exchange); + } + }; + } + } diff --git a/spring-webflux-amqp/src/main/resources/application.yml b/spring-webflux-amqp/src/main/resources/application.yml index 702aaba357..3f527ce4c5 100755 --- a/spring-webflux-amqp/src/main/resources/application.yml +++ b/spring-webflux-amqp/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: rabbitmq: - host: localhost + host: 192.168.99.100 port: 5672 username: guest password: guest diff --git a/stripe/pom.xml b/stripe/pom.xml index b0cb194bfe..86c6389f7f 100644 --- a/stripe/pom.xml +++ b/stripe/pom.xml @@ -40,7 +40,6 @@ - 1.16.16 4.2.0 diff --git a/struts-2/pom.xml b/struts-2/pom.xml index 7f0fba727d..7de688ff2c 100644 --- a/struts-2/pom.xml +++ b/struts-2/pom.xml @@ -33,7 +33,7 @@ javax.servlet javax.servlet-api - ${servlet.version} + ${javax.servlet-api.version} org.springframework @@ -69,7 +69,6 @@ 2.5.5 2.5.8 - 3.0.1 4.3.6.RELEASE 3.0.0 diff --git a/tensorflow-java/pom.xml b/tensorflow-java/pom.xml index f52cd4a68f..f9abde737c 100644 --- a/tensorflow-java/pom.xml +++ b/tensorflow-java/pom.xml @@ -45,7 +45,6 @@ - 1.8 1.12.0 5.4.0 diff --git a/testing-modules/junit-5-basics/README.md b/testing-modules/junit-5-basics/README.md new file mode 100644 index 0000000000..a00e2a3f4a --- /dev/null +++ b/testing-modules/junit-5-basics/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Get the Path of the /src/test/resources Directory in JUnit](https://www.baeldung.com/junit-src-test-resources-directory-path) diff --git a/testing-modules/junit-5-configuration/pom.xml b/testing-modules/junit-5-basics/pom.xml similarity index 97% rename from testing-modules/junit-5-configuration/pom.xml rename to testing-modules/junit-5-basics/pom.xml index 0f19bc19b7..28afcd6aac 100644 --- a/testing-modules/junit-5-configuration/pom.xml +++ b/testing-modules/junit-5-basics/pom.xml @@ -3,10 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - junit-5-configuration + junit-5-basics 1.0-SNAPSHOT - junit-5-configuration - Intro to JUnit 5 configuration + junit-5-basics + Intro to JUnit 5 com.baeldung diff --git a/testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/Employee.java b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/Employee.java similarity index 100% rename from testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/Employee.java rename to testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/Employee.java diff --git a/testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/EmployeeDAO.java b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeDAO.java similarity index 100% rename from testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/EmployeeDAO.java rename to testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeDAO.java diff --git a/testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/EmployeeRowMapper.java b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeRowMapper.java similarity index 100% rename from testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/EmployeeRowMapper.java rename to testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeRowMapper.java diff --git a/testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/SpringJdbcConfig.java b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/SpringJdbcConfig.java similarity index 100% rename from testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/SpringJdbcConfig.java rename to testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/SpringJdbcConfig.java diff --git a/testing-modules/junit-5-configuration/src/main/resources/jdbc/schema.sql b/testing-modules/junit-5-basics/src/main/resources/jdbc/schema.sql similarity index 100% rename from testing-modules/junit-5-configuration/src/main/resources/jdbc/schema.sql rename to testing-modules/junit-5-basics/src/main/resources/jdbc/schema.sql diff --git a/testing-modules/junit-5-configuration/src/main/resources/jdbc/springJdbc-config.xml b/testing-modules/junit-5-basics/src/main/resources/jdbc/springJdbc-config.xml similarity index 100% rename from testing-modules/junit-5-configuration/src/main/resources/jdbc/springJdbc-config.xml rename to testing-modules/junit-5-basics/src/main/resources/jdbc/springJdbc-config.xml diff --git a/testing-modules/junit-5-configuration/src/main/resources/jdbc/test-data.sql b/testing-modules/junit-5-basics/src/main/resources/jdbc/test-data.sql similarity index 100% rename from testing-modules/junit-5-configuration/src/main/resources/jdbc/test-data.sql rename to testing-modules/junit-5-basics/src/main/resources/jdbc/test-data.sql diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/EmployeeDAOCategoryIntegrationTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOCategoryIntegrationTest.java similarity index 100% rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/EmployeeDAOCategoryIntegrationTest.java rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOCategoryIntegrationTest.java diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/EmployeeDAOUnitTestSuite.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOUnitTestSuite.java similarity index 100% rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/EmployeeDAOUnitTestSuite.java rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOUnitTestSuite.java diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/IntegrationTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/IntegrationTest.java similarity index 100% rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/IntegrationTest.java rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/IntegrationTest.java diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/UnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/UnitTest.java similarity index 100% rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/UnitTest.java rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/UnitTest.java diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/example/EmployeeDAOIntegrationTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeDAOIntegrationTest.java similarity index 100% rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/example/EmployeeDAOIntegrationTest.java rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeDAOIntegrationTest.java diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/example/EmployeeUnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeUnitTest.java similarity index 100% rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/example/EmployeeUnitTest.java rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeUnitTest.java diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/resourcedirectory/ReadResourceDirectoryUnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/resourcedirectory/ReadResourceDirectoryUnitTest.java similarity index 100% rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/resourcedirectory/ReadResourceDirectoryUnitTest.java rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/resourcedirectory/ReadResourceDirectoryUnitTest.java diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/tags/EmployeeDAOIntegrationTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOIntegrationTest.java similarity index 100% rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/tags/EmployeeDAOIntegrationTest.java rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOIntegrationTest.java diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/tags/EmployeeDAOTestSuite.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOTestSuite.java similarity index 100% rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/tags/EmployeeDAOTestSuite.java rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOTestSuite.java diff --git a/testing-modules/junit-5-configuration/src/test/resources/example_resource.txt b/testing-modules/junit-5-basics/src/test/resources/example_resource.txt similarity index 100% rename from testing-modules/junit-5-configuration/src/test/resources/example_resource.txt rename to testing-modules/junit-5-basics/src/test/resources/example_resource.txt diff --git a/testing-modules/junit-5-configuration/README.md b/testing-modules/junit-5-configuration/README.md deleted file mode 100644 index c274391766..0000000000 --- a/testing-modules/junit-5-configuration/README.md +++ /dev/null @@ -1,2 +0,0 @@ -### Relevant Articles: -- diff --git a/testing-modules/junit-5/README.md b/testing-modules/junit-5/README.md index aafdd75e81..47db6587b4 100644 --- a/testing-modules/junit-5/README.md +++ b/testing-modules/junit-5/README.md @@ -6,7 +6,7 @@ - [A Guide to JUnit 5 Extensions](http://www.baeldung.com/junit-5-extensions) - [Inject Parameters into JUnit Jupiter Unit Tests](http://www.baeldung.com/junit-5-parameters) - [Mockito and JUnit 5 – Using ExtendWith](http://www.baeldung.com/mockito-junit-5-extension) -- [JUnit 5 @RunWith](http://www.baeldung.com/junit-5-runwith) +- [JUnit5 @RunWith](http://www.baeldung.com/junit-5-runwith) - [JUnit 5 @Test Annotation](http://www.baeldung.com/junit-5-test-annotation) - [Assert an Exception is Thrown in JUnit 4 and 5](http://www.baeldung.com/junit-assert-exception) - [@Before vs @BeforeClass vs @BeforeEach vs @BeforeAll](http://www.baeldung.com/junit-before-beforeclass-beforeeach-beforeall) diff --git a/testing-modules/junit-5/pom.xml b/testing-modules/junit-5/pom.xml index c1c44791d1..84e0577cfe 100644 --- a/testing-modules/junit-5/pom.xml +++ b/testing-modules/junit-5/pom.xml @@ -138,7 +138,6 @@ 1.4.2 5.4.2 2.8.2 - 1.4.196 2.0.0-RC.1 2.21.0 1.6.0 diff --git a/testing-modules/mockito-2/README.md b/testing-modules/mockito-2/README.md index ee443df81a..5c9e8fc81a 100644 --- a/testing-modules/mockito-2/README.md +++ b/testing-modules/mockito-2/README.md @@ -2,7 +2,4 @@ - [Mockito’s Java 8 Features](http://www.baeldung.com/mockito-2-java-8) - [Lazy Verification with Mockito 2](http://www.baeldung.com/mockito-2-lazy-verification) - -## Mockito 2 and Java 8 Tips - -Examples on how to leverage Java 8 new features with Mockito version 2 +- [Mockito Strict Stubbing and The UnnecessaryStubbingException](https://www.baeldung.com/mockito-unnecessary-stubbing-exception) diff --git a/testing-modules/pom.xml b/testing-modules/pom.xml index 40ed63bc12..90ec857b7f 100644 --- a/testing-modules/pom.xml +++ b/testing-modules/pom.xml @@ -32,6 +32,6 @@ test-containers testing testng - junit-5-configuration + junit-5-basics diff --git a/testing-modules/rest-assured/README.md b/testing-modules/rest-assured/README.md index d44fd08335..ec108353a0 100644 --- a/testing-modules/rest-assured/README.md +++ b/testing-modules/rest-assured/README.md @@ -2,3 +2,4 @@ - [A Guide to REST-assured](http://www.baeldung.com/rest-assured-tutorial) - [REST-assured Support for Spring MockMvc](https://www.baeldung.com/spring-mock-mvc-rest-assured) - [Getting and Verifying Response Data with REST-assured](https://www.baeldung.com/rest-assured-response) +- [REST Assured Authentication](https://www.baeldung.com/rest-assured-authentication) diff --git a/testing-modules/rest-assured/pom.xml b/testing-modules/rest-assured/pom.xml index c528a34e21..4ed10f0641 100644 --- a/testing-modules/rest-assured/pom.xml +++ b/testing-modules/rest-assured/pom.xml @@ -197,8 +197,6 @@ 2.9.7 1.8 19.0 - - 3.1.0 2.5 1.4.7 9.4.0.v20161208 diff --git a/testing-modules/rest-testing/pom.xml b/testing-modules/rest-testing/pom.xml index c3a9477a47..6dad3be117 100644 --- a/testing-modules/rest-testing/pom.xml +++ b/testing-modules/rest-testing/pom.xml @@ -149,9 +149,6 @@ - - 2.9.7 - 19.0 3.5 diff --git a/testing-modules/test-containers/pom.xml b/testing-modules/test-containers/pom.xml index 1f4c483988..7ee002ea8b 100644 --- a/testing-modules/test-containers/pom.xml +++ b/testing-modules/test-containers/pom.xml @@ -103,7 +103,6 @@ 1.0.1 4.12.1 2.8.2 - 1.4.196 2.21.0 5.0.1.RELEASE 1.7.2 diff --git a/vaadin/pom.xml b/vaadin/pom.xml index ec69e240e2..648343fcd8 100644 --- a/vaadin/pom.xml +++ b/vaadin/pom.xml @@ -155,7 +155,6 @@ - 3.0.1 10.0.11 10.0.11 10.0.11 diff --git a/vavr/pom.xml b/vavr/pom.xml index ae495e9830..a2c6e29cde 100644 --- a/vavr/pom.xml +++ b/vavr/pom.xml @@ -41,7 +41,6 @@ - 1.8 0.9.1 3.0.0 diff --git a/video-tutorials/jackson-annotations/pom.xml b/video-tutorials/jackson-annotations/pom.xml index b0e1c7e8d9..2492951d1a 100644 --- a/video-tutorials/jackson-annotations/pom.xml +++ b/video-tutorials/jackson-annotations/pom.xml @@ -136,10 +136,6 @@ - - - 2.9.7 - 2.9.6 2.8.0 diff --git a/vraptor/pom.xml b/vraptor/pom.xml index 214a44cede..3904eb8c63 100644 --- a/vraptor/pom.xml +++ b/vraptor/pom.xml @@ -67,7 +67,7 @@ javax.servlet javax.servlet-api - ${servlet.version} + ${javax.servlet-api.version} provided @@ -129,8 +129,6 @@ 2.1.2.Final 2.2 5.1.1.Final - 1.2 - 3.1.0 1.7.5 4.1.0-RC3 4.0.4