diff --git a/aws-lambda-project/.github/workflows/maven.yml b/aws-lambda-project/.github/workflows/maven.yml index 9bcf32e7..6d3bbed7 100644 --- a/aws-lambda-project/.github/workflows/maven.yml +++ b/aws-lambda-project/.github/workflows/maven.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v3 - name: Setup Java 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: ${{ matrix.java }} distribution: ${{ matrix.distribution }} diff --git a/aws-lambda-project/pom.xml b/aws-lambda-project/pom.xml index 9617bd7b..c62685fd 100644 --- a/aws-lambda-project/pom.xml +++ b/aws-lambda-project/pom.xml @@ -7,7 +7,7 @@ org.springframework.boot spring-boot-starter-parent - 3.1.5 + 3.2.0-RC2 com.learning.awslambda @@ -21,15 +21,14 @@ UTF-8 17 - 2022.0.4 - 3.0.3 + 2023.0.0-RC1 2.2.0 1.0.31.RELEASE 2.21.28 ${project.build.directory}/test-results 2.40.0 - 8.4.2 + 9.0.0 1.2.1 3.10.0.2594 0.8.11 @@ -43,10 +42,6 @@ - - org.springframework.boot - spring-boot-starter-actuator - org.springframework.boot spring-boot-starter-web @@ -62,7 +57,7 @@ org.springframework.boot - spring-boot-starter-data-jpa + spring-boot-starter-data-jdbc org.postgresql @@ -121,13 +116,6 @@ pom import - - io.awspring.cloud - spring-cloud-aws-dependencies - ${spring-cloud-aws.version} - pom - import - software.amazon.awssdk bom @@ -376,4 +364,24 @@ + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + diff --git a/aws-lambda-project/src/main/java/com/learning/awslambda/config/logging/Loggable.java b/aws-lambda-project/src/main/java/com/learning/awslambda/config/logging/Loggable.java deleted file mode 100644 index 59c1eaec..00000000 --- a/aws-lambda-project/src/main/java/com/learning/awslambda/config/logging/Loggable.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.learning.awslambda.config.logging; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -@Target({TYPE, METHOD}) -@Retention(RUNTIME) -@Inherited -public @interface Loggable {} diff --git a/aws-lambda-project/src/main/java/com/learning/awslambda/config/logging/LoggingAspect.java b/aws-lambda-project/src/main/java/com/learning/awslambda/config/logging/LoggingAspect.java deleted file mode 100644 index fd4d413d..00000000 --- a/aws-lambda-project/src/main/java/com/learning/awslambda/config/logging/LoggingAspect.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.learning.awslambda.config.logging; - -import com.learning.awslambda.utils.AppConstants; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.AfterThrowing; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.env.Environment; -import org.springframework.core.env.Profiles; -import org.springframework.stereotype.Component; - -@Aspect -@Component -public class LoggingAspect { - - private final Logger log = LoggerFactory.getLogger(this.getClass()); - - private final Environment env; - - public LoggingAspect(Environment env) { - this.env = env; - } - - @Pointcut("within(@org.springframework.stereotype.Repository *)" - + " || within(@org.springframework.stereotype.Service *)" - + " || within(@org.springframework.web.bind.annotation.RestController *)") - public void springBeanPointcut() { - // pointcut definition - } - - @Pointcut("@within(com.learning.awslambda.config.logging.Loggable) || " - + "@annotation(com.learning.awslambda.config.logging.Loggable)") - public void applicationPackagePointcut() { - // pointcut definition - } - - @AfterThrowing(pointcut = "applicationPackagePointcut()", throwing = "e") - public void logAfterThrowing(JoinPoint joinPoint, Throwable e) { - if (env.acceptsProfiles(Profiles.of(AppConstants.PROFILE_NOT_PROD))) { - log.error( - "Exception in {}.{}() with cause = '{}' and exception = '{}'", - joinPoint.getSignature().getDeclaringTypeName(), - joinPoint.getSignature().getName(), - e.getCause() == null ? "NULL" : e.getCause(), - e.getMessage(), - e); - - } else { - log.error( - "Exception in {}.{}() with cause = {}", - joinPoint.getSignature().getDeclaringTypeName(), - joinPoint.getSignature().getName(), - e.getCause() == null ? "NULL" : e.getCause()); - } - } - - @Around("applicationPackagePointcut()") - public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { - if (log.isTraceEnabled()) { - log.trace( - "Enter: {}.{}()", - joinPoint.getSignature().getDeclaringTypeName(), - joinPoint.getSignature().getName()); - } - long start = System.currentTimeMillis(); - Object result = joinPoint.proceed(); - long end = System.currentTimeMillis(); - if (log.isTraceEnabled()) { - log.trace( - "Exit: {}.{}(). Time taken: {} millis", - joinPoint.getSignature().getDeclaringTypeName(), - joinPoint.getSignature().getName(), - end - start); - } - return result; - } -} diff --git a/aws-lambda-project/src/main/java/com/learning/awslambda/entities/Actor.java b/aws-lambda-project/src/main/java/com/learning/awslambda/entities/Actor.java index d1a78aca..56c4cd4a 100644 --- a/aws-lambda-project/src/main/java/com/learning/awslambda/entities/Actor.java +++ b/aws-lambda-project/src/main/java/com/learning/awslambda/entities/Actor.java @@ -1,23 +1,11 @@ package com.learning.awslambda.entities; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; import java.util.Objects; -import org.hibernate.Hibernate; -@Entity -@Table(name = "actors") public class Actor { - @Id - @GeneratedValue(strategy = GenerationType.SEQUENCE) private Long id; - @Column(nullable = false) private String name; public Actor(Long id, String name) { @@ -46,7 +34,6 @@ public void setName(String name) { @Override public boolean equals(Object o) { if (this == o) return true; - if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; Actor actor = (Actor) o; return id != null && Objects.equals(id, actor.id); } diff --git a/aws-lambda-project/src/main/java/com/learning/awslambda/repositories/ActorRepository.java b/aws-lambda-project/src/main/java/com/learning/awslambda/repositories/ActorRepository.java index 0504943f..1d147b85 100644 --- a/aws-lambda-project/src/main/java/com/learning/awslambda/repositories/ActorRepository.java +++ b/aws-lambda-project/src/main/java/com/learning/awslambda/repositories/ActorRepository.java @@ -1,9 +1,57 @@ package com.learning.awslambda.repositories; import com.learning.awslambda.entities.Actor; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.simple.JdbcClient; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; -public interface ActorRepository extends JpaRepository { - Optional findByNameLike(String name); +@Repository +public class ActorRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(ActorRepository.class); + + private final JdbcClient jdbcClient; + private final NamedParameterJdbcTemplate jdbcTemplate; + + public ActorRepository(JdbcClient jdbcClient, NamedParameterJdbcTemplate jdbcTemplate) { + this.jdbcClient = jdbcClient; + this.jdbcTemplate = jdbcTemplate; + } + + @Transactional(readOnly = true) + public Optional findByNameLike(String name) { + String sql = "select id, name from actors where name like :name"; + return jdbcClient.sql(sql).param("name", name).query(Actor.class).optional(); + } + + @Transactional + public void deleteAll() { + String sql = "delete from actors"; + int count = jdbcClient.sql(sql).update(); + LOGGER.info("deleted {} rows", count); + } + + @Transactional + public List saveAll(List actorList) { + + List batch = actorList.stream() + .map(customer -> new Object[] {customer.getName()}) + .toList(); + + String sql = "INSERT INTO actors(name) values :batch RETURNING id, name"; + + return jdbcTemplate.query(sql, new MapSqlParameterSource("batch", batch), rs -> { + List actors = new ArrayList<>(); + while (rs.next()) { + actors.add(new Actor(rs.getLong(1), rs.getString(2))); + } + return actors; + }); + } } diff --git a/aws-lambda-project/src/test/java/com/learning/awslambda/SchemaValidationTest.java b/aws-lambda-project/src/test/java/com/learning/awslambda/SchemaValidationTest.java index 6e56cc2e..1da30620 100644 --- a/aws-lambda-project/src/test/java/com/learning/awslambda/SchemaValidationTest.java +++ b/aws-lambda-project/src/test/java/com/learning/awslambda/SchemaValidationTest.java @@ -1,14 +1,12 @@ package com.learning.awslambda; +import com.learning.awslambda.common.ContainersConfig; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; -@DataJpaTest( - properties = { - "spring.jpa.hibernate.ddl-auto=validate", - "spring.test.database.replace=none", - "spring.datasource.url=jdbc:tc:postgresql:16.1-alpine:///db" - }) +@DataJpaTest(properties = {"spring.jpa.hibernate.ddl-auto=validate", "spring.test.database.replace=none"}) +@Import(ContainersConfig.class) class SchemaValidationTest { @Test diff --git a/aws-lambda-project/src/test/java/com/learning/awslambda/common/ContainersConfig.java b/aws-lambda-project/src/test/java/com/learning/awslambda/common/ContainersConfig.java index c5131611..b3209b00 100644 --- a/aws-lambda-project/src/test/java/com/learning/awslambda/common/ContainersConfig.java +++ b/aws-lambda-project/src/test/java/com/learning/awslambda/common/ContainersConfig.java @@ -3,9 +3,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.springframework.test.context.DynamicPropertyRegistry; import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.containers.localstack.LocalStackContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -16,15 +14,4 @@ public class ContainersConfig { PostgreSQLContainer postgreSQLContainer() { return new PostgreSQLContainer<>(DockerImageName.parse("postgres:16.1-alpine")); } - - @Bean - LocalStackContainer localstackContainer(DynamicPropertyRegistry registry) { - LocalStackContainer localStackContainer = - new LocalStackContainer(DockerImageName.parse("localstack/localstack:3.0.0")); - registry.add("spring.cloud.aws.credentials.access-key", localStackContainer::getAccessKey); - registry.add("spring.cloud.aws.credentials.secret-key", localStackContainer::getSecretKey); - registry.add("spring.cloud.aws.region.static", localStackContainer::getRegion); - registry.add("spring.cloud.aws.endpoint", localStackContainer::getEndpoint); - return localStackContainer; - } } diff --git a/aws-lambda-project/src/test/java/com/learning/awslambda/web/controllers/ActorControllerIT.java b/aws-lambda-project/src/test/java/com/learning/awslambda/web/controllers/ActorControllerIT.java index fb9d2d1c..53664b35 100644 --- a/aws-lambda-project/src/test/java/com/learning/awslambda/web/controllers/ActorControllerIT.java +++ b/aws-lambda-project/src/test/java/com/learning/awslambda/web/controllers/ActorControllerIT.java @@ -23,7 +23,7 @@ class ActorControllerIT extends AbstractIntegrationTest { @BeforeEach void setUp() { - actorRepository.deleteAllInBatch(); + actorRepository.deleteAll(); actorList = new ArrayList<>(); actorList.add(new Actor(null, "First Actor"));