From e3bada67dd6bcabcdeb4c61304360aa78054abf7 Mon Sep 17 00:00:00 2001 From: Philippe Date: Thu, 24 Jan 2019 23:35:44 -0200 Subject: [PATCH 01/31] BAEL-1381 --- sql-injection-samples/.gitignore | 25 +++ sql-injection-samples/pom.xml | 61 +++++++ .../examples/security/sql/AccountDAO.java | 169 ++++++++++++++++++ .../examples/security/sql/AccountDTO.java | 16 ++ .../sql/SqlInjectionSamplesApplication.java | 14 ++ .../src/main/resources/application.properties | 0 .../resources/db/changelog/create-tables.xml | 19 ++ .../main/resources/db/master-changelog.xml | 8 + ...qlInjectionSamplesApplicationUnitTest.java | 60 +++++++ .../src/test/resources/application-test.yml | 6 + .../src/test/resources/data.sql | 4 + .../src/test/resources/schema.sql | 6 + 12 files changed, 388 insertions(+) create mode 100644 sql-injection-samples/.gitignore create mode 100644 sql-injection-samples/pom.xml create mode 100644 sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java create mode 100644 sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java create mode 100644 sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java create mode 100644 sql-injection-samples/src/main/resources/application.properties create mode 100644 sql-injection-samples/src/main/resources/db/changelog/create-tables.xml create mode 100644 sql-injection-samples/src/main/resources/db/master-changelog.xml create mode 100644 sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java create mode 100644 sql-injection-samples/src/test/resources/application-test.yml create mode 100644 sql-injection-samples/src/test/resources/data.sql create mode 100644 sql-injection-samples/src/test/resources/schema.sql diff --git a/sql-injection-samples/.gitignore b/sql-injection-samples/.gitignore new file mode 100644 index 0000000000..82eca336e3 --- /dev/null +++ b/sql-injection-samples/.gitignore @@ -0,0 +1,25 @@ +/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/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ \ No newline at end of file diff --git a/sql-injection-samples/pom.xml b/sql-injection-samples/pom.xml new file mode 100644 index 0000000000..b6390ad387 --- /dev/null +++ b/sql-injection-samples/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + com.baeldung + sql-injection-samples + 0.0.1-SNAPSHOT + sql-injection-samples + Sample SQL Injection tests + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-jdbc + + + + org.apache.derby + derby + runtime + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.projectlombok + lombok + provided + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java b/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java new file mode 100644 index 0000000000..447dcc456d --- /dev/null +++ b/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java @@ -0,0 +1,169 @@ +/** + * + */ +package com.baeldung.examples.security.sql; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.sql.DataSource; + +import org.springframework.stereotype.Component; + +/** + * @author Philippe + * + */ +@Component +public class AccountDAO { + + private final DataSource dataSource; + + public AccountDAO(DataSource dataSource) { + this.dataSource = dataSource; + } + + /** + * Return all accounts owned by a given customer,given his/her external id + * + * @param customerId + * @return + */ + public List unsafeFindAccountsByCustomerId(String customerId) { + + String sql = "select " + "customer_id,acc_number,branch_id,balance from Accounts where customer_id = '" + customerId + "'"; + + try (Connection c = dataSource.getConnection(); + ResultSet rs = c.createStatement() + .executeQuery(sql)) { + List accounts = new ArrayList<>(); + while (rs.next()) { + AccountDTO acc = AccountDTO.builder() + .customerId(rs.getString("customer_id")) + .branchId(rs.getString("branch_id")) + .accNumber(rs.getString("acc_number")) + .balance(rs.getBigDecimal("balance")) + .build(); + + accounts.add(acc); + } + + return accounts; + } catch (SQLException ex) { + throw new RuntimeException(ex); + } + } + + /** + * Return all accounts owned by a given customer,given his/her external id + * + * @param customerId + * @return + */ + public List safeFindAccountsByCustomerId(String customerId) { + + String sql = "select " + "customer_id,acc_number,branch_id,balance from Accounts where customer_id = ?"; + + try (Connection c = dataSource.getConnection(); PreparedStatement p = c.prepareStatement(sql)) { + p.setString(1, customerId); + ResultSet rs = p.executeQuery(); + List accounts = new ArrayList<>(); + while (rs.next()) { + AccountDTO acc = AccountDTO.builder() + .customerId(rs.getString("customerId")) + .branchId(rs.getString("branch_id")) + .accNumber(rs.getString("acc_number")) + .balance(rs.getBigDecimal("balance")) + .build(); + + accounts.add(acc); + } + return accounts; + } catch (SQLException ex) { + throw new RuntimeException(ex); + } + } + + private static final Set VALID_COLUMNS_FOR_ORDER_BY = Stream.of("acc_number", "branch_id", "balance") + .collect(Collectors.toCollection(HashSet::new)); + + /** + * Return all accounts owned by a given customer,given his/her external id + * + * @param customerId + * @return + */ + public List safeFindAccountsByCustomerId(String customerId, String orderBy) { + + String sql = "select " + "customer_id,acc_number,branch_id,balance from Accounts where customer_id = ? "; + + if (VALID_COLUMNS_FOR_ORDER_BY.contains(orderBy)) { + sql = sql + " order by " + orderBy; + } + else { + throw new IllegalArgumentException("Nice try!"); + } + + try (Connection c = dataSource.getConnection(); PreparedStatement p = c.prepareStatement(sql)) { + + p.setString(1, customerId); + ResultSet rs = p.executeQuery(); + List accounts = new ArrayList<>(); + while (rs.next()) { + AccountDTO acc = AccountDTO.builder() + .customerId(rs.getString("customerId")) + .branchId(rs.getString("branch_id")) + .accNumber(rs.getString("acc_number")) + .balance(rs.getBigDecimal("balance")) + .build(); + + accounts.add(acc); + } + + return accounts; + } catch (SQLException ex) { + throw new RuntimeException(ex); + } + } + + /** + * Invalid placeholder usage example + * + * @param tableName + * @return + */ + public List wrongCountRecordsByTableName(String tableName) { + + try (Connection c = dataSource.getConnection(); + PreparedStatement p = c.prepareStatement("select count(*) from ?")) { + + p.setString(1, tableName); + ResultSet rs = p.executeQuery(); + List accounts = new ArrayList<>(); + while (rs.next()) { + AccountDTO acc = AccountDTO.builder() + .customerId(rs.getString("customerId")) + .branchId(rs.getString("branch_id")) + .accNumber(rs.getString("acc_number")) + .balance(rs.getBigDecimal("balance")) + .build(); + + accounts.add(acc); + } + + return accounts; + } catch (SQLException ex) { + throw new RuntimeException(ex); + } + } + +} diff --git a/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java b/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java new file mode 100644 index 0000000000..2e6fa04af4 --- /dev/null +++ b/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java @@ -0,0 +1,16 @@ +package com.baeldung.examples.security.sql; + +import java.math.BigDecimal; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class AccountDTO { + + private String customerId; + private String accNumber; + private String branchId; + private BigDecimal balance; +} diff --git a/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java b/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java new file mode 100644 index 0000000000..c1083ae3de --- /dev/null +++ b/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.examples.security.sql; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SqlInjectionSamplesApplication { + + public static void main(String[] args) { + SpringApplication.run(SqlInjectionSamplesApplication.class, args); + } + +} + diff --git a/sql-injection-samples/src/main/resources/application.properties b/sql-injection-samples/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml b/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml new file mode 100644 index 0000000000..a405c02049 --- /dev/null +++ b/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sql-injection-samples/src/main/resources/db/master-changelog.xml b/sql-injection-samples/src/main/resources/db/master-changelog.xml new file mode 100644 index 0000000000..047ca2b314 --- /dev/null +++ b/sql-injection-samples/src/main/resources/db/master-changelog.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java b/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java new file mode 100644 index 0000000000..1f37ba04b6 --- /dev/null +++ b/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java @@ -0,0 +1,60 @@ +package com.baeldung.examples.security.sql; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +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.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.examples.security.sql.AccountDAO; +import com.baeldung.examples.security.sql.AccountDTO; + +@RunWith(SpringRunner.class) +@SpringBootTest +@ActiveProfiles({ "test" }) +public class SqlInjectionSamplesApplicationUnitTest { + + @Autowired + private AccountDAO target; + + @Test + public void givenAVulnerableMethod_whenValidCustomerId_thenReturnSingleAccount() { + + List accounts = target.unsafeFindAccountsByCustomerId("C1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isNotEmpty(); + assertThat(accounts).hasSize(1); + } + + @Test + public void givenAVulnerableMethod_whenHackedCustomerId_thenReturnAllAccounts() { + + List accounts = target.unsafeFindAccountsByCustomerId("C1' or '1'='1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isNotEmpty(); + assertThat(accounts).hasSize(3); + } + + @Test + public void givenASafeMethod_whenHackedCustomerId_thenReturnNoAccounts() { + + List accounts = target.safeFindAccountsByCustomerId("C1' or '1'='1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isEmpty(); + } + + @Test(expected = IllegalArgumentException.class) + public void givenASafeMethod_whenInvalidOrderBy_thenThroweException() { + target.safeFindAccountsByCustomerId("C1", "INVALID"); + } + + @Test(expected = RuntimeException.class) + public void givenWrongPlaceholderUsageMethod_whenNormalCall_thenThrowsException() { + target.wrongCountRecordsByTableName("Accounts"); + } +} diff --git a/sql-injection-samples/src/test/resources/application-test.yml b/sql-injection-samples/src/test/resources/application-test.yml new file mode 100644 index 0000000000..d07ee10aee --- /dev/null +++ b/sql-injection-samples/src/test/resources/application-test.yml @@ -0,0 +1,6 @@ +# +# Test profile configuration +# +spring: + datasource: + initialization-mode: always diff --git a/sql-injection-samples/src/test/resources/data.sql b/sql-injection-samples/src/test/resources/data.sql new file mode 100644 index 0000000000..586618a07f --- /dev/null +++ b/sql-injection-samples/src/test/resources/data.sql @@ -0,0 +1,4 @@ +insert into Accounts(customer_id,acc_number,branch_id,balance) values ('C1','0001',1,1000.00); +insert into Accounts(customer_id,acc_number,branch_id,balance) values ('C2','0002',1,500.00); +insert into Accounts(customer_id,acc_number,branch_id,balance) values ('C3','0003',1,501.00); + diff --git a/sql-injection-samples/src/test/resources/schema.sql b/sql-injection-samples/src/test/resources/schema.sql new file mode 100644 index 0000000000..bfb0ae8059 --- /dev/null +++ b/sql-injection-samples/src/test/resources/schema.sql @@ -0,0 +1,6 @@ +create table Accounts ( + customer_id varchar(16) not null, + acc_number varchar(16) not null, + branch_id decimal(8,0), + balance decimal(16,4) +); From 43d429e4151d5cf62ba7ce7ae69b13bb415be698 Mon Sep 17 00:00:00 2001 From: Philippe Date: Thu, 24 Jan 2019 23:48:22 -0200 Subject: [PATCH 02/31] [BAEL-1381] --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d084d0f7af..9306a1db2e 100644 --- a/pom.xml +++ b/pom.xml @@ -567,7 +567,8 @@ rule-engines/rulebook rsocket rxjava - rxjava-2 + rxjava-2 + sql-injection-samples From bc267aec07a0de7a79a7484cb60343f7a8067da3 Mon Sep 17 00:00:00 2001 From: Philippe Date: Tue, 29 Jan 2019 21:34:30 -0200 Subject: [PATCH 03/31] [BAEL-1381] New module name --- pom.xml | 2 +- .../sql-injection-samples}/.gitignore | 0 .../sql-injection-samples}/pom.xml | 2 +- .../java/com/baeldung/examples/security/sql/AccountDAO.java | 0 .../java/com/baeldung/examples/security/sql/AccountDTO.java | 0 .../examples/security/sql/SqlInjectionSamplesApplication.java | 0 .../src/main/resources/application.properties | 0 .../src/main/resources/db/changelog/create-tables.xml | 0 .../src/main/resources/db/master-changelog.xml | 0 .../security/sql/SqlInjectionSamplesApplicationUnitTest.java | 0 .../src/test/resources/application-test.yml | 0 .../sql-injection-samples}/src/test/resources/data.sql | 0 .../sql-injection-samples}/src/test/resources/schema.sql | 0 13 files changed, 2 insertions(+), 2 deletions(-) rename {sql-injection-samples => software-security/sql-injection-samples}/.gitignore (100%) rename {sql-injection-samples => software-security/sql-injection-samples}/pom.xml (96%) rename {sql-injection-samples => software-security/sql-injection-samples}/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java (100%) rename {sql-injection-samples => software-security/sql-injection-samples}/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java (100%) rename {sql-injection-samples => software-security/sql-injection-samples}/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java (100%) rename {sql-injection-samples => software-security/sql-injection-samples}/src/main/resources/application.properties (100%) rename {sql-injection-samples => software-security/sql-injection-samples}/src/main/resources/db/changelog/create-tables.xml (100%) rename {sql-injection-samples => software-security/sql-injection-samples}/src/main/resources/db/master-changelog.xml (100%) rename {sql-injection-samples => software-security/sql-injection-samples}/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java (100%) rename {sql-injection-samples => software-security/sql-injection-samples}/src/test/resources/application-test.yml (100%) rename {sql-injection-samples => software-security/sql-injection-samples}/src/test/resources/data.sql (100%) rename {sql-injection-samples => software-security/sql-injection-samples}/src/test/resources/schema.sql (100%) diff --git a/pom.xml b/pom.xml index 68a4a1f7ad..30d5e2ade8 100644 --- a/pom.xml +++ b/pom.xml @@ -568,7 +568,7 @@ rsocket rxjava rxjava-2 - sql-injection-samples + software-security diff --git a/sql-injection-samples/.gitignore b/software-security/sql-injection-samples/.gitignore similarity index 100% rename from sql-injection-samples/.gitignore rename to software-security/sql-injection-samples/.gitignore diff --git a/sql-injection-samples/pom.xml b/software-security/sql-injection-samples/pom.xml similarity index 96% rename from sql-injection-samples/pom.xml rename to software-security/sql-injection-samples/pom.xml index b6390ad387..d5e64db6b3 100644 --- a/sql-injection-samples/pom.xml +++ b/software-security/sql-injection-samples/pom.xml @@ -7,7 +7,7 @@ parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 com.baeldung diff --git a/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java similarity index 100% rename from sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java rename to software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java diff --git a/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java similarity index 100% rename from sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java rename to software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java diff --git a/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java similarity index 100% rename from sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java rename to software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java diff --git a/sql-injection-samples/src/main/resources/application.properties b/software-security/sql-injection-samples/src/main/resources/application.properties similarity index 100% rename from sql-injection-samples/src/main/resources/application.properties rename to software-security/sql-injection-samples/src/main/resources/application.properties diff --git a/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml b/software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml similarity index 100% rename from sql-injection-samples/src/main/resources/db/changelog/create-tables.xml rename to software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml diff --git a/sql-injection-samples/src/main/resources/db/master-changelog.xml b/software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml similarity index 100% rename from sql-injection-samples/src/main/resources/db/master-changelog.xml rename to software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml diff --git a/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java b/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java similarity index 100% rename from sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java rename to software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java diff --git a/sql-injection-samples/src/test/resources/application-test.yml b/software-security/sql-injection-samples/src/test/resources/application-test.yml similarity index 100% rename from sql-injection-samples/src/test/resources/application-test.yml rename to software-security/sql-injection-samples/src/test/resources/application-test.yml diff --git a/sql-injection-samples/src/test/resources/data.sql b/software-security/sql-injection-samples/src/test/resources/data.sql similarity index 100% rename from sql-injection-samples/src/test/resources/data.sql rename to software-security/sql-injection-samples/src/test/resources/data.sql diff --git a/sql-injection-samples/src/test/resources/schema.sql b/software-security/sql-injection-samples/src/test/resources/schema.sql similarity index 100% rename from sql-injection-samples/src/test/resources/schema.sql rename to software-security/sql-injection-samples/src/test/resources/schema.sql From 35b89e5cbcd54032f7c80dca83fcca7b011a0cc9 Mon Sep 17 00:00:00 2001 From: Philippe Date: Tue, 29 Jan 2019 22:06:02 -0200 Subject: [PATCH 04/31] [BAEL-1381] software-security module --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 30d5e2ade8..787a03c2fb 100644 --- a/pom.xml +++ b/pom.xml @@ -568,7 +568,7 @@ rsocket rxjava rxjava-2 - software-security + software-security/sql-injection-samples From 9f61a81114fa31132c4764c22ae11f3bc4f51171 Mon Sep 17 00:00:00 2001 From: Philippe Date: Sun, 17 Feb 2019 20:56:09 -0300 Subject: [PATCH 05/31] [BAEL-1381] Add JPA examples --- .../CustomBaeldungQueueUnitTest.java | 0 .../PriorityQueueUnitTest.java | 0 .../sql-injection-samples/pom.xml | 13 ++ .../examples/security/sql/Account.java | 34 ++++ .../examples/security/sql/AccountDAO.java | 171 +++++++++++++++--- .../src/main/resources/application.properties | 1 + .../resources/db/changelog/create-tables.xml | 19 -- .../main/resources/db/master-changelog.xml | 8 - ...qlInjectionSamplesApplicationUnitTest.java | 34 +++- .../src/test/resources/application-test.yml | 14 +- .../src/test/resources/schema.sql | 1 + 11 files changed, 245 insertions(+), 50 deletions(-) rename core-java-collections/src/test/java/com/baeldung/{queueinterface => queueInterface}/CustomBaeldungQueueUnitTest.java (100%) rename core-java-collections/src/test/java/com/baeldung/{queueinterface => queueInterface}/PriorityQueueUnitTest.java (100%) create mode 100644 software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/Account.java delete mode 100644 software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml delete mode 100644 software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml diff --git a/core-java-collections/src/test/java/com/baeldung/queueinterface/CustomBaeldungQueueUnitTest.java b/core-java-collections/src/test/java/com/baeldung/queueInterface/CustomBaeldungQueueUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/queueinterface/CustomBaeldungQueueUnitTest.java rename to core-java-collections/src/test/java/com/baeldung/queueInterface/CustomBaeldungQueueUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/queueinterface/PriorityQueueUnitTest.java b/core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/queueinterface/PriorityQueueUnitTest.java rename to core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java diff --git a/software-security/sql-injection-samples/pom.xml b/software-security/sql-injection-samples/pom.xml index e4510d9ef8..5b33c674d4 100644 --- a/software-security/sql-injection-samples/pom.xml +++ b/software-security/sql-injection-samples/pom.xml @@ -16,6 +16,8 @@ + + org.springframework.boot spring-boot-starter-jdbc @@ -42,6 +44,17 @@ provided + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.hibernate + hibernate-jpamodelgen + + + diff --git a/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/Account.java b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/Account.java new file mode 100644 index 0000000000..3f077d5592 --- /dev/null +++ b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/Account.java @@ -0,0 +1,34 @@ +/** + * + */ +package com.baeldung.examples.security.sql; + +import java.math.BigDecimal; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import lombok.Data; + +/** + * @author Philippe + * + */ +@Entity +@Table(name="Accounts") +@Data +public class Account { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + private Long id; + + private String customerId; + private String accNumber; + private String branchId; + private BigDecimal balance; + +} diff --git a/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java index 447dcc456d..c7285e5fd3 100644 --- a/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java +++ b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java @@ -7,14 +7,24 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.persistence.EntityManager; +import javax.persistence.Query; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Order; +import javax.persistence.criteria.Root; +import javax.persistence.metamodel.SingularAttribute; import javax.sql.DataSource; import org.springframework.stereotype.Component; @@ -27,9 +37,11 @@ import org.springframework.stereotype.Component; public class AccountDAO { private final DataSource dataSource; + private final EntityManager em; - public AccountDAO(DataSource dataSource) { + public AccountDAO(DataSource dataSource, EntityManager em) { this.dataSource = dataSource; + this.em = em; } /** @@ -63,6 +75,26 @@ public class AccountDAO { } } + /** + * Return all accounts owned by a given customer,given his/her external id - JPA version + * + * @param customerId + * @return + */ + public List unsafeJpaFindAccountsByCustomerId(String customerId) { + String jql = "from Account where customerId = '" + customerId + "'"; + TypedQuery q = em.createQuery(jql, Account.class); + return q.getResultList() + .stream() + .map(a -> AccountDTO.builder() + .accNumber(a.getAccNumber()) + .balance(a.getBalance()) + .branchId(a.getAccNumber()) + .customerId(a.getCustomerId()) + .build()) + .collect(Collectors.toList()); + } + /** * Return all accounts owned by a given customer,given his/her external id * @@ -71,7 +103,7 @@ public class AccountDAO { */ public List safeFindAccountsByCustomerId(String customerId) { - String sql = "select " + "customer_id,acc_number,branch_id,balance from Accounts where customer_id = ?"; + String sql = "select customer_id, branch_id,acc_number,balance from Accounts where customer_id = ?"; try (Connection c = dataSource.getConnection(); PreparedStatement p = c.prepareStatement(sql)) { p.setString(1, customerId); @@ -93,23 +125,73 @@ public class AccountDAO { } } + /** + * Return all accounts owned by a given customer,given his/her external id - JPA version + * + * @param customerId + * @return + */ + public List safeJpaFindAccountsByCustomerId(String customerId) { + + String jql = "from Account where customerId = :customerId"; + TypedQuery q = em.createQuery(jql, Account.class) + .setParameter("customerId", customerId); + + return q.getResultList() + .stream() + .map(a -> AccountDTO.builder() + .accNumber(a.getAccNumber()) + .balance(a.getBalance()) + .branchId(a.getAccNumber()) + .customerId(a.getCustomerId()) + .build()) + .collect(Collectors.toList()); + } + + /** + * Return all accounts owned by a given customer,given his/her external id - JPA version + * + * @param customerId + * @return + */ + public List safeJpaCriteriaFindAccountsByCustomerId(String customerId) { + + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(Account.class); + Root root = cq.from(Account.class); + cq.select(root) + .where(cb.equal(root.get(Account_.customerId), customerId)); + + TypedQuery q = em.createQuery(cq); + + return q.getResultList() + .stream() + .map(a -> AccountDTO.builder() + .accNumber(a.getAccNumber()) + .balance(a.getBalance()) + .branchId(a.getAccNumber()) + .customerId(a.getCustomerId()) + .build()) + .collect(Collectors.toList()); + } + private static final Set VALID_COLUMNS_FOR_ORDER_BY = Stream.of("acc_number", "branch_id", "balance") .collect(Collectors.toCollection(HashSet::new)); + /** * Return all accounts owned by a given customer,given his/her external id * * @param customerId * @return */ - public List safeFindAccountsByCustomerId(String customerId, String orderBy) { + public List safeFindAccountsByCustomerId(String customerId, String orderBy) { String sql = "select " + "customer_id,acc_number,branch_id,balance from Accounts where customer_id = ? "; if (VALID_COLUMNS_FOR_ORDER_BY.contains(orderBy)) { sql = sql + " order by " + orderBy; - } - else { + } else { throw new IllegalArgumentException("Nice try!"); } @@ -135,35 +217,82 @@ public class AccountDAO { } } + + private static final Map> VALID_JPA_COLUMNS_FOR_ORDER_BY = Stream.of( + new AbstractMap.SimpleEntry<>(Account_.ACC_NUMBER, Account_.accNumber), + new AbstractMap.SimpleEntry<>(Account_.BRANCH_ID, Account_.branchId), + new AbstractMap.SimpleEntry<>(Account_.BALANCE, Account_.balance) + ) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + /** + * Return all accounts owned by a given customer,given his/her external id + * + * @param customerId + * @return + */ + public List safeJpaFindAccountsByCustomerId(String customerId, String orderBy) { + +SingularAttribute orderByAttribute = VALID_JPA_COLUMNS_FOR_ORDER_BY.get(orderBy); +if ( orderByAttribute == null) { + throw new IllegalArgumentException("Nice try!"); +} + +CriteriaBuilder cb = em.getCriteriaBuilder(); +CriteriaQuery cq = cb.createQuery(Account.class); +Root root = cq.from(Account.class); +cq.select(root) + .where(cb.equal(root.get(Account_.customerId), customerId)) + .orderBy(cb.asc(root.get(orderByAttribute))); + +TypedQuery q = em.createQuery(cq); + + return q.getResultList() + .stream() + .map(a -> AccountDTO.builder() + .accNumber(a.getAccNumber()) + .balance(a.getBalance()) + .branchId(a.getAccNumber()) + .customerId(a.getCustomerId()) + .build()) + .collect(Collectors.toList()); + + } + /** * Invalid placeholder usage example * * @param tableName * @return */ - public List wrongCountRecordsByTableName(String tableName) { + public Long wrongCountRecordsByTableName(String tableName) { + + try (Connection c = dataSource.getConnection(); PreparedStatement p = c.prepareStatement("select count(*) from ?")) { - try (Connection c = dataSource.getConnection(); - PreparedStatement p = c.prepareStatement("select count(*) from ?")) { - p.setString(1, tableName); ResultSet rs = p.executeQuery(); - List accounts = new ArrayList<>(); - while (rs.next()) { - AccountDTO acc = AccountDTO.builder() - .customerId(rs.getString("customerId")) - .branchId(rs.getString("branch_id")) - .accNumber(rs.getString("acc_number")) - .balance(rs.getBigDecimal("balance")) - .build(); + rs.next(); + return rs.getLong(1); - accounts.add(acc); - } - - return accounts; } catch (SQLException ex) { throw new RuntimeException(ex); } } + /** + * Invalid placeholder usage example - JPA + * + * @param tableName + * @return + */ + public Long wrongJpaCountRecordsByTableName(String tableName) { + + String jql = "select count(*) from :tableName"; + TypedQuery q = em.createQuery(jql, Long.class) + .setParameter("tableName", tableName); + + return q.getSingleResult(); + + } + } diff --git a/software-security/sql-injection-samples/src/main/resources/application.properties b/software-security/sql-injection-samples/src/main/resources/application.properties index e69de29bb2..8b13789179 100644 --- a/software-security/sql-injection-samples/src/main/resources/application.properties +++ b/software-security/sql-injection-samples/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml b/software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml deleted file mode 100644 index a405c02049..0000000000 --- a/software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml b/software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml deleted file mode 100644 index 047ca2b314..0000000000 --- a/software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java b/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java index 1f37ba04b6..f61b738abc 100644 --- a/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java +++ b/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java @@ -40,6 +40,15 @@ public class SqlInjectionSamplesApplicationUnitTest { assertThat(accounts).hasSize(3); } + @Test + public void givenAVulnerableJpaMethod_whenHackedCustomerId_thenReturnAllAccounts() { + + List accounts = target.unsafeJpaFindAccountsByCustomerId("C1' or '1'='1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isNotEmpty(); + assertThat(accounts).hasSize(3); + } + @Test public void givenASafeMethod_whenHackedCustomerId_thenReturnNoAccounts() { @@ -48,13 +57,36 @@ public class SqlInjectionSamplesApplicationUnitTest { assertThat(accounts).isEmpty(); } + @Test + public void givenASafeJpaMethod_whenHackedCustomerId_thenReturnNoAccounts() { + + List accounts = target.safeJpaFindAccountsByCustomerId("C1' or '1'='1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isEmpty(); + } + + + @Test + public void givenASafeJpaCriteriaMethod_whenHackedCustomerId_thenReturnNoAccounts() { + + List accounts = target.safeJpaCriteriaFindAccountsByCustomerId("C1' or '1'='1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isEmpty(); + } + @Test(expected = IllegalArgumentException.class) public void givenASafeMethod_whenInvalidOrderBy_thenThroweException() { target.safeFindAccountsByCustomerId("C1", "INVALID"); } - @Test(expected = RuntimeException.class) + @Test(expected = Exception.class) public void givenWrongPlaceholderUsageMethod_whenNormalCall_thenThrowsException() { target.wrongCountRecordsByTableName("Accounts"); } + + @Test(expected = Exception.class) + public void givenWrongJpaPlaceholderUsageMethod_whenNormalCall_thenThrowsException() { + target.wrongJpaCountRecordsByTableName("Accounts"); + } + } diff --git a/software-security/sql-injection-samples/src/test/resources/application-test.yml b/software-security/sql-injection-samples/src/test/resources/application-test.yml index d07ee10aee..3af3f58bff 100644 --- a/software-security/sql-injection-samples/src/test/resources/application-test.yml +++ b/software-security/sql-injection-samples/src/test/resources/application-test.yml @@ -2,5 +2,17 @@ # Test profile configuration # spring: + liquibase: + change-log: db/changelog/db.changelog-master.xml + + jpa: + hibernate: + ddl-auto: none + datasource: - initialization-mode: always + initialization-mode: embedded + +logging: + level: + sql: DEBUG + \ No newline at end of file diff --git a/software-security/sql-injection-samples/src/test/resources/schema.sql b/software-security/sql-injection-samples/src/test/resources/schema.sql index bfb0ae8059..cfc4c44f98 100644 --- a/software-security/sql-injection-samples/src/test/resources/schema.sql +++ b/software-security/sql-injection-samples/src/test/resources/schema.sql @@ -1,4 +1,5 @@ create table Accounts ( + id BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), customer_id varchar(16) not null, acc_number varchar(16) not null, branch_id decimal(8,0), From a86c69429bf8c99b56ed1b0f236db9a87043aab3 Mon Sep 17 00:00:00 2001 From: Philippe Date: Mon, 1 Apr 2019 22:22:02 -0300 Subject: [PATCH 06/31] Workaround for spring-framework#21094 --- spring-webflux-amqp/pom.xml | 116 ++++++++++-------- .../amqp/SpringWebfluxAmqpApplication.java | 21 ++++ .../src/main/resources/application.yml | 2 +- 3 files changed, 87 insertions(+), 52 deletions(-) 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 From bac144389785c0a78ae398d5854b671fecccce41 Mon Sep 17 00:00:00 2001 From: Philippe Date: Tue, 2 Apr 2019 02:12:55 -0300 Subject: [PATCH 07/31] Initial import --- apache-olingo/olingo2/.gitignore | 29 +++++ apache-olingo/olingo2/pom.xml | 108 ++++++++++++++++++ .../olingo2/CarsODataApplication.java | 24 ++++ .../olingo2/CarsODataJPAServiceFactory.java | 38 ++++++ .../examples/olingo2/JerseyConfig.java | 49 ++++++++ .../olingo2/Olingo2SampleApplication.java | 15 +++ .../examples/olingo2/domain/CarMaker.java | 31 +++++ .../examples/olingo2/domain/CarModel.java | 30 +++++ .../src/main/resources/application.yml | 9 ++ .../olingo2/src/main/resources/data.sql | 3 + .../Olingo2SampleApplicationTests.java | 16 +++ .../sql-injection-samples/pom.xml | 4 + 12 files changed, 356 insertions(+) create mode 100644 apache-olingo/olingo2/.gitignore create mode 100644 apache-olingo/olingo2/pom.xml create mode 100644 apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataApplication.java create mode 100644 apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java create mode 100644 apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/JerseyConfig.java create mode 100644 apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/Olingo2SampleApplication.java create mode 100644 apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarMaker.java create mode 100644 apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarModel.java create mode 100644 apache-olingo/olingo2/src/main/resources/application.yml create mode 100644 apache-olingo/olingo2/src/main/resources/data.sql create mode 100644 apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java diff --git a/apache-olingo/olingo2/.gitignore b/apache-olingo/olingo2/.gitignore new file mode 100644 index 0000000000..153c9335eb --- /dev/null +++ b/apache-olingo/olingo2/.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/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/CarsODataApplication.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataApplication.java new file mode 100644 index 0000000000..c7e3878f44 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataApplication.java @@ -0,0 +1,24 @@ +package org.baeldung.examples.olingo2; + + +import java.util.Set; + +import javax.ws.rs.ApplicationPath; + +import org.apache.olingo.odata2.core.rest.ODataRootLocator; +import org.apache.olingo.odata2.core.rest.app.ODataApplication; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class CarsODataApplication extends ODataApplication { + + private static final Logger log = LoggerFactory.getLogger(CarsODataApplication.class); + + public CarsODataApplication() { + super(); + log.info("[I17] Creating CarsODataApplication..."); + } + +} 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..2d0ae14686 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java @@ -0,0 +1,38 @@ +package org.baeldung.examples.olingo2; + +import javax.persistence.EntityManager; + +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.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * OData ServiceFactory that + * @author Philippe + * + */ +@Component +public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory { + + private EntityManager em; + private static final Logger log = LoggerFactory.getLogger(CarsODataJPAServiceFactory.class); + + public CarsODataJPAServiceFactory(EntityManager em) { + this.em = em; + } + + @Override + public ODataJPAContext initializeODataJPAContext() throws ODataJPARuntimeException { + + ODataJPAContext oDataJPAContext = getODataJPAContext(); + oDataJPAContext.setEntityManagerFactory(em.getEntityManagerFactory()); + oDataJPAContext.setPersistenceUnitName("default"); + + return oDataJPAContext; + + } + +} 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..33db629318 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/JerseyConfig.java @@ -0,0 +1,49 @@ +package org.baeldung.examples.olingo2; + +import javax.servlet.ServletContext; +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.Path; + +import org.apache.olingo.odata2.api.ODataServiceFactory; +import org.apache.olingo.odata2.core.rest.ODataRootLocator; +import org.glassfish.jersey.server.ResourceConfig; +import org.springframework.stereotype.Component; + +@Component +@ApplicationPath("/odata") +public class JerseyConfig extends ResourceConfig { + + + public JerseyConfig(CarsODataApplication delegate,ServletContext servletContext,CarsODataJPAServiceFactory serviceFactory) { + + delegate + .getClasses() + .forEach( c -> { + // Avoid using the default Locator + if ( !ODataRootLocator.class.isAssignableFrom(c)) { + register(c); + } + }); + + register(new CustomLocator(serviceFactory)); + + } + + + @Path("/") + public static class CustomLocator extends ODataRootLocator { + + private CarsODataJPAServiceFactory serviceFactory; + + public CustomLocator(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..6cc4a45927 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/Olingo2SampleApplication.java @@ -0,0 +1,15 @@ +package org.baeldung.examples.olingo2; + +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) { + new Olingo2SampleApplication() + .configure(new SpringApplicationBuilder(Olingo2SampleApplication.class)) + .run(args); + } +} 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..1817a2dece --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarMaker.java @@ -0,0 +1,31 @@ +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.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 + private Long id; + + @NotNull + @Column(name="name") + private String name; + + @OneToMany(mappedBy="maker",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..285e5ce379 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarModel.java @@ -0,0 +1,30 @@ +package org.baeldung.examples.olingo2.domain; + + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.validation.constraints.NotNull; + +import lombok.Data; + +@Entity +@Data +public class CarModel { + + @Id + private Long id; + + @NotNull + private String name; + + @NotNull + private Integer year; + + @NotNull + private String sku; + + @ManyToOne + 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..2af431eee1 --- /dev/null +++ b/apache-olingo/olingo2/src/main/resources/application.yml @@ -0,0 +1,9 @@ + +spring: + jersey: + application-path: /odata + + jpa: + show-sql: true + 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..c1d32dc6ef --- /dev/null +++ b/apache-olingo/olingo2/src/main/resources/data.sql @@ -0,0 +1,3 @@ +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'); diff --git a/apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java b/apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java new file mode 100644 index 0000000000..687f6ab1ff --- /dev/null +++ b/apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java @@ -0,0 +1,16 @@ +package org.baeldung.examples.olingo2; + +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 Olingo2SampleApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/software-security/sql-injection-samples/pom.xml b/software-security/sql-injection-samples/pom.xml index 5b33c674d4..b943151896 100644 --- a/software-security/sql-injection-samples/pom.xml +++ b/software-security/sql-injection-samples/pom.xml @@ -55,6 +55,10 @@ + + org.springframework.boot + spring-boot-devtools + From 881580f2fe9eac3464fafa0f7d4e9456a5deb441 Mon Sep 17 00:00:00 2001 From: Philippe Date: Thu, 4 Apr 2019 00:09:38 -0300 Subject: [PATCH 08/31] [BAEL-1219] OLingo2 code --- .../olingo2/CarsODataApplication.java | 24 -- .../olingo2/CarsODataJPAServiceFactory.java | 271 +++++++++++++++++- .../examples/olingo2/EntityManagerHolder.java | 18 ++ .../examples/olingo2/JerseyConfig.java | 82 +++++- .../olingo2/Olingo2SampleApplication.java | 7 +- .../examples/olingo2/domain/CarMaker.java | 7 +- .../examples/olingo2/domain/CarModel.java | 10 +- .../src/main/resources/application.yml | 1 + .../olingo2/src/main/resources/data.sql | 9 + .../src/test/resources/olingo2-queries.json | 256 +++++++++++++++++ 10 files changed, 641 insertions(+), 44 deletions(-) delete mode 100644 apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataApplication.java create mode 100644 apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/EntityManagerHolder.java create mode 100644 apache-olingo/olingo2/src/test/resources/olingo2-queries.json diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataApplication.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataApplication.java deleted file mode 100644 index c7e3878f44..0000000000 --- a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataApplication.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.baeldung.examples.olingo2; - - -import java.util.Set; - -import javax.ws.rs.ApplicationPath; - -import org.apache.olingo.odata2.core.rest.ODataRootLocator; -import org.apache.olingo.odata2.core.rest.app.ODataApplication; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -@Component -public class CarsODataApplication extends ODataApplication { - - private static final Logger log = LoggerFactory.getLogger(CarsODataApplication.class); - - public CarsODataApplication() { - super(); - log.info("[I17] Creating CarsODataApplication..."); - } - -} 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 index 2d0ae14686..cf13bd0fc9 100644 --- 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 @@ -1,37 +1,292 @@ 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 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.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.orm.jpa.EntityManagerFactoryUtils; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.stereotype.Component; /** - * OData ServiceFactory that + * ODataJPAServiceFactory implementation for our sample domain * @author Philippe * */ @Component public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory { - private EntityManager em; private static final Logger log = LoggerFactory.getLogger(CarsODataJPAServiceFactory.class); - public CarsODataJPAServiceFactory(EntityManager em) { - this.em = em; + 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 { - ODataJPAContext oDataJPAContext = getODataJPAContext(); - oDataJPAContext.setEntityManagerFactory(em.getEntityManagerFactory()); - oDataJPAContext.setPersistenceUnitName("default"); + log.info("[I32] >>> initializeODataJPAContext()"); + ODataJPAContext ctx = getODataJPAContext(); - return oDataJPAContext; + // Here we're passing the EM that was created by the EntityManagerFilter (see JerseyConfig) + ctx.setEntityManager(new EntityManagerWrapper(EntityManagerHolder.getCurrentEntityManager())); + 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/EntityManagerHolder.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/EntityManagerHolder.java new file mode 100644 index 0000000000..682621eb99 --- /dev/null +++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/EntityManagerHolder.java @@ -0,0 +1,18 @@ +package org.baeldung.examples.olingo2; + +import javax.persistence.EntityManager; + +public class EntityManagerHolder { + + private static ThreadLocal currentEntityManager = new ThreadLocal<>(); + + + public static void setCurrentEntityManager(EntityManager em) { + currentEntityManager.set(em); + } + + public static EntityManager getCurrentEntityManager() { + return currentEntityManager.get(); + } + +} 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 index 33db629318..a82220e854 100644 --- 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 @@ -1,41 +1,111 @@ 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.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.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(CarsODataApplication delegate,ServletContext servletContext,CarsODataJPAServiceFactory serviceFactory) { + public JerseyConfig(CarsODataJPAServiceFactory serviceFactory, EntityManagerFactory emf) { - delegate + ODataApplication app = new ODataApplication(); + + app .getClasses() .forEach( c -> { - // Avoid using the default Locator + // Avoid using the default RootLocator, as we want + // a Spring Managed one if ( !ODataRootLocator.class.isAssignableFrom(c)) { register(c); } }); - register(new CustomLocator(serviceFactory)); + 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); + + private final EntityManagerFactory emf; + + public EntityManagerFilter(EntityManagerFactory emf) { + this.emf = emf; + } + + @Override + public void filter(ContainerRequestContext ctx) throws IOException { + log.info("[I60] >>> filter"); + EntityManager em = this.emf.createEntityManager(); + EntityManagerHolder.setCurrentEntityManager(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 = EntityManagerHolder.getCurrentEntityManager(); + if ( em != null && !"GET".equalsIgnoreCase(requestContext.getMethod())) { + EntityTransaction t = em.getTransaction(); + if ( t.isActive()) { + if ( !t.getRollbackOnly()) { + t.commit(); + } + } + } + + em.close(); + + } } @Path("/") - public static class CustomLocator extends ODataRootLocator { + public static class CarsRootLocator extends ODataRootLocator { private CarsODataJPAServiceFactory serviceFactory; - public CustomLocator(CarsODataJPAServiceFactory serviceFactory) { + public CarsRootLocator(CarsODataJPAServiceFactory serviceFactory) { this.serviceFactory = 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 index 6cc4a45927..fa58612088 100644 --- 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 @@ -1,5 +1,6 @@ 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; @@ -7,9 +8,7 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer @SpringBootApplication public class Olingo2SampleApplication extends SpringBootServletInitializer { - public static void main(String[] args) { - new Olingo2SampleApplication() - .configure(new SpringApplicationBuilder(Olingo2SampleApplication.class)) - .run(args); + 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 index 1817a2dece..42a3eaa59d 100644 --- 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 @@ -5,6 +5,8 @@ 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; @@ -18,13 +20,16 @@ import lombok.Data; public class CarMaker { @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @NotNull @Column(name="name") private String name; - @OneToMany(mappedBy="maker",cascade=CascadeType.ALL) + @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 index 285e5ce379..a4f2a04f6e 100644 --- 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 @@ -2,17 +2,24 @@ 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 @@ -24,7 +31,8 @@ public class CarModel { @NotNull private String sku; - @ManyToOne + @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 index 2af431eee1..a29b572575 100644 --- a/apache-olingo/olingo2/src/main/resources/application.yml +++ b/apache-olingo/olingo2/src/main/resources/application.yml @@ -5,5 +5,6 @@ spring: 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 index c1d32dc6ef..327f2688c5 100644 --- a/apache-olingo/olingo2/src/main/resources/data.sql +++ b/apache-olingo/olingo2/src/main/resources/data.sql @@ -1,3 +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/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 From 6ac9c01d3d996ec716e4386b945815acdcbe3b4c Mon Sep 17 00:00:00 2001 From: Philippe Date: Mon, 8 Apr 2019 10:23:31 -0300 Subject: [PATCH 09/31] Initial import --- .../olingo2/CarsODataJPAServiceFactory.java | 39 +-- .../examples/olingo2/EntityManagerHolder.java | 18 -- .../examples/olingo2/JerseyConfig.java | 40 +-- .../src/main/resources/application.yml | 4 +- apache-olingo/olingo4/.gitignore | 29 +++ apache-olingo/olingo4/pom.xml | 95 +++++++ .../examples/olingo4/DefaultODataFactory.java | 20 ++ .../examples/olingo4/ODataFactory.java | 8 + .../olingo4/ODataHttpHandlerFactory.java | 8 + .../olingo4/ODataHttpHandlerFactoryImpl.java | 42 ++++ .../olingo4/ODataServiceConfiguration.java | 46 ++++ .../examples/olingo4/ODataServlet.java | 38 +++ .../olingo4/Olingo4SampleApplication.java | 13 + .../examples/olingo4/domain/CarMaker.java | 36 +++ .../examples/olingo4/domain/CarModel.java | 38 +++ .../examples/olingo4/edm/EdmTypeMapper.java | 46 ++++ .../examples/olingo4/edm/JpaEdmProvider.java | 237 ++++++++++++++++++ .../JpaEntityCollectionProcessor.java | 185 ++++++++++++++ .../repository/CarMakerRepository.java | 12 + .../repository/CarModelRepository.java | 13 + .../repository/EdmEntityRepository.java | 15 ++ .../repository/RepositoryRegistry.java | 28 +++ .../src/main/resources/application.properties | 6 + .../olingo4/src/main/resources/data.sql | 12 + .../Olingo4SampleApplicationTests.java | 16 ++ 25 files changed, 991 insertions(+), 53 deletions(-) delete mode 100644 apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/EntityManagerHolder.java create mode 100644 apache-olingo/olingo4/.gitignore create mode 100644 apache-olingo/olingo4/pom.xml create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/DefaultODataFactory.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataFactory.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataHttpHandlerFactory.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataHttpHandlerFactoryImpl.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServiceConfiguration.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServlet.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/Olingo4SampleApplication.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/domain/CarMaker.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/domain/CarModel.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/EdmTypeMapper.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/JpaEdmProvider.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityCollectionProcessor.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarMakerRepository.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarModelRepository.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/EdmEntityRepository.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/RepositoryRegistry.java create mode 100644 apache-olingo/olingo4/src/main/resources/application.properties create mode 100644 apache-olingo/olingo4/src/main/resources/data.sql create mode 100644 apache-olingo/olingo4/src/test/java/org/baeldung/examples/olingo4/Olingo4SampleApplicationTests.java 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 index cf13bd0fc9..65a0428154 100644 --- 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 @@ -19,10 +19,13 @@ 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; @@ -36,15 +39,14 @@ import org.springframework.stereotype.Component; */ @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. @@ -54,37 +56,40 @@ public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory { 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(EntityManagerHolder.getCurrentEntityManager())); + 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); - - + 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()); + log.info("[I68] persist: entity.class=" + entity.getClass() + .getSimpleName()); delegate.persist(entity); - //delegate.flush(); + // delegate.flush(); } public T merge(T entity) { - log.info("[I74] merge: entity.class=" + entity.getClass().getSimpleName()); + 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()); + log.info("[I78] remove: entity.class=" + entity.getClass() + .getSimpleName()); delegate.remove(entity); } @@ -287,7 +292,7 @@ public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory { public EntityManagerWrapper(EntityManager delegate) { this.delegate = delegate; } - + } } diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/EntityManagerHolder.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/EntityManagerHolder.java deleted file mode 100644 index 682621eb99..0000000000 --- a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/EntityManagerHolder.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.baeldung.examples.olingo2; - -import javax.persistence.EntityManager; - -public class EntityManagerHolder { - - private static ThreadLocal currentEntityManager = new ThreadLocal<>(); - - - public static void setCurrentEntityManager(EntityManager em) { - currentEntityManager.set(em); - } - - public static EntityManager getCurrentEntityManager() { - return currentEntityManager.get(); - } - -} 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 index a82220e854..78caf99861 100644 --- 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 @@ -1,4 +1,4 @@ -package org.baeldung.examples.olingo2; + package org.baeldung.examples.olingo2; import java.io.IOException; @@ -6,12 +6,14 @@ 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; @@ -57,11 +59,15 @@ public class JerseyConfig extends ResourceConfig { */ @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; } @@ -70,11 +76,12 @@ public class JerseyConfig extends ResourceConfig { public void filter(ContainerRequestContext ctx) throws IOException { log.info("[I60] >>> filter"); EntityManager em = this.emf.createEntityManager(); - EntityManagerHolder.setCurrentEntityManager(em); - + httpRequest.setAttribute(EM_REQUEST_ATTRIBUTE, em); + // Start a new transaction unless we have a simple GET - if ( !"GET".equalsIgnoreCase(ctx.getMethod())) { - em.getTransaction().begin(); + if (!"GET".equalsIgnoreCase(ctx.getMethod())) { + em.getTransaction() + .begin(); } } @@ -82,24 +89,23 @@ public class JerseyConfig extends ResourceConfig { public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { log.info("[I68] <<< filter"); + EntityManager em = (EntityManager) httpRequest.getAttribute(EM_REQUEST_ATTRIBUTE); - EntityManager em = EntityManagerHolder.getCurrentEntityManager(); - if ( em != null && !"GET".equalsIgnoreCase(requestContext.getMethod())) { + if (!"GET".equalsIgnoreCase(requestContext.getMethod())) { EntityTransaction t = em.getTransaction(); - if ( t.isActive()) { - if ( !t.getRollbackOnly()) { + if (t.isActive()) { + if (!t.getRollbackOnly()) { t.commit(); } } } - + em.close(); - + } - + } - - + @Path("/") public static class CarsRootLocator extends ODataRootLocator { @@ -113,7 +119,7 @@ public class JerseyConfig extends ResourceConfig { public ODataServiceFactory getServiceFactory() { return this.serviceFactory; } - + } } diff --git a/apache-olingo/olingo2/src/main/resources/application.yml b/apache-olingo/olingo2/src/main/resources/application.yml index a29b572575..21563a94fe 100644 --- a/apache-olingo/olingo2/src/main/resources/application.yml +++ b/apache-olingo/olingo2/src/main/resources/application.yml @@ -1,4 +1,6 @@ - +server: + port: 8180 + spring: jersey: application-path: /odata 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..a6f1fcdb7b --- /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..bbac0ceac7 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServiceConfiguration.java @@ -0,0 +1,46 @@ +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, EntityManagerFactory emf) { + + ServletRegistrationBean bean = new ServletRegistrationBean( + odataServlet(factory,emf), + "/odata/*"); + bean.setLoadOnStartup(1); + return bean; + } + + + @Bean + public HttpServlet odataServlet(ODataHttpHandlerFactory factory, EntityManagerFactory emf ) { + + return new ODataServlet(factory,emf); + } + + + @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..c2adf2c1ae --- /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, EntityManagerFactory emf) { + 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/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/Olingo4SampleApplication.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/Olingo4SampleApplication.java new file mode 100644 index 0000000000..1ac872ea0f --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/Olingo4SampleApplication.java @@ -0,0 +1,13 @@ +package org.baeldung.examples.olingo4; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Olingo4SampleApplication { + + public static void main(String[] args) { + SpringApplication.run(Olingo4SampleApplication.class, args); + } + +} 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..e6cd80ebf1 --- /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.LAZY) + @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..3e490cdf58 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/JpaEdmProvider.java @@ -0,0 +1,237 @@ +package org.baeldung.examples.olingo4.edm; + +import java.util.ArrayList; +import java.util.List; +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 = "OData.Demo"; + + // EDM Container + public static final String CONTAINER_NAME = "Cars"; + public static final FullQualifiedName CONTAINER = new FullQualifiedName(NAMESPACE, CONTAINER_NAME); + + 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); + entitySet.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 { + + Metamodel mm = emf.getMetamodel(); + + CsdlEntityType result = null; + + result = mm.getEntities() + .stream() + .filter(et -> entityTypeName.equals(new FullQualifiedName(NAMESPACE, et.getName()))) + .map(et -> buildODataType(et)) + .findFirst() + .orElse(null); + + 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 navs + List navs = et.getDeclaredPluralAttributes() + .stream() + .map(attr -> buildNavAttribute(et, attr)) + .collect(Collectors.toList()); + result.setNavigationProperties(navs); + + 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; + } + + private CsdlNavigationProperty buildNavAttribute(EntityType et, PluralAttribute attr) { + + CsdlNavigationProperty p = new CsdlNavigationProperty().setName(attr.getName()) + .setType(new FullQualifiedName(NAMESPACE, attr.getBindableJavaType().getSimpleName())) + .setNullable(false); // for now + + 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..ed921484c1 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityCollectionProcessor.java @@ -0,0 +1,185 @@ +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.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.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.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; + + public JpaEntityCollectionProcessor(EntityManagerFactory emf, RepositoryRegistry repositoryRegistry) { + this.emf = emf; + this.repositoryRegistry = repositoryRegistry; + } + + @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"); + + } + + private EntityCollection getData(EdmEntitySet edmEntitySet, UriInfo uriInfo) { + + EdmEntityType type = edmEntitySet.getEntityType(); + JpaRepository repo = repositoryRegistry.getRepositoryForEntity(type); + EntityCollection result = new EntityCollection(); + + repo.findAll() + .stream() + .forEach((it) -> result.getEntities() + .add(map2entity(edmEntitySet, it))); + + return result; + } + + private Entity map2entity(EdmEntitySet edmEntitySet, Object entry) { + + EntityType et = emf.getMetamodel() + .entity(entry.getClass()); + + + Entity e = new Entity(); + try { + // First, we set the entity's primary key + + // Now map all properties + 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; + } + + private 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); + } + } + + 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); + } + } + + private Long getCount(EdmEntitySet edmEntitySet, UriInfo uriInfo) { + // TODO Auto-generated method stub + return null; + } + +} 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..70664bcf86 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarMakerRepository.java @@ -0,0 +1,12 @@ +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 JpaRepository, JpaSpecificationExecutor, EdmEntityRepository { + + public default String getEdmEntityName() { return CarMaker.class.getSimpleName();} +} 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..40590b15e1 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarModelRepository.java @@ -0,0 +1,13 @@ +package org.baeldung.examples.olingo4.repository; + +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 JpaRepository, JpaSpecificationExecutor,EdmEntityRepository { + + public default String getEdmEntityName() { return CarModel.class.getSimpleName();} + +} 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..105925c958 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/EdmEntityRepository.java @@ -0,0 +1,15 @@ +/** + * + */ +package org.baeldung.examples.olingo4.repository; + + +/** + * @author Philippe + * + */ +public interface EdmEntityRepository { + + public String getEdmEntityName(); + +} 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..991eb21fc2 --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/RepositoryRegistry.java @@ -0,0 +1,28 @@ +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..6f115b5ae4 --- /dev/null +++ b/apache-olingo/olingo4/src/main/resources/application.properties @@ -0,0 +1,6 @@ +spring: + jpa: + show-sql: true + open-in-view: false + 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() { + } + +} From 270582b25aac5b27b87281f9bdeaecf9e155c87f Mon Sep 17 00:00:00 2001 From: Philippe Date: Fri, 12 Apr 2019 00:16:38 -0300 Subject: [PATCH 10/31] [BAEL-1219] Code for Olingo V4 sample --- apache-olingo/olingo4/pom.xml | 2 +- .../olingo4/ODataServiceConfiguration.java | 31 +- .../examples/olingo4/ODataServlet.java | 2 +- .../examples/olingo4/edm/JpaEdmProvider.java | 33 +- .../JpaEntityCollectionProcessor.java | 77 ++-- .../olingo4/processor/JpaEntityMapper.java | 84 ++++ .../olingo4/processor/JpaEntityProcessor.java | 378 ++++++++++++++++++ .../repository/CarMakerRepository.java | 6 +- .../repository/CarModelRepository.java | 11 +- .../repository/EdmEntityRepository.java | 4 +- .../repository/RepositoryRegistry.java | 11 +- .../src/main/resources/application.properties | 3 + 12 files changed, 552 insertions(+), 90 deletions(-) create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityMapper.java create mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityProcessor.java diff --git a/apache-olingo/olingo4/pom.xml b/apache-olingo/olingo4/pom.xml index a6f1fcdb7b..794aee0711 100644 --- a/apache-olingo/olingo4/pom.xml +++ b/apache-olingo/olingo4/pom.xml @@ -52,7 +52,7 @@ org.springframework.boot spring-boot-starter-web - + org.apache.olingo odata-server-api 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 index bbac0ceac7..0cde665359 100644 --- 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 @@ -14,33 +14,22 @@ import org.springframework.context.annotation.Configuration; @Configuration public class ODataServiceConfiguration { - - - @Bean - public ServletRegistrationBean odataServletRegistration(ODataHttpHandlerFactory factory, EntityManagerFactory emf) { - - ServletRegistrationBean bean = new ServletRegistrationBean( - odataServlet(factory,emf), - "/odata/*"); - bean.setLoadOnStartup(1); - return bean; - } - @Bean - public HttpServlet odataServlet(ODataHttpHandlerFactory factory, EntityManagerFactory emf ) { - - return new ODataServlet(factory,emf); + 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(); + .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 index c2adf2c1ae..c379124541 100644 --- 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 @@ -25,7 +25,7 @@ public class ODataServlet extends HttpServlet { private final ODataHttpHandlerFactory odataHttpHandlerFactory; - public ODataServlet(ODataHttpHandlerFactory factory, EntityManagerFactory emf) { + public ODataServlet(ODataHttpHandlerFactory factory) { this.odataHttpHandlerFactory = factory; } 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 index 3e490cdf58..68edb58e12 100644 --- 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 @@ -62,8 +62,9 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider { if (e != null) { CsdlEntitySet entitySet = new CsdlEntitySet(); - entitySet.setName(entitySetName); - entitySet.setType(new FullQualifiedName(NAMESPACE, e.getName())); + entitySet + .setName(entitySetName) + .setType(new FullQualifiedName(NAMESPACE, e.getName())); return entitySet; } } @@ -135,7 +136,6 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider { .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); @@ -197,12 +197,22 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider { result.setKey(ids); - // Process navs + // 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; } @@ -225,13 +235,26 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider { 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())) - .setNullable(false); // for now + .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 index ed921484c1..6bca0e9896 100644 --- 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 @@ -48,10 +48,12 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces private ServiceMetadata serviceMetadata; private EntityManagerFactory emf; private RepositoryRegistry repositoryRegistry; + private JpaEntityMapper entityMapper; - public JpaEntityCollectionProcessor(EntityManagerFactory emf, RepositoryRegistry repositoryRegistry) { + public JpaEntityCollectionProcessor(EntityManagerFactory emf, RepositoryRegistry repositoryRegistry, JpaEntityMapper entityMapper) { this.emf = emf; this.repositoryRegistry = repositoryRegistry; + this.entityMapper = entityMapper; } @Override @@ -115,71 +117,40 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces } - private EntityCollection getData(EdmEntitySet edmEntitySet, UriInfo uriInfo) { + /** + * 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 = repositoryRegistry.getRepositoryForEntity(type); + JpaRepository repo = (JpaRepository)repositoryRegistry.getRepositoryForEntity(type); EntityCollection result = new EntityCollection(); repo.findAll() .stream() .forEach((it) -> result.getEntities() - .add(map2entity(edmEntitySet, it))); + .add(entityMapper.map2entity(edmEntitySet, it))); return result; } - private Entity map2entity(EdmEntitySet edmEntitySet, Object entry) { - - EntityType et = emf.getMetamodel() - .entity(entry.getClass()); - - - Entity e = new Entity(); - try { - // First, we set the entity's primary key - - // Now map all properties - 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; - } - - private 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); - } - } - - 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); - } - } + /** + * Helper method to get the total size of an entity set + * @param edmEntitySet + * @param uriInfo + * @return + */ private Long getCount(EdmEntitySet edmEntitySet, UriInfo uriInfo) { - // TODO Auto-generated method stub - return null; + + 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..5fd863124f --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityMapper.java @@ -0,0 +1,84 @@ +/** + * + */ +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; + } + + + private 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); + } + } + + 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..23a5a7ac4b --- /dev/null +++ b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityProcessor.java @@ -0,0 +1,378 @@ +/** + * + */ +package org.baeldung.examples.olingo4.processor; + +import java.io.InputStream; +import java.lang.reflect.Member; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; + +import javax.persistence.EntityManagerFactory; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +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.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmNavigationProperty; +import org.apache.olingo.commons.api.edm.EdmType; +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.EntityCollectionSerializerOptions; +import org.apache.olingo.server.api.serializer.EntitySerializerOptions; +import org.apache.olingo.server.api.serializer.ODataSerializer; +import org.apache.olingo.server.api.serializer.SerializerException; +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.domain.Specification; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +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(); + EdmEntityType rootEntityType = rootEntitySet.getEntityType(); + + + if ( resourceParts.size() == 1 ) { + entityStream = readEntity(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; + + // We have three scenarios we must handle: + // Entity(x)/Related, where Related is a 1:N or M:N relationship => result is a collection + // Entity(x)/Related, where Related is a N:1 or 1:1 relationship => result is a single entity + // Entity(x)/Related(z), where Related is a 1:N or M:N relationship => result is a single entity + if (navSegment.getKeyPredicates().isEmpty()) { + if ( isOne2ManyProperty(rootEntityType,navSegment.getProperty())) { + entityStream = readRelatedEntities(rootEntitySet,rootPredicates,navSegment.getProperty(),responseFormat); + } + else { + // The relation must point to another entity type, so casting should be safe here + EdmEntityType resultType = (EdmEntityType)rootEntityType.getNavigationProperty(navSegment.getProperty().getName()).getType(); + EdmEntitySet resultEntitySet = entitySetFromType(resultType); + + entityStream = readEntity(resultEntitySet, navSegment.getKeyPredicates(), responseFormat); + } + } + else { + 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(); + } + + private InputStream readEntity(EdmEntitySet entitySet, List keyPredicates,ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { + + Entity entity = readEntityData(entitySet,keyPredicates); + + 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(); + } + + private InputStream readRelatedEntities(EdmEntitySet rootEntitySet, List rootPredicates, EdmNavigationProperty property, ContentType responseFormat) throws ODataApplicationException { + + Object jpaEntity = readJPAEntity(rootEntitySet, rootPredicates); + try { + Object set = 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(); + + ((Collection)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", "serial", "unchecked" }) + private InputStream readRelatedEntity(ODataRequest request, EdmEntitySet rootEntitySet, List rootPredicates, EdmNavigationProperty property, List predicates, ContentType responseFormat) throws ODataApplicationException, SerializerException { + + + JpaSpecificationExecutor rootRepo = (JpaSpecificationExecutor)registry.getRepositoryForEntity(rootEntitySet.getEntityType()); + JpaSpecificationExecutor repo = (JpaSpecificationExecutor)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)rootRepo).getEntityClass(); + Class childClass = ((EdmEntityRepository)repo).getEntityClass(); + SingularAttribute fk = emf.getMetamodel() + .entity(childClass) + .getSingularAttributes() + .stream() + .filter((attr) -> attr.isAssociation() && attr.getJavaType().isAssignableFrom(rootClass)) + .findFirst() + .orElse(null); + + SingularAttribute pk = emf.getMetamodel() + .entity(childClass) + .getId(Long.class); + + SingularAttribute rootPk = emf.getMetamodel() + .entity(rootClass) + .getId(Long.class); + + if ( fk == null ) { + throw new ODataRuntimeException("[E230] No singular attribute of child class '" + childClass.getName() + "' found" ); + } + + + Specification spec = new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery q, CriteriaBuilder cb) { + + try { + Object rootInstance = rootClass.newInstance(); + PropertyUtils.setProperty(rootInstance, rootPk.getName(), getEntityKey(rootEntitySet.getEntityType(),rootPredicates)); + + final Predicate p = cb.and( + cb.equal( + root.get(pk), + getEntityKey(property.getType(),predicates)), + cb.equal( + root.get(fk), + rootInstance)); + + return p; + } + catch(Exception ex) { + throw new ODataRuntimeException(ex); + } + + } + }; + + // Read data from DB + EdmEntitySet relatedEntitySet = entitySetFromType(property.getType()); + EntityCollection data = new EntityCollection(); + + repo.findAll(spec) + .stream() + .forEach((entry) -> data.getEntities().add(entityMapper.map2entity(relatedEntitySet, entry))); + + // + + ODataSerializer serializer = odata.createSerializer(responseFormat); + + // 4th: Now serialize the content: transform from the EntitySet object to InputStream + EdmEntityType edmEntityType = relatedEntitySet.getEntityType(); + ContextURL contextUrl = ContextURL.with() + .entitySet(relatedEntitySet) + .build(); + + final String id = request.getRawBaseUri() + "/" + relatedEntitySet.getName(); + EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with() + .id(id) + .contextURL(contextUrl) + .build(); + SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, edmEntityType, data, opts); + InputStream serializedContent = serializerResult.getContent(); + + + return serializedContent; + } + + + /** + * This method returns a speficic entity given its primary key + * @param edmEntitySet + * @param keyPredicates + * @return + */ + protected Entity readEntityData(EdmEntitySet edmEntitySet, List keyPredicates) throws ODataApplicationException { + + Object jpaEntry = readJPAEntity(edmEntitySet, keyPredicates); + Entity e = entityMapper.map2entity(edmEntitySet, jpaEntry); + return e; + } + + 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 Object getEntityKey(EdmEntityType type, 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 index 70664bcf86..1bde9f148c 100644 --- 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 @@ -6,7 +6,11 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.stereotype.Repository; @Repository -public interface CarMakerRepository extends JpaRepository, JpaSpecificationExecutor, EdmEntityRepository { +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 index 40590b15e1..247bf6e77b 100644 --- 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 @@ -1,13 +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 JpaRepository, JpaSpecificationExecutor,EdmEntityRepository { +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 index 105925c958..dbfd0e6f93 100644 --- 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 @@ -8,8 +8,10 @@ package org.baeldung.examples.olingo4.repository; * @author Philippe * */ -public interface EdmEntityRepository { +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 index 991eb21fc2..20981fdfef 100644 --- 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 @@ -5,24 +5,23 @@ 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<>(); + private Map> repositoriesByClassName = new HashMap<>(); - public RepositoryRegistry(List allRepositories) { + public RepositoryRegistry(List> allRepositories) { allRepositories.stream().forEach((r) -> - repositoriesByClassName.put(r.getEdmEntityName(),(JpaRepository)r)); + repositoriesByClassName.put(r.getEdmEntityName(),(EdmEntityRepository)r)); } - public JpaRepository getRepositoryForEntity(EdmEntityType entityType) { - JpaRepository repo = repositoriesByClassName.get(entityType.getName()); + public EdmEntityRepository getRepositoryForEntity(EdmEntityType entityType) { + EdmEntityRepository 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 index 6f115b5ae4..e4742b4fbb 100644 --- a/apache-olingo/olingo4/src/main/resources/application.properties +++ b/apache-olingo/olingo4/src/main/resources/application.properties @@ -1,3 +1,6 @@ +server: + port: 8080 + spring: jpa: show-sql: true From 5f30277f9e8af356288061502bc180a425d314be Mon Sep 17 00:00:00 2001 From: Philippe Date: Sun, 14 Apr 2019 13:17:38 -0300 Subject: [PATCH 11/31] [BAEL-1219] Code polishing --- .../examples/olingo4/domain/CarModel.java | 2 +- .../examples/olingo4/edm/JpaEdmProvider.java | 17 +- .../JpaEntityCollectionProcessor.java | 17 +- .../olingo4/processor/JpaEntityMapper.java | 11 +- .../olingo4/processor/JpaEntityProcessor.java | 276 +++++++----------- .../repository/RepositoryRegistry.java | 12 +- .../src/main/resources/application.properties | 2 +- 7 files changed, 144 insertions(+), 193 deletions(-) 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 index e6cd80ebf1..a9254e48b9 100644 --- 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 @@ -31,7 +31,7 @@ public class CarModel { @NotNull private String sku; - @ManyToOne(optional=false, fetch= FetchType.LAZY) + @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/JpaEdmProvider.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/JpaEdmProvider.java index 68edb58e12..4cd979e931 100644 --- 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 @@ -1,7 +1,9 @@ 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; @@ -33,11 +35,14 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider { private EdmTypeMapper typeMapper; // Service Namespace - public static final String NAMESPACE = "OData.Demo"; + 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; @@ -153,11 +158,13 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider { @Override public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) throws ODataException { + + CsdlEntityType result = cdslName2Type.get(entityTypeName); + if ( result != null ) { + return result; + } Metamodel mm = emf.getMetamodel(); - - CsdlEntityType result = null; - result = mm.getEntities() .stream() .filter(et -> entityTypeName.equals(new FullQualifiedName(NAMESPACE, et.getName()))) @@ -165,6 +172,8 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider { .findFirst() .orElse(null); + // save for future use + cdslName2Type.put(entityTypeName, result); return result; } 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 index 6bca0e9896..4a4e5026f3 100644 --- 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 @@ -5,6 +5,7 @@ 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; @@ -19,6 +20,7 @@ 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; @@ -35,6 +37,7 @@ 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; @@ -110,8 +113,7 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces 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.setContent(new ByteArrayInputStream(count.toString().getBytes())); response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setHeader(HttpHeader.CONTENT_TYPE, "text/plain"); @@ -130,9 +132,9 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces EntityCollection result = new EntityCollection(); repo.findAll() - .stream() - .forEach((it) -> result.getEntities() - .add(entityMapper.map2entity(edmEntitySet, it))); + .stream() + .forEach((it) -> result.getEntities() + .add(entityMapper.map2entity(edmEntitySet, it))); return result; } @@ -144,7 +146,7 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces * @param uriInfo * @return */ - private Long getCount(EdmEntitySet edmEntitySet, UriInfo uriInfo) { + protected Long getCount(EdmEntitySet edmEntitySet, UriInfo uriInfo) { EdmEntityType type = edmEntitySet.getEntityType(); JpaRepository repo = (JpaRepository)repositoryRegistry.getRepositoryForEntity(type); @@ -152,5 +154,8 @@ public class JpaEntityCollectionProcessor implements CountEntityCollectionProces 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 index 5fd863124f..1978aa4fd6 100644 --- 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 @@ -63,13 +63,22 @@ public class JpaEntityMapper { } - private Object getPropertyValue(Object entry, String name) { + 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 { 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 index 23a5a7ac4b..719e5de160 100644 --- 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 @@ -4,27 +4,19 @@ package org.baeldung.examples.olingo4.processor; import java.io.InputStream; -import java.lang.reflect.Member; -import java.util.Collection; import java.util.List; import java.util.Locale; -import java.util.stream.Collectors; +import java.util.Optional; +import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; 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.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.edm.EdmNavigationProperty; -import org.apache.olingo.commons.api.edm.EdmType; import org.apache.olingo.commons.api.ex.ODataRuntimeException; import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.http.HttpHeader; @@ -36,10 +28,8 @@ 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.EntityCollectionSerializerOptions; import org.apache.olingo.server.api.serializer.EntitySerializerOptions; import org.apache.olingo.server.api.serializer.ODataSerializer; -import org.apache.olingo.server.api.serializer.SerializerException; import org.apache.olingo.server.api.serializer.SerializerResult; import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.api.uri.UriParameter; @@ -48,9 +38,7 @@ 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.domain.Specification; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.stereotype.Component; /** @@ -99,11 +87,9 @@ public class JpaEntityProcessor implements EntityProcessor { UriResourceEntitySet rootResourceEntitySet = (UriResourceEntitySet) resourceParts.get(0); EdmEntitySet rootEntitySet = rootResourceEntitySet.getEntitySet(); List rootPredicates = rootResourceEntitySet.getKeyPredicates(); - EdmEntityType rootEntityType = rootEntitySet.getEntityType(); - if ( resourceParts.size() == 1 ) { - entityStream = readEntity(rootEntitySet,rootPredicates,responseFormat); + entityStream = readRootEntity(rootEntitySet,rootPredicates,responseFormat); } else if ( resourceParts.size() == 2 ) { UriResource part = resourceParts.get(1); @@ -112,27 +98,7 @@ public class JpaEntityProcessor implements EntityProcessor { } UriResourceNavigation navSegment = (UriResourceNavigation)part; - - // We have three scenarios we must handle: - // Entity(x)/Related, where Related is a 1:N or M:N relationship => result is a collection - // Entity(x)/Related, where Related is a N:1 or 1:1 relationship => result is a single entity - // Entity(x)/Related(z), where Related is a 1:N or M:N relationship => result is a single entity - if (navSegment.getKeyPredicates().isEmpty()) { - if ( isOne2ManyProperty(rootEntityType,navSegment.getProperty())) { - entityStream = readRelatedEntities(rootEntitySet,rootPredicates,navSegment.getProperty(),responseFormat); - } - else { - // The relation must point to another entity type, so casting should be safe here - EdmEntityType resultType = (EdmEntityType)rootEntityType.getNavigationProperty(navSegment.getProperty().getName()).getType(); - EdmEntitySet resultEntitySet = entitySetFromType(resultType); - - entityStream = readEntity(resultEntitySet, navSegment.getKeyPredicates(), responseFormat); - } - } - else { - entityStream = readRelatedEntity(request, rootEntitySet,rootPredicates,navSegment.getProperty(),navSegment.getKeyPredicates(),responseFormat); - } - + entityStream = readRelatedEntity(request, rootEntitySet,rootPredicates,navSegment.getProperty(),navSegment.getKeyPredicates(),responseFormat); } else { // For now, we'll only allow navigation just to directly linked navs @@ -161,14 +127,30 @@ public class JpaEntityProcessor implements EntityProcessor { } // - private boolean isOne2ManyProperty(EdmEntityType entityType, EdmNavigationProperty property) { - return entityType.getProperty(property.getName()) != null && property.isCollection(); - } + // private boolean isOne2ManyProperty(EdmEntityType entityType, EdmNavigationProperty property) { + // return entityType.getProperty(property.getName()) != null && property.isCollection(); + //} - private InputStream readEntity(EdmEntitySet entitySet, List keyPredicates,ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { - - Entity entity = readEntityData(entitySet,keyPredicates); + @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 @@ -180,157 +162,101 @@ public class JpaEntityProcessor implements EntityProcessor { SerializerResult serializerResult = serializer.entity(serviceMetadata, entitySet.getEntityType(), entity, options); return serializerResult.getContent(); + } - private InputStream readRelatedEntities(EdmEntitySet rootEntitySet, List rootPredicates, EdmNavigationProperty property, ContentType responseFormat) throws ODataApplicationException { - - Object jpaEntity = readJPAEntity(rootEntitySet, rootPredicates); - try { - Object set = 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(); - - ((Collection)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("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", "serial", "unchecked" }) - private InputStream readRelatedEntity(ODataRequest request, EdmEntitySet rootEntitySet, List rootPredicates, EdmNavigationProperty property, List predicates, ContentType responseFormat) throws ODataApplicationException, SerializerException { + @SuppressWarnings({ "rawtypes", "unchecked" }) + private InputStream readRelatedEntity(ODataRequest request, EdmEntitySet entitySet, List rootPredicates, EdmNavigationProperty property, List parentPredicates, ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { - JpaSpecificationExecutor rootRepo = (JpaSpecificationExecutor)registry.getRepositoryForEntity(rootEntitySet.getEntityType()); - JpaSpecificationExecutor repo = (JpaSpecificationExecutor)registry.getRepositoryForEntity(property.getType()); + 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)rootRepo).getEntityClass(); - Class childClass = ((EdmEntityRepository)repo).getEntityClass(); + Class rootClass = ((EdmEntityRepository)repo).getEntityClass(); + Class relatedClass = ((EdmEntityRepository)relatedRepo).getEntityClass(); + SingularAttribute fk = emf.getMetamodel() - .entity(childClass) + .entity(rootClass) .getSingularAttributes() .stream() - .filter((attr) -> attr.isAssociation() && attr.getJavaType().isAssignableFrom(rootClass)) + .filter((attr) -> { + boolean b = attr.isAssociation() && attr.getJavaType().isAssignableFrom(relatedClass); + return b; + }) .findFirst() .orElse(null); - SingularAttribute pk = emf.getMetamodel() - .entity(childClass) - .getId(Long.class); - - SingularAttribute rootPk = emf.getMetamodel() - .entity(rootClass) - .getId(Long.class); - if ( fk == null ) { - throw new ODataRuntimeException("[E230] No singular attribute of child class '" + childClass.getName() + "' found" ); + throw new ODataRuntimeException("[E230] No singular attribute of child class '" + relatedClass.getName() + "' found" ); } - - Specification spec = new Specification() { - @Override - public Predicate toPredicate(Root root, CriteriaQuery q, CriteriaBuilder cb) { + 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()); - try { - Object rootInstance = rootClass.newInstance(); - PropertyUtils.setProperty(rootInstance, rootPk.getName(), getEntityKey(rootEntitySet.getEntityType(),rootPredicates)); - - final Predicate p = cb.and( - cb.equal( - root.get(pk), - getEntityKey(property.getType(),predicates)), - cb.equal( - root.get(fk), - rootInstance)); - - return p; - } - catch(Exception ex) { - throw new ODataRuntimeException(ex); - } - - } - }; - - // Read data from DB - EdmEntitySet relatedEntitySet = entitySetFromType(property.getType()); - EntityCollection data = new EntityCollection(); - - repo.findAll(spec) - .stream() - .forEach((entry) -> data.getEntities().add(entityMapper.map2entity(relatedEntitySet, entry))); - - // - - ODataSerializer serializer = odata.createSerializer(responseFormat); - - // 4th: Now serialize the content: transform from the EntitySet object to InputStream - EdmEntityType edmEntityType = relatedEntitySet.getEntityType(); - ContextURL contextUrl = ContextURL.with() - .entitySet(relatedEntitySet) - .build(); - - final String id = request.getRawBaseUri() + "/" + relatedEntitySet.getName(); - EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with() - .id(id) - .contextURL(contextUrl) - .build(); - SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, edmEntityType, data, opts); - InputStream serializedContent = serializerResult.getContent(); - - - return serializedContent; - } - - - /** - * This method returns a speficic entity given its primary key - * @param edmEntitySet - * @param keyPredicates - * @return - */ - protected Entity readEntityData(EdmEntitySet edmEntitySet, List keyPredicates) throws ODataApplicationException { - - Object jpaEntry = readJPAEntity(edmEntitySet, keyPredicates); - Entity e = entityMapper.map2entity(edmEntitySet, jpaEntry); - return e; - } - - 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; + EdmEntitySet relatedEntitySet = entitySetFromType(property.getType()); + Entity e = entityMapper.map2entity(relatedEntitySet, related); + return serializeEntity(relatedEntitySet,e,responseFormat); + } + finally { + em.close(); + } } - private Object getEntityKey(EdmEntityType type, List keyPredicates) { +// @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"); 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 index 20981fdfef..e3bb172e3a 100644 --- 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 @@ -5,23 +5,25 @@ 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<>(); + private Map> repositoriesByClassName = new HashMap<>(); public RepositoryRegistry(List> allRepositories) { - allRepositories.stream().forEach((r) -> - repositoriesByClassName.put(r.getEdmEntityName(),(EdmEntityRepository)r)); + allRepositories.stream() + .forEach((r) -> + repositoriesByClassName.put(r.getEdmEntityName(),(JpaRepository)r)); } - public EdmEntityRepository getRepositoryForEntity(EdmEntityType entityType) { - EdmEntityRepository repo = repositoriesByClassName.get(entityType.getName()); + 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 index e4742b4fbb..02c7fe5c4d 100644 --- a/apache-olingo/olingo4/src/main/resources/application.properties +++ b/apache-olingo/olingo4/src/main/resources/application.properties @@ -4,6 +4,6 @@ server: spring: jpa: show-sql: true - open-in-view: false + open-in-view: true hibernate: ddl-auto: update From 8372ad4a379d45eb9f0f0f6e44efc443bee1cde7 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Fri, 26 Apr 2019 00:39:53 +0530 Subject: [PATCH 12/31] [BAEL-14118] - Make sure the tutorials build doesn't generate any un-committed or un-ignored artifacts --- .gitignore | 3 +- core-groovy/.gitignore | 1 + .../src/main/resources/ioSerializedObject.txt | Bin 199 -> 0 bytes .../baeldung/io/DataAndObjectsUnitTest.groovy | 4 +- jackson-2/.gitignore | 5 +- .../jhipster-microservice/car-app/pom.xml | 166 ++++++++--------- .../jhipster-microservice/dealer-app/pom.xml | 164 ++++++++--------- .../jhipster-microservice/gateway-app/pom.xml | 172 +++++++++--------- testing-modules/groovy-spock/.gitignore | 1 + 9 files changed, 262 insertions(+), 254 deletions(-) create mode 100644 core-groovy/.gitignore delete mode 100644 core-groovy/src/main/resources/ioSerializedObject.txt create mode 100644 testing-modules/groovy-spock/.gitignore diff --git a/.gitignore b/.gitignore index b981a473f6..50cb889e5b 100644 --- a/.gitignore +++ b/.gitignore @@ -76,4 +76,5 @@ persistence-modules/hibernate5/transaction.log apache-avro/src/main/java/com/baeldung/avro/model/ jta/transaction-logs/ software-security/sql-injection-samples/derby.log -spring-soap/src/main/java/com/baeldung/springsoap/gen/ \ No newline at end of file +spring-soap/src/main/java/com/baeldung/springsoap/gen/ +/report-*.json \ No newline at end of file diff --git a/core-groovy/.gitignore b/core-groovy/.gitignore new file mode 100644 index 0000000000..09220fdf52 --- /dev/null +++ b/core-groovy/.gitignore @@ -0,0 +1 @@ +/src/main/resources/ioSerializedObject.txt \ No newline at end of file diff --git a/core-groovy/src/main/resources/ioSerializedObject.txt b/core-groovy/src/main/resources/ioSerializedObject.txt deleted file mode 100644 index 833ed32bf128ecf8d2d6b6893b3959bc3c4bf8a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 199 zcmZ4UmVvdnh(RPdKUXg)F*PTpG%sB*GhZ(xu{itSp^g0yHl1)~Vqo!PU@I<3EGaGa zVc + def serializedDataFile = new File('src/main/resources/ioSerializedObject.txt') + serializedDataFile.createNewFile() + serializedDataFile.withObjectOutputStream { out -> out.writeObject(task) } diff --git a/jackson-2/.gitignore b/jackson-2/.gitignore index 83c05e60c8..4b1cfaf098 100644 --- a/jackson-2/.gitignore +++ b/jackson-2/.gitignore @@ -10,4 +10,7 @@ # Packaged files # *.jar *.war -*.ear \ No newline at end of file +*.ear + +# Files +/src/main/resources/orderOutput.yaml \ No newline at end of file diff --git a/jhipster/jhipster-microservice/car-app/pom.xml b/jhipster/jhipster-microservice/car-app/pom.xml index 529877d448..86d94d0a44 100644 --- a/jhipster/jhipster-microservice/car-app/pom.xml +++ b/jhipster/jhipster-microservice/car-app/pom.xml @@ -1,21 +1,100 @@ 4.0.0 - com.car.app - car-app - car-app - war jhipster-microservice com.baeldung.jhipster 1.0.0-SNAPSHOT + com.car.app + car-app + war + car-app ${maven.version} + + -Djava.security.egd=file:/dev/./urandom -Xmx256m + 3.6.2 + 2.0.0 + 2.5 + 3.5 + 0.4.13 + 1.2 + 5.2.8.Final + 2.6.0 + 0.7.9 + 1.8 + 3.21.0-GA + 1.0.0 + 1.1.0 + 0.7.0 + 3.6 + 2.0.0 + 3.6.2 + 4.8 + jdt_apt + 1.1.0.Final + 2.10 + 1.4.1 + 3.0.1 + yyyyMMddHHmmss + 3.0.0 + 3.1.3 + v6.10.0 + + + + + ${project.build.directory}/test-results + 0.0.20 + false + 3.2.2 + 2.12.1 + 3.2 + + src/main/webapp/content/**/*.*, src/main/webapp/bower_components/**/*.*, src/main/webapp/i18n/*.js, target/www/**/*.* + + S3437,UndocumentedApi,BoldAndItalicTagsCheck + + + src/main/webapp/app/**/*.* + Web:BoldAndItalicTagsCheck + + src/main/java/**/* + squid:S3437 + + src/main/java/**/* + squid:UndocumentedApi + + ${project.testresult.directory}/coverage/jacoco/jacoco-it.exec + ${project.testresult.directory}/coverage/jacoco/jacoco.exec + jacoco + + ${project.testresult.directory}/karma + + ${project.testresult.directory}/coverage/report-lcov/lcov.info + + ${project.testresult.directory}/coverage/report-lcov/lcov.info + + ${project.basedir}/src/main/ + ${project.testresult.directory}/surefire-reports + ${project.basedir}/src/test/ + + 2.5.0 + + Camden.SR5 + 2.6.1 + 1.4.10.Final + 1.1.0.Final + v0.21.3 + + @@ -819,83 +898,4 @@ - - -Djava.security.egd=file:/dev/./urandom -Xmx256m - 3.6.2 - 2.0.0 - 2.5 - 3.5 - 0.4.13 - 1.2 - 5.2.8.Final - 2.6.0 - 0.7.9 - 1.8 - 3.21.0-GA - 1.0.0 - 1.1.0 - 0.7.0 - 3.6 - 2.0.0 - 3.6.2 - 4.8 - jdt_apt - 1.1.0.Final - 2.10 - 1.4.1 - 3.0.1 - yyyyMMddHHmmss - 3.0.0 - 3.1.3 - v6.10.0 - - - - - ${project.build.directory}/test-results - 0.0.20 - false - 3.2.2 - 2.12.1 - 3.2 - - src/main/webapp/content/**/*.*, src/main/webapp/bower_components/**/*.*, src/main/webapp/i18n/*.js, target/www/**/*.* - - S3437,UndocumentedApi,BoldAndItalicTagsCheck - - - src/main/webapp/app/**/*.* - Web:BoldAndItalicTagsCheck - - src/main/java/**/* - squid:S3437 - - src/main/java/**/* - squid:UndocumentedApi - - ${project.testresult.directory}/coverage/jacoco/jacoco-it.exec - ${project.testresult.directory}/coverage/jacoco/jacoco.exec - jacoco - - ${project.testresult.directory}/karma - - ${project.testresult.directory}/coverage/report-lcov/lcov.info - - ${project.testresult.directory}/coverage/report-lcov/lcov.info - - ${project.basedir}/src/main/ - ${project.testresult.directory}/surefire-reports - ${project.basedir}/src/test/ - - 2.5.0 - - Camden.SR5 - 2.6.1 - 1.4.10.Final - 1.1.0.Final - v0.21.3 - - diff --git a/jhipster/jhipster-microservice/dealer-app/pom.xml b/jhipster/jhipster-microservice/dealer-app/pom.xml index 1eac8a930e..3051399ae6 100644 --- a/jhipster/jhipster-microservice/dealer-app/pom.xml +++ b/jhipster/jhipster-microservice/dealer-app/pom.xml @@ -1,21 +1,99 @@ 4.0.0 - com.dealer.app - dealer-app - dealer-app - war jhipster-microservice com.baeldung.jhipster 1.0.0-SNAPSHOT + com.dealer.app + dealer-app + war + dealer-app ${maven.version} + + -Djava.security.egd=file:/dev/./urandom -Xmx256m + 3.6.2 + 2.0.0 + 2.5 + 3.5 + 0.4.13 + 1.2 + 5.2.8.Final + 2.6.0 + 0.7.9 + 3.21.0-GA + 1.0.0 + 1.1.0 + 0.7.0 + 3.6 + 2.0.0 + 3.6.2 + 4.8 + jdt_apt + 1.1.0.Final + 2.10 + 1.4.1 + 3.0.1 + yyyyMMddHHmmss + 3.0.0 + 3.1.3 + v6.10.0 + + + + + ${project.build.directory}/test-results + 0.0.20 + false + 3.2.2 + 2.12.1 + 3.2 + + src/main/webapp/content/**/*.*, src/main/webapp/bower_components/**/*.*, src/main/webapp/i18n/*.js, target/www/**/*.* + + S3437,UndocumentedApi,BoldAndItalicTagsCheck + + + src/main/webapp/app/**/*.* + Web:BoldAndItalicTagsCheck + + src/main/java/**/* + squid:S3437 + + src/main/java/**/* + squid:UndocumentedApi + + ${project.testresult.directory}/coverage/jacoco/jacoco-it.exec + ${project.testresult.directory}/coverage/jacoco/jacoco.exec + jacoco + + ${project.testresult.directory}/karma + + ${project.testresult.directory}/coverage/report-lcov/lcov.info + + ${project.testresult.directory}/coverage/report-lcov/lcov.info + + ${project.basedir}/src/main/ + ${project.testresult.directory}/surefire-reports + ${project.basedir}/src/test/ + + 2.5.0 + + Camden.SR5 + 2.6.1 + 1.4.10.Final + 1.1.0.Final + v0.21.3 + + @@ -813,83 +891,5 @@ - - - -Djava.security.egd=file:/dev/./urandom -Xmx256m - 3.6.2 - 2.0.0 - 2.5 - 3.5 - 0.4.13 - 1.2 - 5.2.8.Final - 2.6.0 - 0.7.9 - 3.21.0-GA - 1.0.0 - 1.1.0 - 0.7.0 - 3.6 - 2.0.0 - 3.6.2 - 4.8 - jdt_apt - 1.1.0.Final - 2.10 - 1.4.1 - 3.0.1 - yyyyMMddHHmmss - 3.0.0 - 3.1.3 - v6.10.0 - - - - - ${project.build.directory}/test-results - 0.0.20 - false - 3.2.2 - 2.12.1 - 3.2 - src/main/webapp/content/**/*.*, src/main/webapp/bower_components/**/*.*, src/main/webapp/i18n/*.js, target/www/**/*.* - - S3437,UndocumentedApi,BoldAndItalicTagsCheck - - - src/main/webapp/app/**/*.* - Web:BoldAndItalicTagsCheck - - src/main/java/**/* - squid:S3437 - - src/main/java/**/* - squid:UndocumentedApi - - ${project.testresult.directory}/coverage/jacoco/jacoco-it.exec - ${project.testresult.directory}/coverage/jacoco/jacoco.exec - jacoco - - ${project.testresult.directory}/karma - - ${project.testresult.directory}/coverage/report-lcov/lcov.info - - ${project.testresult.directory}/coverage/report-lcov/lcov.info - - ${project.basedir}/src/main/ - ${project.testresult.directory}/surefire-reports - ${project.basedir}/src/test/ - - 2.5.0 - - Camden.SR5 - 2.6.1 - 1.4.10.Final - 1.1.0.Final - v0.21.3 - - diff --git a/jhipster/jhipster-microservice/gateway-app/pom.xml b/jhipster/jhipster-microservice/gateway-app/pom.xml index babc9e4f24..4e2c19ed2d 100644 --- a/jhipster/jhipster-microservice/gateway-app/pom.xml +++ b/jhipster/jhipster-microservice/gateway-app/pom.xml @@ -1,21 +1,103 @@ 4.0.0 - com.gateway - gateway-app - gateway-app - war jhipster-microservice com.baeldung.jhipster 1.0.0-SNAPSHOT + com.gateway + gateway-app + war + gateway-app ${maven.version} + + -Djava.security.egd=file:/dev/./urandom -Xmx256m + 3.6.2 + 2.0.0 + 3.6.0 + 1.10 + 2.5 + 3.5 + 0.4.13 + 1.3 + 1.2 + 5.2.8.Final + 2.6.0 + 0.7.9 + 3.21.0-GA + 1.0.0 + 1.1.0 + 0.7.0 + 3.6 + 2.0.0 + 3.6.2 + 4.8 + 1.3.0 + jdt_apt + 1.1.0.Final + 2.10 + 1.4.1 + 3.0.1 + yyyyMMddHHmmss + 3.0.0 + 3.1.3 + v6.10.0 + + + + + ${project.build.directory}/test-results + 0.0.20 + false + 3.2.2 + 2.12.1 + 3.2 + + src/main/webapp/content/**/*.*, src/main/webapp/bower_components/**/*.*, src/main/webapp/i18n/*.js, target/www/**/*.* + + S3437,UndocumentedApi,BoldAndItalicTagsCheck + + + src/main/webapp/app/**/*.* + Web:BoldAndItalicTagsCheck + + src/main/java/**/* + squid:S3437 + + src/main/java/**/* + squid:UndocumentedApi + + ${project.testresult.directory}/coverage/jacoco/jacoco-it.exec + ${project.testresult.directory}/coverage/jacoco/jacoco.exec + jacoco + + ${project.testresult.directory}/karma + + ${project.testresult.directory}/coverage/report-lcov/lcov.info + + ${project.testresult.directory}/coverage/report-lcov/lcov.info + + ${project.basedir}/src/main/ + ${project.testresult.directory}/surefire-reports + ${project.basedir}/src/test/ + + 2.5.0 + + Camden.SR5 + 2.6.1 + 1.4.10.Final + 1.1.0.Final + v0.21.3 + + @@ -925,87 +1007,5 @@ - - - -Djava.security.egd=file:/dev/./urandom -Xmx256m - 3.6.2 - 2.0.0 - 3.6.0 - 1.10 - 2.5 - 3.5 - 0.4.13 - 1.3 - 1.2 - 5.2.8.Final - 2.6.0 - 0.7.9 - 3.21.0-GA - 1.0.0 - 1.1.0 - 0.7.0 - 3.6 - 2.0.0 - 3.6.2 - 4.8 - 1.3.0 - jdt_apt - 1.1.0.Final - 2.10 - 1.4.1 - 3.0.1 - yyyyMMddHHmmss - 3.0.0 - 3.1.3 - v6.10.0 - - - - - ${project.build.directory}/test-results - 0.0.20 - false - 3.2.2 - 2.12.1 - 3.2 - - src/main/webapp/content/**/*.*, src/main/webapp/bower_components/**/*.*, src/main/webapp/i18n/*.js, target/www/**/*.* - - S3437,UndocumentedApi,BoldAndItalicTagsCheck - - - src/main/webapp/app/**/*.* - Web:BoldAndItalicTagsCheck - - src/main/java/**/* - squid:S3437 - - src/main/java/**/* - squid:UndocumentedApi - - ${project.testresult.directory}/coverage/jacoco/jacoco-it.exec - ${project.testresult.directory}/coverage/jacoco/jacoco.exec - jacoco - - ${project.testresult.directory}/karma - - ${project.testresult.directory}/coverage/report-lcov/lcov.info - - ${project.testresult.directory}/coverage/report-lcov/lcov.info - - ${project.basedir}/src/main/ - ${project.testresult.directory}/surefire-reports - ${project.basedir}/src/test/ - - 2.5.0 - - Camden.SR5 - 2.6.1 - 1.4.10.Final - 1.1.0.Final - v0.21.3 - diff --git a/testing-modules/groovy-spock/.gitignore b/testing-modules/groovy-spock/.gitignore new file mode 100644 index 0000000000..37118ef42c --- /dev/null +++ b/testing-modules/groovy-spock/.gitignore @@ -0,0 +1 @@ +/report-*.json \ No newline at end of file From 21b43b0f1184a9d463bcf810c421e0654bd5b604 Mon Sep 17 00:00:00 2001 From: mikr Date: Mon, 6 May 2019 00:12:00 +0200 Subject: [PATCH 13/31] BAEL-2580 JVM Platform Annotations in Kotlin - added Unit Test --- .../com/baeldung/jvmannotations/Document.kt | 8 ++------ .../kotlin/com/baeldung/range/DocumentTest.kt | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/range/DocumentTest.kt diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/Document.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/Document.kt index 3f9922b88b..f66f8fbae0 100644 --- a/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/Document.kt +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/jvmannotations/Document.kt @@ -5,6 +5,8 @@ import java.util.* interface Document { @JvmDefault + fun getTypeDefault() = "document" + fun getType() = "document" } @@ -23,9 +25,3 @@ class TextDocument : Document { } class XmlDocument(d : Document) : Document by d - -fun main() { - val myDocument = TextDocument() - val myTextDocument = XmlDocument(myDocument) - println("${myDocument.getType()} ${myTextDocument.getType()}") -} diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/DocumentTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/DocumentTest.kt new file mode 100644 index 0000000000..449e009104 --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/DocumentTest.kt @@ -0,0 +1,18 @@ +package com.baeldung.range + +import org.junit.Test +import kotlin.test.assertEquals + +class DocumentTest { + + @Test + fun testDefaultMethod() { + + val myDocument = TextDocument() + val myTextDocument = XmlDocument(myDocument) + + assertEquals("text", myDocument.getType()) + assertEquals("text", myTextDocument.getType()) + assertEquals("document", myTextDocument.getTypeDefault()) + } +} \ No newline at end of file From 4d85678e968074b6b52870cf6553c5ac3f52e582 Mon Sep 17 00:00:00 2001 From: Hamed Mirzaei Date: Tue, 7 May 2019 10:22:42 +0430 Subject: [PATCH 14/31] To enable multiple execution of a job with the same parameters --- spring-batch/src/main/java/org/baeldung/batch/App.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/spring-batch/src/main/java/org/baeldung/batch/App.java b/spring-batch/src/main/java/org/baeldung/batch/App.java index cea4e8d486..8bf58e65d2 100644 --- a/spring-batch/src/main/java/org/baeldung/batch/App.java +++ b/spring-batch/src/main/java/org/baeldung/batch/App.java @@ -3,6 +3,7 @@ package org.baeldung.batch; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -21,7 +22,11 @@ public class App { final Job job = (Job) context.getBean("firstBatchJob"); System.out.println("Starting the batch job"); try { - final JobExecution execution = jobLauncher.run(job, new JobParameters()); + // To enable multiple execution of a job with the same parameters + JobParameters jobParameters = new JobParametersBuilder() + .addString("jobID", String.valueOf(System.currentTimeMillis())) + .toJobParameters(); + final JobExecution execution = jobLauncher.run(job, jobParameters); System.out.println("Job Status : " + execution.getStatus()); System.out.println("Job succeeded"); } catch (final Exception e) { From 26f6585a19db17f9709ca028fc288093c7db9c8e Mon Sep 17 00:00:00 2001 From: Philippe Date: Tue, 7 May 2019 23:57:54 -0300 Subject: [PATCH 15/31] [BAEL-1219] Add Sample URLs --- apache-olingo/Samples.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 apache-olingo/Samples.md 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| + + + + + + From 6824bfa4972fca771393acd3cd2174219256ec3f Mon Sep 17 00:00:00 2001 From: Guilherme Lima Date: Thu, 9 May 2019 14:34:03 -0300 Subject: [PATCH 16/31] Updating javadoc --- .../java/org/baeldung/web/util/RestPreconditions.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java b/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java index 4e211ccb10..4f2dedcfa0 100644 --- a/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java +++ b/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java @@ -31,11 +31,11 @@ public final class RestPreconditions { /** * Check if some value was found, otherwise throw exception. - * - * @param expression - * has value true if found, otherwise false + * + * @param resource + * has value not null to be returned, otherwise throw exception * @throws MyResourceNotFoundException - * if expression is false, means value not found. + * if resource is null, means value not found. */ public static T checkFound(final T resource) { if (resource == null) { From f833bc18d161b6b737488d6b375c29a467833835 Mon Sep 17 00:00:00 2001 From: Philippe Date: Sat, 11 May 2019 21:21:18 -0300 Subject: [PATCH 17/31] [BAEL-2894] Minor formatting --- apache-olingo/olingo2/pom.xml | 10 ---- apache-olingo/olingo4/pom.xml | 14 +++--- .../examples/olingo4/edm/JpaEdmProvider.java | 47 +++++++++---------- 3 files changed, 30 insertions(+), 41 deletions(-) diff --git a/apache-olingo/olingo2/pom.xml b/apache-olingo/olingo2/pom.xml index 4fc81e5e49..493d34119e 100644 --- a/apache-olingo/olingo2/pom.xml +++ b/apache-olingo/olingo2/pom.xml @@ -68,16 +68,6 @@ - - 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 diff --git a/apache-olingo/olingo4/pom.xml b/apache-olingo/olingo4/pom.xml index 794aee0711..6323db413a 100644 --- a/apache-olingo/olingo4/pom.xml +++ b/apache-olingo/olingo4/pom.xml @@ -53,16 +53,16 @@ spring-boot-starter-web - - org.apache.olingo - odata-server-api - ${odata.version} - org.apache.olingo odata-server-core ${odata.version} - runtime + + commons-beanutils commons-beanutils 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 index 4cd979e931..585aecfa84 100644 --- 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 @@ -192,7 +192,7 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider { List properties = et.getDeclaredSingularAttributes() .stream() .filter(attr -> attr.getPersistentAttributeType() == PersistentAttributeType.BASIC) - .map(attr -> buildBasicAttribute(et, attr)) + .map(attr -> buildBasicAttribute(attr)) .collect(Collectors.toList()); result.setProperties(properties); @@ -201,24 +201,25 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider { List ids = et.getDeclaredSingularAttributes() .stream() .filter(attr -> attr.getPersistentAttributeType() == PersistentAttributeType.BASIC && attr.isId()) - .map(attr -> buildRefAttribute(et, attr)) + .map(attr -> buildRefAttribute(attr)) .collect(Collectors.toList()); result.setKey(ids); // Process 1:N navs List navs = et.getDeclaredPluralAttributes() - .stream() - .map(attr -> buildNavAttribute(et, attr)) - .collect(Collectors.toList()); + .stream() + .filter(attr -> attr.isAssociation()) + .map(attr -> buildNavAttribute(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()); + .stream() + .filter(attr -> attr.getPersistentAttributeType() == PersistentAttributeType.MANY_TO_ONE) + .map(attr -> buildMany2OneNavAttribute(attr)) + .collect(Collectors.toList()); result.getNavigationProperties().addAll(navs2); @@ -226,42 +227,40 @@ public class JpaEdmProvider extends CsdlAbstractEdmProvider { return result; } - private CsdlProperty buildBasicAttribute(EntityType et, SingularAttribute attr) { + private CsdlProperty buildBasicAttribute(SingularAttribute attr) { CsdlProperty p = new CsdlProperty().setName(attr.getName()) - .setType(typeMapper.java2edm(attr.getJavaType()) - .getFullQualifiedName()) - .setNullable(et.getDeclaredSingularAttribute(attr.getName()) - .isOptional()); + .setType(typeMapper.java2edm(attr.getJavaType()) + .getFullQualifiedName()) + .setNullable(attr.isOptional()); return p; } - private CsdlPropertyRef buildRefAttribute(EntityType et, SingularAttribute attr) { + private CsdlPropertyRef buildRefAttribute(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) { + private CsdlNavigationProperty buildNavAttribute(PluralAttribute attr) { CsdlNavigationProperty p = new CsdlNavigationProperty().setName(attr.getName()) - .setType(new FullQualifiedName(NAMESPACE, attr.getBindableJavaType().getSimpleName())) - .setCollection(true) - .setNullable(false); + .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) { + private CsdlNavigationProperty buildMany2OneNavAttribute(SingularAttribute attr) { CsdlNavigationProperty p = new CsdlNavigationProperty().setName(attr.getName()) - .setType(new FullQualifiedName(NAMESPACE, attr.getBindableJavaType().getSimpleName())) - .setCollection(false) - .setNullable(attr.isOptional()); + .setType(new FullQualifiedName(NAMESPACE, attr.getBindableJavaType().getSimpleName())) + .setCollection(false) + .setNullable(attr.isOptional()); return p; } From b83362799dbda6d758ba7277f0c8c37883b3fcee Mon Sep 17 00:00:00 2001 From: Philippe Date: Sun, 12 May 2019 17:09:09 -0300 Subject: [PATCH 18/31] [BAEL-2894] remove Lombok --- apache-olingo/olingo2/pom.xml | 5 - .../examples/olingo2/domain/CarMaker.java | 105 +++++++++++-- .../examples/olingo2/domain/CarModel.java | 145 ++++++++++++++++-- apache-olingo/olingo4/pom.xml | 5 - .../olingo4/ODataHttpHandlerFactoryImpl.java | 42 +++-- .../examples/olingo4/domain/CarMaker.java | 105 +++++++++++-- .../examples/olingo4/domain/CarModel.java | 145 ++++++++++++++++-- 7 files changed, 482 insertions(+), 70 deletions(-) diff --git a/apache-olingo/olingo2/pom.xml b/apache-olingo/olingo2/pom.xml index 493d34119e..1efd4ea602 100644 --- a/apache-olingo/olingo2/pom.xml +++ b/apache-olingo/olingo2/pom.xml @@ -44,11 +44,6 @@ spring-boot-configuration-processor true - - org.projectlombok - lombok - true - org.springframework.boot spring-boot-starter-test 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 index 42a3eaa59d..e66d266062 100644 --- 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 @@ -12,25 +12,104 @@ import javax.persistence.OneToMany; import javax.persistence.Table; import javax.validation.constraints.NotNull; -import lombok.Data; - @Entity -@Data -@Table(name="car_maker") +@Table(name = "car_maker") public class CarMaker { - + @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - + @NotNull - @Column(name="name") + @Column(name = "name") private String name; - - @OneToMany(mappedBy="maker", - orphanRemoval = true, - cascade=CascadeType.ALL) + + @OneToMany(mappedBy = "maker", orphanRemoval = true, cascade = CascadeType.ALL) private List models; - + + /** + * @return the id + */ + public Long getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the models + */ + public List getModels() { + return models; + } + + /** + * @param models the models to set + */ + public void setModels(List models) { + this.models = models; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((models == null) ? 0 : models.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CarMaker other = (CarMaker) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (models == null) { + if (other.models != null) + return false; + } else if (!models.equals(other.models)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } } 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 index a4f2a04f6e..f9f563e01e 100644 --- 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 @@ -1,6 +1,5 @@ package org.baeldung.examples.olingo2.domain; - import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; @@ -11,28 +10,150 @@ import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.validation.constraints.NotNull; -import lombok.Data; - @Entity -@Data -@Table(name="car_model") +@Table(name = "car_model") public class CarModel { @Id - @GeneratedValue(strategy=GenerationType.AUTO) + @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") + + @ManyToOne(optional = false, fetch = FetchType.LAZY) + @JoinColumn(name = "maker_fk") private CarMaker maker; + /** + * @return the id + */ + public Long getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the year + */ + public Integer getYear() { + return year; + } + + /** + * @param year the year to set + */ + public void setYear(Integer year) { + this.year = year; + } + + /** + * @return the sku + */ + public String getSku() { + return sku; + } + + /** + * @param sku the sku to set + */ + public void setSku(String sku) { + this.sku = sku; + } + + /** + * @return the maker + */ + public CarMaker getMaker() { + return maker; + } + + /** + * @param maker the maker to set + */ + public void setMaker(CarMaker maker) { + this.maker = maker; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((maker == null) ? 0 : maker.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((sku == null) ? 0 : sku.hashCode()); + result = prime * result + ((year == null) ? 0 : year.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CarModel other = (CarModel) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (maker == null) { + if (other.maker != null) + return false; + } else if (!maker.equals(other.maker)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (sku == null) { + if (other.sku != null) + return false; + } else if (!sku.equals(other.sku)) + return false; + if (year == null) { + if (other.year != null) + return false; + } else if (!year.equals(other.year)) + return false; + return true; + } + } diff --git a/apache-olingo/olingo4/pom.xml b/apache-olingo/olingo4/pom.xml index 6323db413a..3a93a6fa45 100644 --- a/apache-olingo/olingo4/pom.xml +++ b/apache-olingo/olingo4/pom.xml @@ -38,11 +38,6 @@ runtime - - org.projectlombok - lombok - true - org.springframework.boot spring-boot-starter-test 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 index 68d39dc052..e5d4d06a95 100644 --- 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 @@ -9,17 +9,13 @@ 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) { + public ODataHttpHandlerFactoryImpl(ODataFactory odataFactory, CsdlEdmProvider edmProvider, List processors) { this.odataFactory = odataFactory; this.edmProvider = edmProvider; this.processors = processors; @@ -27,16 +23,42 @@ public class ODataHttpHandlerFactoryImpl implements ODataHttpHandlerFactory { @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; } + public static class ODataHttpHandlerFactoryImplBuilder { + + private ODataFactory odataFactory; + private CsdlEdmProvider edmProvider; + private List processors; + + public ODataHttpHandlerFactoryImplBuilder odataFactory(ODataFactory odataFactory) { + this.odataFactory = odataFactory; + return this; + } + + public ODataHttpHandlerFactoryImplBuilder edmProvider(CsdlEdmProvider edmProvider) { + this.edmProvider = edmProvider; + return this; + } + + public ODataHttpHandlerFactoryImplBuilder processors(List processors) { + this.processors = processors; + return this; + } + + public ODataHttpHandlerFactoryImpl build() { + return new ODataHttpHandlerFactoryImpl(odataFactory, edmProvider, processors); + } + + } + } 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 index 79825b4556..f1b793cbe9 100644 --- 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 @@ -12,25 +12,104 @@ import javax.persistence.OneToMany; import javax.persistence.Table; import javax.validation.constraints.NotNull; -import lombok.Data; - @Entity -@Data -@Table(name="car_maker") +@Table(name = "car_maker") public class CarMaker { - + @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - + @NotNull - @Column(name="name") + @Column(name = "name") private String name; - - @OneToMany(mappedBy="maker", - orphanRemoval = true, - cascade=CascadeType.ALL) + + @OneToMany(mappedBy = "maker", orphanRemoval = true, cascade = CascadeType.ALL) private List models; - + + /** + * @return the id + */ + public Long getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the models + */ + public List getModels() { + return models; + } + + /** + * @param models the models to set + */ + public void setModels(List models) { + this.models = models; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((models == null) ? 0 : models.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CarMaker other = (CarMaker) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (models == null) { + if (other.models != null) + return false; + } else if (!models.equals(other.models)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } } 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 index a9254e48b9..7652641d7e 100644 --- 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 @@ -1,6 +1,5 @@ package org.baeldung.examples.olingo4.domain; - import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; @@ -11,28 +10,150 @@ import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.validation.constraints.NotNull; -import lombok.Data; - @Entity -@Data -@Table(name="car_model") +@Table(name = "car_model") public class CarModel { @Id - @GeneratedValue(strategy=GenerationType.AUTO) + @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") + + @ManyToOne(optional = false, fetch = FetchType.EAGER) + @JoinColumn(name = "maker_fk") private CarMaker maker; + /** + * @return the id + */ + public Long getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the year + */ + public Integer getYear() { + return year; + } + + /** + * @param year the year to set + */ + public void setYear(Integer year) { + this.year = year; + } + + /** + * @return the sku + */ + public String getSku() { + return sku; + } + + /** + * @param sku the sku to set + */ + public void setSku(String sku) { + this.sku = sku; + } + + /** + * @return the maker + */ + public CarMaker getMaker() { + return maker; + } + + /** + * @param maker the maker to set + */ + public void setMaker(CarMaker maker) { + this.maker = maker; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((maker == null) ? 0 : maker.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((sku == null) ? 0 : sku.hashCode()); + result = prime * result + ((year == null) ? 0 : year.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CarModel other = (CarModel) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (maker == null) { + if (other.maker != null) + return false; + } else if (!maker.equals(other.maker)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (sku == null) { + if (other.sku != null) + return false; + } else if (!sku.equals(other.sku)) + return false; + if (year == null) { + if (other.year != null) + return false; + } else if (!year.equals(other.year)) + return false; + return true; + } + } From 350a93ea9d5570425ef9fa086777e9cacf265408 Mon Sep 17 00:00:00 2001 From: Philippe Date: Tue, 21 May 2019 01:03:22 -0300 Subject: [PATCH 19/31] [BAEL-2894] Use standard port --- apache-olingo/olingo2/src/main/resources/application.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apache-olingo/olingo2/src/main/resources/application.yml b/apache-olingo/olingo2/src/main/resources/application.yml index 21563a94fe..71df0c4166 100644 --- a/apache-olingo/olingo2/src/main/resources/application.yml +++ b/apache-olingo/olingo2/src/main/resources/application.yml @@ -1,5 +1,5 @@ server: - port: 8180 + port: 8080 spring: jersey: From b1c95c27163704af483a0d354393bbed6843997f Mon Sep 17 00:00:00 2001 From: Philippe Date: Tue, 21 May 2019 01:06:09 -0300 Subject: [PATCH 20/31] [BAEL-2894] Remove olingo4 module --- apache-olingo/olingo4/.gitignore | 29 -- apache-olingo/olingo4/pom.xml | 90 ------ .../examples/olingo4/DefaultODataFactory.java | 20 -- .../examples/olingo4/ODataFactory.java | 8 - .../olingo4/ODataHttpHandlerFactory.java | 8 - .../olingo4/ODataHttpHandlerFactoryImpl.java | 64 ---- .../olingo4/ODataServiceConfiguration.java | 35 -- .../examples/olingo4/ODataServlet.java | 38 --- .../olingo4/Olingo4SampleApplication.java | 13 - .../examples/olingo4/domain/CarMaker.java | 115 ------- .../examples/olingo4/domain/CarModel.java | 159 --------- .../examples/olingo4/edm/EdmTypeMapper.java | 46 --- .../examples/olingo4/edm/JpaEdmProvider.java | 268 --------------- .../JpaEntityCollectionProcessor.java | 161 ---------- .../olingo4/processor/JpaEntityMapper.java | 93 ------ .../olingo4/processor/JpaEntityProcessor.java | 304 ------------------ .../repository/CarMakerRepository.java | 16 - .../repository/CarModelRepository.java | 22 -- .../repository/EdmEntityRepository.java | 17 - .../repository/RepositoryRegistry.java | 29 -- .../src/main/resources/application.properties | 9 - .../olingo4/src/main/resources/data.sql | 12 - .../Olingo4SampleApplicationTests.java | 16 - 23 files changed, 1572 deletions(-) delete mode 100644 apache-olingo/olingo4/.gitignore delete mode 100644 apache-olingo/olingo4/pom.xml delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/DefaultODataFactory.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataFactory.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataHttpHandlerFactory.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataHttpHandlerFactoryImpl.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServiceConfiguration.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServlet.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/Olingo4SampleApplication.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/domain/CarMaker.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/domain/CarModel.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/EdmTypeMapper.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/JpaEdmProvider.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityCollectionProcessor.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityMapper.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityProcessor.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarMakerRepository.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarModelRepository.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/EdmEntityRepository.java delete mode 100644 apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/RepositoryRegistry.java delete mode 100644 apache-olingo/olingo4/src/main/resources/application.properties delete mode 100644 apache-olingo/olingo4/src/main/resources/data.sql delete mode 100644 apache-olingo/olingo4/src/test/java/org/baeldung/examples/olingo4/Olingo4SampleApplicationTests.java diff --git a/apache-olingo/olingo4/.gitignore b/apache-olingo/olingo4/.gitignore deleted file mode 100644 index 153c9335eb..0000000000 --- a/apache-olingo/olingo4/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -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 deleted file mode 100644 index 3a93a6fa45..0000000000 --- a/apache-olingo/olingo4/pom.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - 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.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-starter-web - - - - org.apache.olingo - odata-server-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 deleted file mode 100644 index 18f7f8ba24..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/DefaultODataFactory.java +++ /dev/null @@ -1,20 +0,0 @@ -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 deleted file mode 100644 index 9acb4b8c5e..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -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 deleted file mode 100644 index 27d0737c24..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataHttpHandlerFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -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 deleted file mode 100644 index e5d4d06a95..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataHttpHandlerFactoryImpl.java +++ /dev/null @@ -1,64 +0,0 @@ -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; - -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; - } - - public static class ODataHttpHandlerFactoryImplBuilder { - - private ODataFactory odataFactory; - private CsdlEdmProvider edmProvider; - private List processors; - - public ODataHttpHandlerFactoryImplBuilder odataFactory(ODataFactory odataFactory) { - this.odataFactory = odataFactory; - return this; - } - - public ODataHttpHandlerFactoryImplBuilder edmProvider(CsdlEdmProvider edmProvider) { - this.edmProvider = edmProvider; - return this; - } - - public ODataHttpHandlerFactoryImplBuilder processors(List processors) { - this.processors = processors; - return this; - } - - public ODataHttpHandlerFactoryImpl build() { - return new ODataHttpHandlerFactoryImpl(odataFactory, edmProvider, processors); - } - - } - -} 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 deleted file mode 100644 index 0cde665359..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServiceConfiguration.java +++ /dev/null @@ -1,35 +0,0 @@ -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 deleted file mode 100644 index c379124541..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/ODataServlet.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * - */ -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/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/Olingo4SampleApplication.java b/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/Olingo4SampleApplication.java deleted file mode 100644 index 1ac872ea0f..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/Olingo4SampleApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.baeldung.examples.olingo4; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class Olingo4SampleApplication { - - public static void main(String[] args) { - SpringApplication.run(Olingo4SampleApplication.class, args); - } - -} 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 deleted file mode 100644 index f1b793cbe9..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/domain/CarMaker.java +++ /dev/null @@ -1,115 +0,0 @@ -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; - -@Entity -@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; - - /** - * @return the id - */ - public Long getId() { - return id; - } - - /** - * @param id the id to set - */ - public void setId(Long id) { - this.id = id; - } - - /** - * @return the name - */ - public String getName() { - return name; - } - - /** - * @param name the name to set - */ - public void setName(String name) { - this.name = name; - } - - /** - * @return the models - */ - public List getModels() { - return models; - } - - /** - * @param models the models to set - */ - public void setModels(List models) { - this.models = models; - } - - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - result = prime * result + ((models == null) ? 0 : models.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - CarMaker other = (CarMaker) obj; - if (id == null) { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - if (models == null) { - if (other.models != null) - return false; - } else if (!models.equals(other.models)) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } - -} 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 deleted file mode 100644 index 7652641d7e..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/domain/CarModel.java +++ /dev/null @@ -1,159 +0,0 @@ -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; - -@Entity -@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; - - /** - * @return the id - */ - public Long getId() { - return id; - } - - /** - * @param id the id to set - */ - public void setId(Long id) { - this.id = id; - } - - /** - * @return the name - */ - public String getName() { - return name; - } - - /** - * @param name the name to set - */ - public void setName(String name) { - this.name = name; - } - - /** - * @return the year - */ - public Integer getYear() { - return year; - } - - /** - * @param year the year to set - */ - public void setYear(Integer year) { - this.year = year; - } - - /** - * @return the sku - */ - public String getSku() { - return sku; - } - - /** - * @param sku the sku to set - */ - public void setSku(String sku) { - this.sku = sku; - } - - /** - * @return the maker - */ - public CarMaker getMaker() { - return maker; - } - - /** - * @param maker the maker to set - */ - public void setMaker(CarMaker maker) { - this.maker = maker; - } - - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - result = prime * result + ((maker == null) ? 0 : maker.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((sku == null) ? 0 : sku.hashCode()); - result = prime * result + ((year == null) ? 0 : year.hashCode()); - return result; - } - - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - CarModel other = (CarModel) obj; - if (id == null) { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - if (maker == null) { - if (other.maker != null) - return false; - } else if (!maker.equals(other.maker)) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - if (sku == null) { - if (other.sku != null) - return false; - } else if (!sku.equals(other.sku)) - return false; - if (year == null) { - if (other.year != null) - return false; - } else if (!year.equals(other.year)) - return false; - return true; - } - -} 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 deleted file mode 100644 index 95797752a2..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/EdmTypeMapper.java +++ /dev/null @@ -1,46 +0,0 @@ -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 deleted file mode 100644 index 585aecfa84..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/edm/JpaEdmProvider.java +++ /dev/null @@ -1,268 +0,0 @@ -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(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(attr)) - .collect(Collectors.toList()); - - result.setKey(ids); - - // Process 1:N navs - List navs = et.getDeclaredPluralAttributes() - .stream() - .filter(attr -> attr.isAssociation()) - .map(attr -> buildNavAttribute(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 -> buildMany2OneNavAttribute(attr)) - .collect(Collectors.toList()); - - result.getNavigationProperties().addAll(navs2); - - - return result; - } - - private CsdlProperty buildBasicAttribute(SingularAttribute attr) { - - CsdlProperty p = new CsdlProperty().setName(attr.getName()) - .setType(typeMapper.java2edm(attr.getJavaType()) - .getFullQualifiedName()) - .setNullable(attr.isOptional()); - - return p; - } - - private CsdlPropertyRef buildRefAttribute(SingularAttribute attr) { - - CsdlPropertyRef p = new CsdlPropertyRef().setName(attr.getName()); - return p; - } - - // Build NavProperty for 1:N or M:N associations - private CsdlNavigationProperty buildNavAttribute(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 buildMany2OneNavAttribute(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 deleted file mode 100644 index 4a4e5026f3..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityCollectionProcessor.java +++ /dev/null @@ -1,161 +0,0 @@ -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 deleted file mode 100644 index 1978aa4fd6..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityMapper.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * - */ -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 deleted file mode 100644 index 719e5de160..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/processor/JpaEntityProcessor.java +++ /dev/null @@ -1,304 +0,0 @@ -/** - * - */ -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 deleted file mode 100644 index 1bde9f148c..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarMakerRepository.java +++ /dev/null @@ -1,16 +0,0 @@ -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 deleted file mode 100644 index 247bf6e77b..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/CarModelRepository.java +++ /dev/null @@ -1,22 +0,0 @@ -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 deleted file mode 100644 index dbfd0e6f93..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/EdmEntityRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -/** - * - */ -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 deleted file mode 100644 index e3bb172e3a..0000000000 --- a/apache-olingo/olingo4/src/main/java/org/baeldung/examples/olingo4/repository/RepositoryRegistry.java +++ /dev/null @@ -1,29 +0,0 @@ -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 deleted file mode 100644 index 02c7fe5c4d..0000000000 --- a/apache-olingo/olingo4/src/main/resources/application.properties +++ /dev/null @@ -1,9 +0,0 @@ -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 deleted file mode 100644 index 327f2688c5..0000000000 --- a/apache-olingo/olingo4/src/main/resources/data.sql +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 index 5d23a4148e..0000000000 --- a/apache-olingo/olingo4/src/test/java/org/baeldung/examples/olingo4/Olingo4SampleApplicationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -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() { - } - -} From a2e90642333c01f2547d1be9b5975d6a3053a34b Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Tue, 21 May 2019 21:24:57 +0300 Subject: [PATCH 21/31] Create README.MD --- core-java-modules/core-java-lambdas/README.MD | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 core-java-modules/core-java-lambdas/README.MD diff --git a/core-java-modules/core-java-lambdas/README.MD b/core-java-modules/core-java-lambdas/README.MD new file mode 100644 index 0000000000..31790ffbb1 --- /dev/null +++ b/core-java-modules/core-java-lambdas/README.MD @@ -0,0 +1,3 @@ +### Relevant Articles + +- [Why Do Local Variables Used in Lambdas Have to Be Final or Effectively Final?](https://www.baeldung.com/java-lambda-effectively-final-local-variables) From d939f2583785ad7d8094bfea60d26747cad6b592 Mon Sep 17 00:00:00 2001 From: Loredana Date: Tue, 21 May 2019 22:55:03 +0300 Subject: [PATCH 22/31] fix slf4j message issue --- .../com/baeldung/logging/slf4j/Slf4jLogger.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java b/core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java index df41e071fd..a5d6abeac7 100644 --- a/core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java +++ b/core-java-modules/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java @@ -4,6 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ResourceBundle; +import java.text.MessageFormat; public class Slf4jLogger implements System.Logger { @@ -74,26 +75,27 @@ public class Slf4jLogger implements System.Logger { if (!isLoggable(level)) { return; } + String message = MessageFormat.format (format, params); switch (level) { case TRACE: - logger.trace(format, params); + logger.trace(message); break; case DEBUG: - logger.debug(format, params); + logger.debug(message); break; case INFO: - logger.info(format, params); + logger.info(message); break; case WARNING: - logger.warn(format, params); + logger.warn(message); break; case ERROR: - logger.error(format, params); + logger.error(message); break; case ALL: default: - logger.info(format, params); + logger.info(message); } } } From af996eed8f7b65f3d376e0a18136f57c9e286530 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Thu, 23 May 2019 00:45:07 +0530 Subject: [PATCH 23/31] [BAEL-12898] - Moved WaysToIterateUnitTest to core-java-collection-list-2 module --- .../test/java/com/baeldung/java/list/WaysToIterateUnitTest.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core-java-modules/{core-java-collections-list => core-java-collections-list-2}/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java (100%) diff --git a/core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java b/core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java similarity index 100% rename from core-java-modules/core-java-collections-list/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java rename to core-java-modules/core-java-collections-list-2/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java From 910186e2d4b6b7600184af69d69ef8f8b2db5cac Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Thu, 23 May 2019 20:16:13 +0300 Subject: [PATCH 24/31] Update pom.xml --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 2cbd218fdc..bdd7562486 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,6 @@ pom - lombok-custom quarkus @@ -1562,4 +1561,4 @@ 1.16.12 1.4.197 - \ No newline at end of file + From ef9f687f687deddcbcc7d165eae77a5a9ae31d5d Mon Sep 17 00:00:00 2001 From: Abhishek Malik Date: Fri, 24 May 2019 08:48:32 +0530 Subject: [PATCH 25/31] rename variable and move underscore to front to simulate minus (#7010) --- .../numberformat/NumberFormatExceptionUnitTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 index a1e8c7c30f..cb26bf451a 100644 --- 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 @@ -36,7 +36,7 @@ public class NumberFormatExceptionUnitTest { @Test(expected = NumberFormatException.class) public void givenParseIntMethod_whenUnderscoreInInput_thenFail() { - int bIntPrim = Integer.parseInt("6_000"); + int bIntPrim = Integer.parseInt("_6000"); } @Test(expected = NumberFormatException.class) @@ -51,7 +51,7 @@ public class NumberFormatExceptionUnitTest { @Test(expected = NumberFormatException.class) public void givenDecodeMethod_whenAlphabetInInput_thenFail() { - Long decodeInteger = Long.decode("64403L"); + Long decodedLong = Long.decode("64403L"); } /* ---INTEGER PASS CASES--- */ @@ -72,7 +72,7 @@ public class NumberFormatExceptionUnitTest { int aIntPrim = Integer.parseInt("6000 ".trim()); assertEquals(6000, aIntPrim); - int bIntPrim = Integer.parseInt("6_000".replaceAll("_", "")); + int bIntPrim = Integer.parseInt("_6000".replaceAll("_", "")); assertEquals(6000, bIntPrim); int cIntPrim = Integer.parseInt("-6000"); From fd5afd015a4b818695e20c4e7163adaa1fe4d2d3 Mon Sep 17 00:00:00 2001 From: Laurentiu Delcea Date: Fri, 24 May 2019 08:20:09 +0300 Subject: [PATCH 26/31] BAEL-2924 Jersey request parameters (#7007) * BAEL-2924 Jersey request parameters * BAEL-2924 Jersey request parameters --- .../com/baeldung/jersey/server/ItemParam.java | 46 ++++++++++++++++ .../com/baeldung/jersey/server/Items.java | 49 +++++++++++++++++ .../server/http/EmbeddedHttpServer.java | 8 ++- .../baeldung/jersey/server/ItemsUnitTest.java | 52 +++++++++++++++++++ 4 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 jersey/src/main/java/com/baeldung/jersey/server/ItemParam.java create mode 100644 jersey/src/main/java/com/baeldung/jersey/server/Items.java create mode 100644 jersey/src/test/java/com/baeldung/jersey/server/ItemsUnitTest.java diff --git a/jersey/src/main/java/com/baeldung/jersey/server/ItemParam.java b/jersey/src/main/java/com/baeldung/jersey/server/ItemParam.java new file mode 100644 index 0000000000..0f60a20b92 --- /dev/null +++ b/jersey/src/main/java/com/baeldung/jersey/server/ItemParam.java @@ -0,0 +1,46 @@ +package com.baeldung.jersey.server; + +import javax.ws.rs.FormParam; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.PathParam; + +public class ItemParam { + + @HeaderParam("headerParam") + private String shopKey; + + @PathParam("pathParam") + private String itemId; + + @FormParam("formParam") + private String price; + + public String getShopKey() { + return shopKey; + } + + public void setShopKey(String shopKey) { + this.shopKey = shopKey; + } + + public String getItemId() { + return itemId; + } + + public void setItemId(String itemId) { + this.itemId = itemId; + } + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + @Override + public String toString() { + return "ItemParam{shopKey='" + shopKey + ", itemId='" + itemId + ", price='" + price + '}'; + } +} diff --git a/jersey/src/main/java/com/baeldung/jersey/server/Items.java b/jersey/src/main/java/com/baeldung/jersey/server/Items.java new file mode 100644 index 0000000000..c24e6820f5 --- /dev/null +++ b/jersey/src/main/java/com/baeldung/jersey/server/Items.java @@ -0,0 +1,49 @@ +package com.baeldung.jersey.server; + +import javax.ws.rs.*; + +@Path("items") +public class Items { + + @GET + @Path("/cookie") + public String readCookieParam(@CookieParam("cookieParamToRead") String cookieParamToRead) { + return "Cookie parameter value is [" + cookieParamToRead + "]"; + } + + @GET + @Path("/header") + public String readHeaderParam(@HeaderParam("headerParamToRead") String headerParamToRead) { + return "Header parameter value is [" + headerParamToRead + "]"; + } + + @GET + @Path("/path/{pathParamToRead}") + public String readPathParam(@PathParam("pathParamToRead") String pathParamToRead) { + return "Path parameter value is [" + pathParamToRead + "]"; + } + + @GET + @Path("/query") + public String readQueryParam(@QueryParam("queryParamToRead") String queryParamToRead) { + return "Query parameter value is [" + queryParamToRead + "]"; + } + + @POST + @Path("/form") + public String readFormParam(@FormParam("formParamToRead") String formParamToRead) { + return "Form parameter value is [" + formParamToRead + "]"; + } + + @GET + @Path("/matrix") + public String readMatrixParam(@MatrixParam("matrixParamToRead") String matrixParamToRead) { + return "Matrix parameter value is [" + matrixParamToRead + "]"; + } + + @POST + @Path("/bean/{pathParam}") + public String readBeanParam(@BeanParam ItemParam itemParam) { + return itemParam.toString(); + } +} \ No newline at end of file diff --git a/jersey/src/main/java/com/baeldung/jersey/server/http/EmbeddedHttpServer.java b/jersey/src/main/java/com/baeldung/jersey/server/http/EmbeddedHttpServer.java index 4afa086858..1d75508c6d 100644 --- a/jersey/src/main/java/com/baeldung/jersey/server/http/EmbeddedHttpServer.java +++ b/jersey/src/main/java/com/baeldung/jersey/server/http/EmbeddedHttpServer.java @@ -7,12 +7,13 @@ import java.util.logging.Logger; import org.glassfish.grizzly.http.server.HttpServer; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; +import org.glassfish.jersey.server.ResourceConfig; import com.baeldung.jersey.server.config.ViewApplicationConfig; public class EmbeddedHttpServer { - private static final URI BASE_URI = URI.create("http://localhost:8082/"); + public static final URI BASE_URI = URI.create("http://localhost:8082/"); public static void main(String[] args) { try { @@ -32,4 +33,9 @@ public class EmbeddedHttpServer { } } + + public static HttpServer startServer() { + final ResourceConfig rc = new ResourceConfig().packages("com.baeldung.jersey.server"); + return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI.toString()), rc); + } } diff --git a/jersey/src/test/java/com/baeldung/jersey/server/ItemsUnitTest.java b/jersey/src/test/java/com/baeldung/jersey/server/ItemsUnitTest.java new file mode 100644 index 0000000000..df85e26b76 --- /dev/null +++ b/jersey/src/test/java/com/baeldung/jersey/server/ItemsUnitTest.java @@ -0,0 +1,52 @@ +package com.baeldung.jersey.server; + +import static org.junit.Assert.assertEquals; + +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.WebTarget; + +import org.glassfish.grizzly.http.server.HttpServer; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.baeldung.jersey.server.http.EmbeddedHttpServer; + +public class ItemsUnitTest { + + private HttpServer server; + private WebTarget target; + + @Before + public void setUp() throws Exception { + server = EmbeddedHttpServer.startServer(); + target = ClientBuilder.newClient().target(EmbeddedHttpServer.BASE_URI.toString()); + } + + @After + public void tearDown() throws Exception { + server.stop(); + } + + @Test + public void givenCookieParameter_whenGet_thenReturnsExpectedText() { + String paramValue = "1"; + String responseText = target.path("items/cookie").request().cookie("cookieParamToRead", paramValue).get(String.class); + assertEquals("Cookie parameter value is [" + paramValue + "]", responseText); + } + + @Test + public void givenHeaderParameter_whenGet_thenReturnsExpectedText() { + String paramValue = "2"; + String responseText = target.path("items/header").request().header("headerParamToRead", paramValue).get(String.class); + assertEquals("Header parameter value is [" + paramValue + "]", responseText); + } + + @Test + public void givenPathParameter_whenGet_thenReturnsExpectedText() { + String paramValue = "3"; + String responseText = target.path("items/path/" + paramValue).request().get(String.class); + assertEquals("Path parameter value is [" + paramValue + "]", responseText); + } +} From 93dfb77f1f9e8e86631014bf23b3621cd8ebf390 Mon Sep 17 00:00:00 2001 From: dionisPrifti Date: Fri, 24 May 2019 18:10:52 +0200 Subject: [PATCH 27/31] Bael 2810 data jpa delete (#6759) * BAEL-2810: Finished the examples and unit tests. * BAEL-2810: Changed assertions to isEqualTo * BAEL-2810: Changed the test of the derived query to reflect the number of the deleted records --- .../datajpadelete/DeleteFromRepositoryUnitTest.java | 10 +++++----- .../datajpadelete/DeleteInRelationshipsUnitTest.java | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteFromRepositoryUnitTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteFromRepositoryUnitTest.java index 9e7e516735..5f4a36bc0e 100644 --- a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteFromRepositoryUnitTest.java +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteFromRepositoryUnitTest.java @@ -43,22 +43,22 @@ public class DeleteFromRepositoryUnitTest { public void whenDeleteByIdFromRepository_thenDeletingShouldBeSuccessful() { repository.deleteById(book1.getId()); - assertThat(repository.count() == 1).isTrue(); + assertThat(repository.count()).isEqualTo(1); } @Test public void whenDeleteAllFromRepository_thenRepositoryShouldBeEmpty() { repository.deleteAll(); - assertThat(repository.count() == 0).isTrue(); + assertThat(repository.count()).isEqualTo(0); } @Test @Transactional public void whenDeleteFromDerivedQuery_thenDeletingShouldBeSuccessful() { - repository.deleteByTitle("The Hobbit"); + long deletedRecords = repository.deleteByTitle("The Hobbit"); - assertThat(repository.count() == 1).isTrue(); + assertThat(deletedRecords).isEqualTo(1); } @Test @@ -66,7 +66,7 @@ public class DeleteFromRepositoryUnitTest { public void whenDeleteFromCustomQuery_thenDeletingShouldBeSuccessful() { repository.deleteBooks("The Hobbit"); - assertThat(repository.count() == 1).isTrue(); + assertThat(repository.count()).isEqualTo(1); } } \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteInRelationshipsUnitTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteInRelationshipsUnitTest.java index 56de8749b2..6275ace6e0 100644 --- a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteInRelationshipsUnitTest.java +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteInRelationshipsUnitTest.java @@ -46,15 +46,15 @@ public class DeleteInRelationshipsUnitTest { public void whenDeletingCategories_thenBooksShouldAlsoBeDeleted() { categoryRepository.deleteAll(); - assertThat(bookRepository.count() == 0).isTrue(); - assertThat(categoryRepository.count() == 0).isTrue(); + assertThat(bookRepository.count()).isEqualTo(0); + assertThat(categoryRepository.count()).isEqualTo(0); } @Test public void whenDeletingBooks_thenCategoriesShouldAlsoBeDeleted() { bookRepository.deleteAll(); - assertThat(bookRepository.count() == 0).isTrue(); - assertThat(categoryRepository.count() == 2).isTrue(); + assertThat(bookRepository.count()).isEqualTo(0); + assertThat(categoryRepository.count()).isEqualTo(2); } } \ No newline at end of file From d373336b74d9b70e5cee2144e406eb6d02c005bd Mon Sep 17 00:00:00 2001 From: binary-joe <48189951+binary-joe@users.noreply.github.com> Date: Fri, 24 May 2019 18:12:40 +0200 Subject: [PATCH 28/31] BAEL-2516 catching errors in catch block (#6761) --- .../com/baeldung/error/ErrorGenerator.java | 15 ++++++ .../error/ErrorGeneratorUnitTest.java | 51 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 core-java-lang/src/main/java/com/baeldung/error/ErrorGenerator.java create mode 100644 core-java-lang/src/test/java/com/baeldung/error/ErrorGeneratorUnitTest.java diff --git a/core-java-lang/src/main/java/com/baeldung/error/ErrorGenerator.java b/core-java-lang/src/main/java/com/baeldung/error/ErrorGenerator.java new file mode 100644 index 0000000000..58cbe22df5 --- /dev/null +++ b/core-java-lang/src/main/java/com/baeldung/error/ErrorGenerator.java @@ -0,0 +1,15 @@ +package com.baeldung.error; + +public class ErrorGenerator { + public void throwException() throws Exception { + throw new Exception("checked"); + } + + public void throwRuntimeException() { + throw new RuntimeException("unchecked"); + } + + public void throwError() { + throw new Error("unchecked"); + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/error/ErrorGeneratorUnitTest.java b/core-java-lang/src/test/java/com/baeldung/error/ErrorGeneratorUnitTest.java new file mode 100644 index 0000000000..2a7c24f5fa --- /dev/null +++ b/core-java-lang/src/test/java/com/baeldung/error/ErrorGeneratorUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.error; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class ErrorGeneratorUnitTest { + + private ErrorGenerator errorGenerator; + + @Before + public void setUp() { + errorGenerator = new ErrorGenerator(); + } + + @Test + public void whenCheckedException_thenIsCaughtByCatchException() { + try { + errorGenerator.throwException(); + } catch (Exception e) { + // caught! -> test pass + } + } + + @Test + public void whenUncheckedException_thenIsCaughtByCatchException() { + try { + errorGenerator.throwRuntimeException(); + } catch (Exception e) { + // caught! -> test pass + } + } + + @Test(expected = Error.class) + public void whenError_thenIsNotCaughtByCatchException() { + try { + errorGenerator.throwError(); + } catch (Exception e) { + Assert.fail(); // errors are not caught by catch exception + } + } + + @Test + public void whenError_thenIsCaughtByCatchError() { + try { + errorGenerator.throwError(); + } catch (Error e) { + // caught! -> test pass + } + } +} \ No newline at end of file From c90f76a4f83977f214c1630934e8959c122bd577 Mon Sep 17 00:00:00 2001 From: Graham Cox Date: Fri, 24 May 2019 17:24:47 +0100 Subject: [PATCH 29/31] Examples for Clojure Ring (#6881) --- clojure/ring/.gitignore | 12 +++++++++ clojure/ring/README.md | 16 ++++++++++++ clojure/ring/project.clj | 8 ++++++ clojure/ring/src/ring/core.clj | 48 ++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+) create mode 100644 clojure/ring/.gitignore create mode 100644 clojure/ring/README.md create mode 100644 clojure/ring/project.clj create mode 100644 clojure/ring/src/ring/core.clj diff --git a/clojure/ring/.gitignore b/clojure/ring/.gitignore new file mode 100644 index 0000000000..d18f225992 --- /dev/null +++ b/clojure/ring/.gitignore @@ -0,0 +1,12 @@ +/target +/classes +/checkouts +profiles.clj +pom.xml +pom.xml.asc +*.jar +*.class +/.lein-* +/.nrepl-port +.hgignore +.hg/ diff --git a/clojure/ring/README.md b/clojure/ring/README.md new file mode 100644 index 0000000000..3bc04ac129 --- /dev/null +++ b/clojure/ring/README.md @@ -0,0 +1,16 @@ +# Clojure Ring Examples + +This project acts as a set of examples for the Clojure Ring library. + +## Runing the examples + +The examples can all be run from the Leiningen REPL. + +Firstly, start the REPL with `lein repl`. Then the examples can be executed with: + +* `(run simple-handler)` - A simple handler that just echos a constant string to the client +* `(run check-ip-handler)` - A handler that echos the clients IP Address back to them +* `(run echo-handler)` - A handler that echos the value of the "input" parameter back +* `(run request-count-handler)` - A handler with a session that tracks how many times this session has requested this handler + +In all cases, the handlers can be accessed on http://localhost:3000. diff --git a/clojure/ring/project.clj b/clojure/ring/project.clj new file mode 100644 index 0000000000..7f2fcc4263 --- /dev/null +++ b/clojure/ring/project.clj @@ -0,0 +1,8 @@ +(defproject baeldung-ring "0.1.0-SNAPSHOT" + :dependencies [[org.clojure/clojure "1.10.0"] + [ring/ring-core "1.7.1"] + [ring/ring-jetty-adapter "1.7.1"] + [ring/ring-devel "1.7.1"]] + :plugins [[lein-ring "0.12.5"]] + :ring {:handler ring.core/simple-handler} + :repl-options {:init-ns ring.core}) diff --git a/clojure/ring/src/ring/core.clj b/clojure/ring/src/ring/core.clj new file mode 100644 index 0000000000..a56e2f2bde --- /dev/null +++ b/clojure/ring/src/ring/core.clj @@ -0,0 +1,48 @@ +(ns ring.core + (:use ring.adapter.jetty + [ring.middleware.content-type] + [ring.middleware.cookies] + [ring.middleware.params] + [ring.middleware.session] + [ring.middleware.session.cookie] + [ring.util.response])) + +;; Handler that just echos back the string "Hello World" +(defn simple-handler [request] + {:status 200 + :headers {"Content-Type" "text/plain"} + :body "Hello World"}) + +;; Handler that echos back the clients IP Address +;; This demonstrates building responses properly, and extracting values from the request +(defn check-ip-handler [request] + (content-type + (response (:remote-addr request)) + "text/plain")) + +;; Handler that echos back the incoming parameter "input" +;; This demonstrates middleware chaining and accessing parameters +(def echo-handler + (-> (fn [{params :params}] + (content-type + (response (get params "input")) + "text/plain")) + (wrap-params {:encoding "UTF-8"}) + )) + +;; Handler that keeps track of how many times each session has accessed the service +;; This demonstrates cookies and sessions +(def request-count-handler + (-> (fn [{session :session}] + (let [count (:count session 0) + session (assoc session :count (inc count))] + (-> (response (str "You accessed this page " count " times.")) + (assoc :session session)))) + wrap-cookies + (wrap-session {:cookie-attrs {:max-age 3600}}) + )) + +;; Run the provided handler on port 3000 +(defn run + [h] + (run-jetty h {:port 3000})) From b0c8a8473216d87c0223290a091db5d89aee1af2 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Fri, 24 May 2019 22:06:10 +0300 Subject: [PATCH 30/31] Update README.md --- testing-modules/junit-5-basics/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/testing-modules/junit-5-basics/README.md b/testing-modules/junit-5-basics/README.md index a00e2a3f4a..6e44a9c071 100644 --- a/testing-modules/junit-5-basics/README.md +++ b/testing-modules/junit-5-basics/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Get the Path of the /src/test/resources Directory in JUnit](https://www.baeldung.com/junit-src-test-resources-directory-path) +- [Tagging and Filtering JUnit Tests](https://www.baeldung.com/junit-filtering-tests) From 97358119cefe8142a14743c33af83cf898e9a292 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Fri, 24 May 2019 22:08:43 +0300 Subject: [PATCH 31/31] Update README.md --- clojure/ring/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clojure/ring/README.md b/clojure/ring/README.md index 3bc04ac129..20263c6b95 100644 --- a/clojure/ring/README.md +++ b/clojure/ring/README.md @@ -14,3 +14,6 @@ Firstly, start the REPL with `lein repl`. Then the examples can be executed with * `(run request-count-handler)` - A handler with a session that tracks how many times this session has requested this handler In all cases, the handlers can be accessed on http://localhost:3000. + +## Relevant Articles +- [Writing Clojure Webapps with Ring](https://www.baeldung.com/clojure-ring)