From 94329348fa61edcaddcfd6ac3b7f55c912526b44 Mon Sep 17 00:00:00 2001 From: gkatzioura Date: Sun, 15 Jan 2023 00:32:28 +0000 Subject: [PATCH 1/9] Added filter for sql commenter --- .../filter/SpringSQLCommenterWebFilter.java | 36 +++++++++++++++ .../r2dbc/ConnectionDecorator.java | 44 +++++++++++++++++++ .../r2dbc/ConnectionFactoryAspect.java | 27 ++++++++++++ .../r2dbc/ConnectionInvocationHandler.java | 38 ++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilter.java create mode 100644 java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecorator.java create mode 100644 java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java create mode 100644 java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandler.java diff --git a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilter.java b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilter.java new file mode 100644 index 00000000..e52f46af --- /dev/null +++ b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilter.java @@ -0,0 +1,36 @@ +package com.google.cloud.sqlcommenter.filter; + +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; + +import com.google.cloud.sqlcommenter.threadlocalstorage.State; + +import reactor.core.publisher.Mono; + +public class SpringSQLCommenterWebFilter implements WebFilter { + + private final RequestMappingHandlerMapping handlerMapping; + + public SpringSQLCommenterWebFilter(RequestMappingHandlerMapping handlerMapping) { + this.handlerMapping = handlerMapping; + } + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + HandlerMethod handlerMethod = (HandlerMethod) this.handlerMapping.getHandler(exchange).toFuture().getNow(null); + + State state = State.newBuilder() + .withActionName(handlerMethod.getMethod().getName()) + .withFramework("spring") + .withControllerName(handlerMethod.getBeanType().getSimpleName().replace("Controller","")) + .build(); + + return chain + .filter(exchange) + .contextWrite(ctx -> ctx.put("state", state)); + } + +} diff --git a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecorator.java b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecorator.java new file mode 100644 index 00000000..8c145261 --- /dev/null +++ b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecorator.java @@ -0,0 +1,44 @@ +package com.google.cloud.sqlcommenter.r2dbc; + +import java.lang.reflect.Proxy; + +import org.reactivestreams.Subscription; + +import io.r2dbc.spi.Connection; +import reactor.core.CoreSubscriber; + +public class ConnectionDecorator implements CoreSubscriber { + + private final CoreSubscriber delegate; + + public ConnectionDecorator(CoreSubscriber delegate) { + this.delegate = delegate; + } + + @Override + public void onSubscribe(Subscription s) { + this.delegate.onSubscribe(s); + } + + @Override + public void onNext(Object o) { + assert o instanceof Connection; + Connection connection = (Connection) o; + + Object proxied = Proxy.newProxyInstance(Connection.class.getClassLoader(), + new Class[] {Connection.class}, + new ConnectionInvocationHandler(connection,delegate.currentContext())); + this.delegate.onNext(proxied); + } + + @Override + public void onError(Throwable t) { + this.delegate.onError(t); + } + + @Override + public void onComplete() { + this.delegate.onComplete(); + } + +} diff --git a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java new file mode 100644 index 00000000..fed3354e --- /dev/null +++ b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java @@ -0,0 +1,27 @@ +package com.google.cloud.sqlcommenter.r2dbc; + + + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.reactivestreams.Publisher; + +import io.r2dbc.spi.Connection; +import reactor.core.publisher.Mono; +import reactor.core.publisher.Operators; + +@Aspect +public class ConnectionFactoryAspect { + + @Around("execution(* io.r2dbc.spi.ConnectionFactory.create(..)) ") + public Object beforeSampleCreation(ProceedingJoinPoint joinPoint) throws Throwable { + Publisher publisher = (Publisher) joinPoint.proceed(); + + + return Mono.from(publisher) + .cast(Object.class) + .transform(Operators.liftPublisher((publisher1, coreSubscriber) -> new ConnectionDecorator(coreSubscriber))); + } + +} diff --git a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandler.java b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandler.java new file mode 100644 index 00000000..4617420f --- /dev/null +++ b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandler.java @@ -0,0 +1,38 @@ +package com.google.cloud.sqlcommenter.r2dbc; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +import com.google.cloud.sqlcommenter.threadlocalstorage.State; + +import io.r2dbc.spi.Connection; +import reactor.util.context.ContextView; + +public class ConnectionInvocationHandler implements InvocationHandler { + + private final Connection connection; + private final ContextView contextView; + + public ConnectionInvocationHandler(Connection connection, ContextView contextView) { + this.connection = connection; + this.contextView = contextView; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + String methodName = method.getName(); + + if ("createStatement".equals(methodName)) { + String query = (String) args[0]; + if(contextView!=null) { + State state = contextView.get("state"); + query = state.formatAndAppendToSQL(query); + } + + return method.invoke(connection, query); + } else { + return method.invoke(connection, args); + } + } + +} From db4d5e815e72f98a5c92cd01795ec379b6d16bc3 Mon Sep 17 00:00:00 2001 From: gkatzioura Date: Sun, 15 Jan 2023 22:39:41 +0000 Subject: [PATCH 2/9] Added test for state --- .../SpringSQLCommenterWebFilterTest.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilterTest.java diff --git a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilterTest.java b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilterTest.java new file mode 100644 index 00000000..916a0de6 --- /dev/null +++ b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilterTest.java @@ -0,0 +1,40 @@ +package com.google.cloud.sqlcommenter.filter; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.springframework.mock.http.server.reactive.MockServerHttpRequest; +import org.springframework.mock.web.server.MockServerWebExchange; +import org.springframework.web.reactive.result.method.RequestMappingInfo; +import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; +import org.springframework.web.server.WebFilterChain; + +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + + +@RunWith(JUnit4.class) +public class SpringSQLCommenterWebFilterTest { + + @Test + public void testPreHandlePlacesStateInContextView() throws NoSuchMethodException { + RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping(); + RequestMappingInfo info = RequestMappingInfo.paths("/test").build(); + requestMappingHandlerMapping.registerMapping(info, this, SpringSQLCommenterWebFilterTest.class.getMethod("testPreHandlePlacesStateInContextView")); + + SpringSQLCommenterWebFilter springSQLCommenterWebFilter = new SpringSQLCommenterWebFilter(requestMappingHandlerMapping); + + WebFilterChain filterChain = filterExchange -> Mono.empty(); + + MockServerWebExchange exchange = MockServerWebExchange.from( + MockServerHttpRequest + .get("/test")); + + StepVerifier.create(springSQLCommenterWebFilter.filter(exchange, filterChain)) + .expectAccessibleContext() + .hasKey("state") + .then() + .verifyComplete(); + } + +} \ No newline at end of file From 7b8da8aea3691096a04d83a968020e7d88bfd61f Mon Sep 17 00:00:00 2001 From: gkatzioura Date: Sun, 15 Jan 2023 22:41:59 +0000 Subject: [PATCH 3/9] 228: Added unchecked exception --- .../cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java index fed3354e..cb404691 100644 --- a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java +++ b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java @@ -7,7 +7,6 @@ import org.aspectj.lang.annotation.Aspect; import org.reactivestreams.Publisher; -import io.r2dbc.spi.Connection; import reactor.core.publisher.Mono; import reactor.core.publisher.Operators; @@ -16,11 +15,11 @@ public class ConnectionFactoryAspect { @Around("execution(* io.r2dbc.spi.ConnectionFactory.create(..)) ") public Object beforeSampleCreation(ProceedingJoinPoint joinPoint) throws Throwable { - Publisher publisher = (Publisher) joinPoint.proceed(); + Object object = joinPoint.proceed(); + @SuppressWarnings("unchecked") Publisher publisher = (Publisher) object; return Mono.from(publisher) - .cast(Object.class) .transform(Operators.liftPublisher((publisher1, coreSubscriber) -> new ConnectionDecorator(coreSubscriber))); } From 0b92255880544106ffa838c9174c98fac08e4ab3 Mon Sep 17 00:00:00 2001 From: gkatzioura Date: Sun, 15 Jan 2023 23:00:17 +0000 Subject: [PATCH 4/9] 228: Added formatting --- .../filter/SpringSQLCommenterWebFilter.java | 38 +++++----- .../r2dbc/ConnectionDecorator.java | 69 +++++++++---------- .../r2dbc/ConnectionFactoryAspect.java | 21 +++--- .../r2dbc/ConnectionInvocationHandler.java | 45 ++++++------ 4 files changed, 83 insertions(+), 90 deletions(-) diff --git a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilter.java b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilter.java index e52f46af..725daece 100644 --- a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilter.java +++ b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilter.java @@ -1,36 +1,34 @@ package com.google.cloud.sqlcommenter.filter; +import com.google.cloud.sqlcommenter.threadlocalstorage.State; import org.springframework.web.method.HandlerMethod; import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; - -import com.google.cloud.sqlcommenter.threadlocalstorage.State; - import reactor.core.publisher.Mono; public class SpringSQLCommenterWebFilter implements WebFilter { - private final RequestMappingHandlerMapping handlerMapping; - - public SpringSQLCommenterWebFilter(RequestMappingHandlerMapping handlerMapping) { - this.handlerMapping = handlerMapping; - } + private final RequestMappingHandlerMapping handlerMapping; - @Override - public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { - HandlerMethod handlerMethod = (HandlerMethod) this.handlerMapping.getHandler(exchange).toFuture().getNow(null); + public SpringSQLCommenterWebFilter(RequestMappingHandlerMapping handlerMapping) { + this.handlerMapping = handlerMapping; + } - State state = State.newBuilder() - .withActionName(handlerMethod.getMethod().getName()) - .withFramework("spring") - .withControllerName(handlerMethod.getBeanType().getSimpleName().replace("Controller","")) - .build(); + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + HandlerMethod handlerMethod = + (HandlerMethod) this.handlerMapping.getHandler(exchange).toFuture().getNow(null); - return chain - .filter(exchange) - .contextWrite(ctx -> ctx.put("state", state)); - } + State state = + State.newBuilder() + .withActionName(handlerMethod.getMethod().getName()) + .withFramework("spring") + .withControllerName( + handlerMethod.getBeanType().getSimpleName().replace("Controller", "")) + .build(); + return chain.filter(exchange).contextWrite(ctx -> ctx.put("state", state)); + } } diff --git a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecorator.java b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecorator.java index 8c145261..c27c36e4 100644 --- a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecorator.java +++ b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecorator.java @@ -1,44 +1,43 @@ package com.google.cloud.sqlcommenter.r2dbc; +import io.r2dbc.spi.Connection; import java.lang.reflect.Proxy; - import org.reactivestreams.Subscription; - -import io.r2dbc.spi.Connection; import reactor.core.CoreSubscriber; public class ConnectionDecorator implements CoreSubscriber { - private final CoreSubscriber delegate; - - public ConnectionDecorator(CoreSubscriber delegate) { - this.delegate = delegate; - } - - @Override - public void onSubscribe(Subscription s) { - this.delegate.onSubscribe(s); - } - - @Override - public void onNext(Object o) { - assert o instanceof Connection; - Connection connection = (Connection) o; - - Object proxied = Proxy.newProxyInstance(Connection.class.getClassLoader(), - new Class[] {Connection.class}, - new ConnectionInvocationHandler(connection,delegate.currentContext())); - this.delegate.onNext(proxied); - } - - @Override - public void onError(Throwable t) { - this.delegate.onError(t); - } - - @Override - public void onComplete() { - this.delegate.onComplete(); - } - + private final CoreSubscriber delegate; + + public ConnectionDecorator(CoreSubscriber delegate) { + this.delegate = delegate; + } + + @Override + public void onSubscribe(Subscription s) { + this.delegate.onSubscribe(s); + } + + @Override + public void onNext(Object o) { + assert o instanceof Connection; + Connection connection = (Connection) o; + + Object proxied = + Proxy.newProxyInstance( + Connection.class.getClassLoader(), + new Class[] {Connection.class}, + new ConnectionInvocationHandler(connection, delegate.currentContext())); + this.delegate.onNext(proxied); + } + + @Override + public void onError(Throwable t) { + this.delegate.onError(t); + } + + @Override + public void onComplete() { + this.delegate.onComplete(); + } } diff --git a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java index cb404691..7ea69692 100644 --- a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java +++ b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspect.java @@ -1,26 +1,25 @@ package com.google.cloud.sqlcommenter.r2dbc; - - import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.reactivestreams.Publisher; - import reactor.core.publisher.Mono; import reactor.core.publisher.Operators; @Aspect public class ConnectionFactoryAspect { - @Around("execution(* io.r2dbc.spi.ConnectionFactory.create(..)) ") - public Object beforeSampleCreation(ProceedingJoinPoint joinPoint) throws Throwable { - Object object = joinPoint.proceed(); - - @SuppressWarnings("unchecked") Publisher publisher = (Publisher) object; + @Around("execution(* io.r2dbc.spi.ConnectionFactory.create(..)) ") + public Object beforeSampleCreation(ProceedingJoinPoint joinPoint) throws Throwable { + Object object = joinPoint.proceed(); - return Mono.from(publisher) - .transform(Operators.liftPublisher((publisher1, coreSubscriber) -> new ConnectionDecorator(coreSubscriber))); - } + @SuppressWarnings("unchecked") + Publisher publisher = (Publisher) object; + return Mono.from(publisher) + .transform( + Operators.liftPublisher( + (publisher1, coreSubscriber) -> new ConnectionDecorator(coreSubscriber))); + } } diff --git a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandler.java b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandler.java index 4617420f..b27d8abe 100644 --- a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandler.java +++ b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandler.java @@ -1,38 +1,35 @@ package com.google.cloud.sqlcommenter.r2dbc; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; - import com.google.cloud.sqlcommenter.threadlocalstorage.State; - import io.r2dbc.spi.Connection; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; import reactor.util.context.ContextView; public class ConnectionInvocationHandler implements InvocationHandler { - private final Connection connection; - private final ContextView contextView; + private final Connection connection; + private final ContextView contextView; - public ConnectionInvocationHandler(Connection connection, ContextView contextView) { - this.connection = connection; - this.contextView = contextView; - } + public ConnectionInvocationHandler(Connection connection, ContextView contextView) { + this.connection = connection; + this.contextView = contextView; + } - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - String methodName = method.getName(); + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + String methodName = method.getName(); - if ("createStatement".equals(methodName)) { - String query = (String) args[0]; - if(contextView!=null) { - State state = contextView.get("state"); - query = state.formatAndAppendToSQL(query); - } + if ("createStatement".equals(methodName)) { + String query = (String) args[0]; + if (contextView != null) { + State state = contextView.get("state"); + query = state.formatAndAppendToSQL(query); + } - return method.invoke(connection, query); - } else { - return method.invoke(connection, args); - } + return method.invoke(connection, query); + } else { + return method.invoke(connection, args); } - + } } From 8628aaa2bd4df98cd7c64b9582d95f421a908ff5 Mon Sep 17 00:00:00 2001 From: gkatzioura Date: Sun, 15 Jan 2023 23:01:13 +0000 Subject: [PATCH 5/9] 228: Added dependencies and test --- java/sqlcommenter-java/build.gradle | 14 ++++++ .../SpringSQLCommenterWebFilterTest.java | 47 +++++++++---------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/java/sqlcommenter-java/build.gradle b/java/sqlcommenter-java/build.gradle index c965bcf4..e2deba08 100644 --- a/java/sqlcommenter-java/build.gradle +++ b/java/sqlcommenter-java/build.gradle @@ -61,6 +61,20 @@ dependencies { compile (group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.1.5.RELEASE') { exclude group: 'org.apache.logging.log4j', module: 'log4j-to-slf4j' } + + compile (group: 'org.springframework.boot', name: 'spring-boot-starter-webflux', version: '2.7.7') { + exclude group: 'org.apache.logging.log4j', module: 'log4j-to-slf4j' + } + + compile (group: 'org.springframework.boot', name: 'spring-boot-starter-aop', version: '2.7.7') { + exclude group: 'org.apache.logging.log4j', module: 'log4j-to-slf4j' + } + + testImplementation 'io.projectreactor:reactor-test:3.5.2' + + compile 'io.r2dbc:r2dbc-proxy:1.1.0.RELEASE' + compile 'io.r2dbc:r2dbc-spi:1.0.0.RELEASE' + compile 'org.apache.logging.log4j:log4j-to-slf4j:2.16.0' compile 'org.hibernate:hibernate-core:5.4.3.Final' diff --git a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilterTest.java b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilterTest.java index 916a0de6..9fa78036 100644 --- a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilterTest.java +++ b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/filter/SpringSQLCommenterWebFilterTest.java @@ -8,33 +8,32 @@ import org.springframework.web.reactive.result.method.RequestMappingInfo; import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.server.WebFilterChain; - import reactor.core.publisher.Mono; import reactor.test.StepVerifier; - @RunWith(JUnit4.class) public class SpringSQLCommenterWebFilterTest { - @Test - public void testPreHandlePlacesStateInContextView() throws NoSuchMethodException { - RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping(); - RequestMappingInfo info = RequestMappingInfo.paths("/test").build(); - requestMappingHandlerMapping.registerMapping(info, this, SpringSQLCommenterWebFilterTest.class.getMethod("testPreHandlePlacesStateInContextView")); - - SpringSQLCommenterWebFilter springSQLCommenterWebFilter = new SpringSQLCommenterWebFilter(requestMappingHandlerMapping); - - WebFilterChain filterChain = filterExchange -> Mono.empty(); - - MockServerWebExchange exchange = MockServerWebExchange.from( - MockServerHttpRequest - .get("/test")); - - StepVerifier.create(springSQLCommenterWebFilter.filter(exchange, filterChain)) - .expectAccessibleContext() - .hasKey("state") - .then() - .verifyComplete(); - } - -} \ No newline at end of file + @Test + public void testPreHandlePlacesStateInContextView() throws NoSuchMethodException { + RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping(); + RequestMappingInfo info = RequestMappingInfo.paths("/test").build(); + requestMappingHandlerMapping.registerMapping( + info, + this, + SpringSQLCommenterWebFilterTest.class.getMethod("testPreHandlePlacesStateInContextView")); + + SpringSQLCommenterWebFilter springSQLCommenterWebFilter = + new SpringSQLCommenterWebFilter(requestMappingHandlerMapping); + + WebFilterChain filterChain = filterExchange -> Mono.empty(); + + MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/test")); + + StepVerifier.create(springSQLCommenterWebFilter.filter(exchange, filterChain)) + .expectAccessibleContext() + .hasKey("state") + .then() + .verifyComplete(); + } +} From b4ad28567ae25519fa49a40363aca9d8feb998b9 Mon Sep 17 00:00:00 2001 From: gkatzioura Date: Mon, 16 Jan 2023 07:47:43 +0000 Subject: [PATCH 6/9] 228: Added tests for ConnectionInvocationHandler --- .../r2dbc/ConnectionInvocationHandler.java | 2 +- .../ConnectionInvocationHandlerTest.java | 79 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandlerTest.java diff --git a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandler.java b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandler.java index b27d8abe..fb47d20a 100644 --- a/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandler.java +++ b/java/sqlcommenter-java/src/main/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandler.java @@ -22,7 +22,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl if ("createStatement".equals(methodName)) { String query = (String) args[0]; - if (contextView != null) { + if (contextView != null && contextView.hasKey("state")) { State state = contextView.get("state"); query = state.formatAndAppendToSQL(query); } diff --git a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandlerTest.java b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandlerTest.java new file mode 100644 index 00000000..82e5ed5b --- /dev/null +++ b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandlerTest.java @@ -0,0 +1,79 @@ +package com.google.cloud.sqlcommenter.r2dbc; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.cloud.sqlcommenter.threadlocalstorage.State; +import io.r2dbc.spi.Connection; +import io.r2dbc.spi.Statement; +import java.lang.reflect.Proxy; +import junit.framework.TestCase; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import reactor.util.context.Context; + +@RunWith(JUnit4.class) +public class ConnectionInvocationHandlerTest extends TestCase { + + private final String stmt1 = "SELECT * from FOO"; + + private Connection connection = mock(Connection.class); + private Connection proxiedConnection; + private Context context = Context.empty(); + private ConnectionInvocationHandler connectionInvocationHandler; + + @Override + @Before + public void setUp() throws Exception { + connection = mock(Connection.class); + when(connection.createStatement(anyString())).thenAnswer(i -> mock(Statement.class)); + + connectionInvocationHandler = new ConnectionInvocationHandler(connection, context); + proxiedConnection = proxyConnection(connectionInvocationHandler); + } + + @Test + public void testInvokeCreateStatementEmptyState() { + proxiedConnection.createStatement(stmt1); + verify(connection).createStatement(eq(stmt1)); + } + + @Test + public void testInvokeCreateStatement() { + State state = + State.newBuilder() + .withControllerName("Order") + .withFramework("spring") + .withActionName("add") + .build(); + Context updatedContext = context.put("state", state); + + connectionInvocationHandler = new ConnectionInvocationHandler(connection, updatedContext); + proxiedConnection = proxyConnection(connectionInvocationHandler); + + proxiedConnection.createStatement(stmt1); + String appendedState = state.formatAndAppendToSQL(stmt1); + verify(connection).createStatement(eq(appendedState)); + } + + @Test + public void testInvokeDelegate() { + proxiedConnection.beginTransaction(); + proxiedConnection.createStatement(stmt1); + verify(connection, times(1)).beginTransaction(); + } + + private Connection proxyConnection(ConnectionInvocationHandler connectionInvocationHandler) { + return (Connection) + Proxy.newProxyInstance( + Connection.class.getClassLoader(), + new Class[] {Connection.class}, + connectionInvocationHandler); + } +} From 682b8c144caaa0d979bbb7a322313233d4dbcda7 Mon Sep 17 00:00:00 2001 From: gkatzioura Date: Mon, 16 Jan 2023 08:10:07 +0000 Subject: [PATCH 7/9] 228: Added unit test --- .../r2dbc/ConnectionDecoratorTest.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecoratorTest.java diff --git a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecoratorTest.java b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecoratorTest.java new file mode 100644 index 00000000..488f38a4 --- /dev/null +++ b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecoratorTest.java @@ -0,0 +1,63 @@ +package com.google.cloud.sqlcommenter.r2dbc; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import io.r2dbc.spi.Connection; +import junit.framework.TestCase; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.reactivestreams.Subscription; +import reactor.core.CoreSubscriber; + +@RunWith(JUnit4.class) +public class ConnectionDecoratorTest extends TestCase { + + private CoreSubscriber delegate; + private ConnectionDecorator connectionDecorator; + + @Override + @Before + public void setUp() throws Exception { + delegate = mock(CoreSubscriber.class); + connectionDecorator = new ConnectionDecorator(delegate); + } + + @Test + public void testOnSubscribe() { + Subscription mocked = mock(Subscription.class); + connectionDecorator.onSubscribe(mocked); + verify(delegate, times(1)).onSubscribe(mocked); + } + + @Test + public void testOnNext() { + Connection connection = mock(Connection.class); + connectionDecorator.onNext(connection); + verify(delegate, times(1)).currentContext(); + verify(delegate, times(1)).onNext(any()); + } + + @Test(expected = AssertionError.class) + public void testOnNextNonConnection() { + Object object = new Object(); + connectionDecorator.onNext(object); + } + + @Test + public void testOnError() { + Throwable mocked = mock(Throwable.class); + connectionDecorator.onError(mocked); + verify(delegate, times(1)).onError(mocked); + } + + @Test + public void testOnComplete() { + connectionDecorator.onComplete(); + verify(delegate, times(1)).onComplete(); + } +} From 43d5819e0b2535b693ea4a30a5d51f1883bb7a06 Mon Sep 17 00:00:00 2001 From: gkatzioura Date: Mon, 16 Jan 2023 10:20:30 +0000 Subject: [PATCH 8/9] 228: Added unit test for aspect --- java/sqlcommenter-java/build.gradle | 1 + .../r2dbc/ConnectionDecoratorTest.java | 4 +- .../r2dbc/ConnectionFactoryAspectTest.java | 52 +++++++++++++++++++ .../ConnectionInvocationHandlerTest.java | 4 +- .../r2dbc/R2DBCConfiguration.java | 28 ++++++++++ 5 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspectTest.java create mode 100644 java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/R2DBCConfiguration.java diff --git a/java/sqlcommenter-java/build.gradle b/java/sqlcommenter-java/build.gradle index e2deba08..818ceb67 100644 --- a/java/sqlcommenter-java/build.gradle +++ b/java/sqlcommenter-java/build.gradle @@ -74,6 +74,7 @@ dependencies { compile 'io.r2dbc:r2dbc-proxy:1.1.0.RELEASE' compile 'io.r2dbc:r2dbc-spi:1.0.0.RELEASE' + testImplementation 'io.r2dbc:r2dbc-h2:1.0.0.RELEASE' compile 'org.apache.logging.log4j:log4j-to-slf4j:2.16.0' diff --git a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecoratorTest.java b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecoratorTest.java index 488f38a4..4254cb63 100644 --- a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecoratorTest.java +++ b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionDecoratorTest.java @@ -6,7 +6,6 @@ import static org.mockito.Mockito.verify; import io.r2dbc.spi.Connection; -import junit.framework.TestCase; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -15,12 +14,11 @@ import reactor.core.CoreSubscriber; @RunWith(JUnit4.class) -public class ConnectionDecoratorTest extends TestCase { +public class ConnectionDecoratorTest { private CoreSubscriber delegate; private ConnectionDecorator connectionDecorator; - @Override @Before public void setUp() throws Exception { delegate = mock(CoreSubscriber.class); diff --git a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspectTest.java b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspectTest.java new file mode 100644 index 00000000..0d17256a --- /dev/null +++ b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspectTest.java @@ -0,0 +1,52 @@ +package com.google.cloud.sqlcommenter.r2dbc; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.reactivestreams.Publisher; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.util.ReflectionTestUtils; + +import com.google.cloud.sqlcommenter.threadlocalstorage.State; + +import io.r2dbc.spi.Connection; +import io.r2dbc.spi.ConnectionFactory; +import io.r2dbc.spi.Statement; +import static org.junit.Assert.assertEquals; +import reactor.core.publisher.Mono; +import reactor.util.context.Context; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = R2DBCConfiguration.class) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +public class ConnectionFactoryAspectTest { + + private final String stmt1 = "SELECT * from FOO"; + + @Autowired + private ConnectionFactory connectionFactory; + + @Test + public void name() { + State state = + State.newBuilder() + .withControllerName("Order") + .withFramework("spring") + .withActionName("add") + .build(); + Context updatedContext = Context.of("state", state); + + Publisher conn = connectionFactory.create(); + + Statement statement = Mono.from(conn) + .contextWrite(updatedContext) + .map(connection -> connection.createStatement(stmt1)) + .block(); + + String value = (String) ReflectionTestUtils.getField(statement, null, "sql"); + assertEquals(value, state.formatAndAppendToSQL(stmt1)); + } + +} \ No newline at end of file diff --git a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandlerTest.java b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandlerTest.java index 82e5ed5b..2d740405 100644 --- a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandlerTest.java +++ b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionInvocationHandlerTest.java @@ -11,7 +11,6 @@ import io.r2dbc.spi.Connection; import io.r2dbc.spi.Statement; import java.lang.reflect.Proxy; -import junit.framework.TestCase; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -19,7 +18,7 @@ import reactor.util.context.Context; @RunWith(JUnit4.class) -public class ConnectionInvocationHandlerTest extends TestCase { +public class ConnectionInvocationHandlerTest { private final String stmt1 = "SELECT * from FOO"; @@ -28,7 +27,6 @@ public class ConnectionInvocationHandlerTest extends TestCase { private Context context = Context.empty(); private ConnectionInvocationHandler connectionInvocationHandler; - @Override @Before public void setUp() throws Exception { connection = mock(Connection.class); diff --git a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/R2DBCConfiguration.java b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/R2DBCConfiguration.java new file mode 100644 index 00000000..83e45840 --- /dev/null +++ b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/R2DBCConfiguration.java @@ -0,0 +1,28 @@ +package com.google.cloud.sqlcommenter.r2dbc; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +import io.r2dbc.h2.H2ConnectionFactory; +import io.r2dbc.spi.ConnectionFactory; + +@Configuration +@EnableAspectJAutoProxy +public class R2DBCConfiguration { + + @Bean + public ConnectionFactory connectionFactory() { + return new H2ConnectionFactory( + io.r2dbc.h2.H2ConnectionConfiguration.builder() + .url("mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;") + .build() + ); + } + + @Bean + public ConnectionFactoryAspect connectionFactoryAspect() { + return new ConnectionFactoryAspect(); + } + +} From 9ede1fe9963bd0e3829d9067c7ba8c34e83dc38d Mon Sep 17 00:00:00 2001 From: gkatzioura Date: Mon, 16 Jan 2023 10:20:51 +0000 Subject: [PATCH 9/9] 228: Formatted --- .../r2dbc/ConnectionFactoryAspectTest.java | 56 +++++++++---------- .../r2dbc/R2DBCConfiguration.java | 29 +++++----- 2 files changed, 40 insertions(+), 45 deletions(-) diff --git a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspectTest.java b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspectTest.java index 0d17256a..1b694d5e 100644 --- a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspectTest.java +++ b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/ConnectionFactoryAspectTest.java @@ -1,5 +1,11 @@ package com.google.cloud.sqlcommenter.r2dbc; +import static org.junit.Assert.assertEquals; + +import com.google.cloud.sqlcommenter.threadlocalstorage.State; +import io.r2dbc.spi.Connection; +import io.r2dbc.spi.ConnectionFactory; +import io.r2dbc.spi.Statement; import org.junit.Test; import org.junit.runner.RunWith; import org.reactivestreams.Publisher; @@ -8,13 +14,6 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.util.ReflectionTestUtils; - -import com.google.cloud.sqlcommenter.threadlocalstorage.State; - -import io.r2dbc.spi.Connection; -import io.r2dbc.spi.ConnectionFactory; -import io.r2dbc.spi.Statement; -import static org.junit.Assert.assertEquals; import reactor.core.publisher.Mono; import reactor.util.context.Context; @@ -23,30 +22,29 @@ @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) public class ConnectionFactoryAspectTest { - private final String stmt1 = "SELECT * from FOO"; - - @Autowired - private ConnectionFactory connectionFactory; + private final String stmt1 = "SELECT * from FOO"; - @Test - public void name() { - State state = - State.newBuilder() - .withControllerName("Order") - .withFramework("spring") - .withActionName("add") - .build(); - Context updatedContext = Context.of("state", state); + @Autowired private ConnectionFactory connectionFactory; - Publisher conn = connectionFactory.create(); + @Test + public void name() { + State state = + State.newBuilder() + .withControllerName("Order") + .withFramework("spring") + .withActionName("add") + .build(); + Context updatedContext = Context.of("state", state); - Statement statement = Mono.from(conn) - .contextWrite(updatedContext) - .map(connection -> connection.createStatement(stmt1)) - .block(); + Publisher conn = connectionFactory.create(); - String value = (String) ReflectionTestUtils.getField(statement, null, "sql"); - assertEquals(value, state.formatAndAppendToSQL(stmt1)); - } + Statement statement = + Mono.from(conn) + .contextWrite(updatedContext) + .map(connection -> connection.createStatement(stmt1)) + .block(); -} \ No newline at end of file + String value = (String) ReflectionTestUtils.getField(statement, null, "sql"); + assertEquals(value, state.formatAndAppendToSQL(stmt1)); + } +} diff --git a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/R2DBCConfiguration.java b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/R2DBCConfiguration.java index 83e45840..83026003 100644 --- a/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/R2DBCConfiguration.java +++ b/java/sqlcommenter-java/src/test/java/com/google/cloud/sqlcommenter/r2dbc/R2DBCConfiguration.java @@ -1,28 +1,25 @@ package com.google.cloud.sqlcommenter.r2dbc; +import io.r2dbc.h2.H2ConnectionFactory; +import io.r2dbc.spi.ConnectionFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; -import io.r2dbc.h2.H2ConnectionFactory; -import io.r2dbc.spi.ConnectionFactory; - @Configuration @EnableAspectJAutoProxy public class R2DBCConfiguration { - @Bean - public ConnectionFactory connectionFactory() { - return new H2ConnectionFactory( - io.r2dbc.h2.H2ConnectionConfiguration.builder() - .url("mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;") - .build() - ); - } - - @Bean - public ConnectionFactoryAspect connectionFactoryAspect() { - return new ConnectionFactoryAspect(); - } + @Bean + public ConnectionFactory connectionFactory() { + return new H2ConnectionFactory( + io.r2dbc.h2.H2ConnectionConfiguration.builder() + .url("mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;") + .build()); + } + @Bean + public ConnectionFactoryAspect connectionFactoryAspect() { + return new ConnectionFactoryAspect(); + } }