Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for gRPC java #244

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion java/sqlcommenter-java/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ tracestate='rojo%253D00f067aa0ba902b7%2Ccongo%253Dt61rcWkgMzE''*/
- [ ] Jetty
- [ ] Netty
- [ ] Apache Tomcat
- [ ] gRPC
- [X] gRPC

### Using it

Expand Down Expand Up @@ -173,3 +173,17 @@ public class JPAConfig {

1. Please follow the instructions to add the [Spring interceptor](#spring)
2. Please follow the instructions to add the [Hibernate StatementInspector](#hibernate)

#### Spring gRPC Configuration
Add following configuration into your code
```java
@Configuration
public class gRPCConfig {

@Bean
public GrpcSQLCommenterInterceptor grpcSQLCommenterInterceptor() {
return new GrpcSQLCommenterInterceptor();
}

}
```
99 changes: 74 additions & 25 deletions java/sqlcommenter-java/build.gradle
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
description = 'SQL commenter integration'
buildscript {
repositories {
mavenCentral()
mavenLocal()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.16'
classpath "gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.8"
}
}

apply plugin: 'com.github.sherter.google-java-format'
apply plugin: 'idea'
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: "maven-publish"
apply plugin: "net.ltgt.errorprone"
apply plugin: "jacoco"
apply plugin: "signing"
plugins {
id 'com.github.sherter.google-java-format' version "0.7.1"
id 'idea'
id 'java'
id 'maven'
id "maven-publish"
id "net.ltgt.errorprone" version "1.1.0"
id "jacoco"
id "signing"
id "com.google.protobuf" version "0.9.1"
id "com.google.osdetector" version "1.6.2"
}

description = 'SQL commenter integration'

group = "com.google.cloud"
version = "2.0.0" // CURRENT_VERSION
Expand All @@ -28,18 +44,6 @@ jar.manifest {
'Target-Compatibility': targetCompatibility)
}

buildscript {
repositories {
mavenCentral()
mavenLocal()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.16'
classpath "gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.7.1"
}
}


def opencensusVersion = '0.28.3'
def errorProneVersion = '2.3.2'
Expand All @@ -49,13 +53,19 @@ def opentelemetryVersion = '1.5.0'

dependencies {
compile "io.opencensus:opencensus-api:${opencensusVersion}"
testImplementation 'org.projectlombok:lombok:1.18.22'
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.22'
testImplementation group: 'org.mockito', name: 'mockito-core', version: '2.1.0'

runtime "io.opencensus:opencensus-impl:${opencensusVersion}"

compileOnly "com.google.code.findbugs:jsr305:${findBugsJsr305Version}"
compileOnly "com.google.errorprone:error_prone_annotations:${errorProneVersion}"
errorprone "com.google.errorprone:error_prone_core:${errorProneVersion}"
implementation "io.opentelemetry:opentelemetry-api:${opentelemetryVersion}"
implementation "io.opentelemetry:opentelemetry-sdk:${opentelemetryVersion}"
implementation 'io.grpc:grpc-all:1.40.1'

// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
compile (group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.1.5.RELEASE') {
Expand All @@ -71,6 +81,44 @@ dependencies {
testCompile 'org.springframework.boot:spring-boot-starter-data-jpa:2.1.5.RELEASE'
testCompile 'org.springframework.boot:spring-boot-starter-test:2.1.5.RELEASE'
testCompile 'org.hsqldb:hsqldb:2.4.0'
testCompile 'io.github.lognet:grpc-spring-boot-starter:4.9.0'
testCompile "com.google.protobuf:protobuf-java:3.19.1"
runtimeOnly 'io.grpc:grpc-netty-shaded:1.52.1'
implementation 'io.grpc:grpc-protobuf:1.52.1'
implementation 'io.grpc:grpc-stub:1.52.1'
compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+

errorprone("com.google.errorprone:error_prone_core:2.3.3")
errorproneJavac("com.google.errorprone:javac:9+181-r4173-1")

testImplementation group: 'com.h2database', name: 'h2', version: '1.3.148'


}

sourceSets {
test {
java {
srcDirs 'build/generated/source/proto/test/grpc'
srcDirs 'build/generated/source/proto/test/java'
}
}
}

protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.21.7"
}
plugins {
grpc {
artifact = "io.grpc:protoc-gen-grpc-java:1.52.1"
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
}
}

compileJava {
Expand All @@ -79,17 +127,17 @@ compileJava {
// We suppress the "processing" warning as suggested in
// https://groups.google.com/forum/#!topic/bazel-discuss/_R3A9TJSoPM
it.options.compilerArgs += ["-Xlint:all", "-Xlint:-try", "-Xlint:-processing"]
it.options.compilerArgs += ["-XepAllDisabledChecksAsWarnings", "-XepDisableWarningsInGeneratedCode"]
//it.options.compilerArgs += ["-XepAllDisabledChecksAsWarnings", "-XepDisableWarningsInGeneratedCode"]

// MutableMethodReturnType can suggest returning Guava types from
// API methods (https://github.com/google/error-prone/issues/982).
it.options.compilerArgs += ["-Xep:MutableMethodReturnType:OFF"]
//it.options.compilerArgs += ["-Xep:MutableMethodReturnType:OFF"]

// ReturnMissingNullable conflicts with Checker Framework null analysis.
it.options.compilerArgs += ["-Xep:ReturnMissingNullable:OFF"]
//it.options.compilerArgs += ["-Xep:ReturnMissingNullable:OFF"]

// We currently don't use Var annotations.
it.options.compilerArgs += ["-Xep:Var:OFF"]
//it.options.compilerArgs += ["-Xep:Var:OFF"]

it.options.encoding = "UTF-8"
it.options.compilerArgs += ["-Xlint:-cast"]
Expand All @@ -110,6 +158,7 @@ if (JavaVersion.current().isJava8Compatible()) {

tasks.verifyGoogleJavaFormat {
source = sourceSets*.allJava
exclude '**/grpc/stubs/**'
include '**/*.java'
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.cloud.sqlcommenter.interceptors;

import com.google.cloud.sqlcommenter.threadlocalstorage.State;
import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;

public class GrpcSQLCommenterInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
ServerCall<ReqT, RespT> call, Metadata requestHeaders, ServerCallHandler<ReqT, RespT> next) {

if (call == null || next == null) return null;

if (call != null) {
String actionName = call.getMethodDescriptor().getBareMethodName();
String serviceName = call.getMethodDescriptor().getServiceName();
State.Holder.set(
State.newBuilder()
.withControllerName(serviceName)
.withActionName(actionName)
.withFramework("spring-grpc")
.build());
}

return next.startCall(call, requestHeaders);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.google.cloud.sqlcommenter.grpc.backend;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;

import com.google.cloud.sqlcommenter.grpc.backend.service.StudentServiceImpl;
import com.google.cloud.sqlcommenter.grpc.stubs.StudentRequest;
import com.google.cloud.sqlcommenter.grpc.stubs.StudentResponse;
import com.google.cloud.sqlcommenter.threadlocalstorage.State;
import com.google.cloud.sqlcommenter.util.SCHibernateWrapper;
import io.grpc.stub.StreamObserver;
import java.util.List;
import org.junit.Test;

public class GrpcSQLCommenterTests {

@Test
public void givenStudentService_whenGetStudentInfoIsCalled_thenSQLStatementsShouldBeTagged() {
// given
StudentServiceImpl studentService = new StudentServiceImpl();
StreamObserver<StudentResponse> observer = mock(StreamObserver.class);
State.Holder.set(
State.newBuilder()
.withControllerName("StudentServiceImpl")
.withActionName("getStudentInfo")
.withFramework("grpc")
.build());

SCHibernateWrapper.reset();
StudentRequest studentRequest = StudentRequest.newBuilder().setStudentId("st1").build();

// when
studentService.getStudentInfo(studentRequest, observer);
List<String> sqlStatements = SCHibernateWrapper.getAfterSqlStatements();

// then
assertEquals(1, sqlStatements.size());
assertEquals(
1,
sqlStatements
.stream()
.filter(
sql ->
sql.contains(
"/*action='getStudentInfo',controller='StudentServiceImpl',framework='grpc'*/"))
.count());

SCHibernateWrapper.reset();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.cloud.sqlcommenter.grpc.backend.dao;

import com.google.cloud.sqlcommenter.grpc.backend.domain.Student;
import java.util.NoSuchElementException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class StudentDao {
public Student findById(String studentId) {

// We use entity managers to manage our two entities.
// We use the factory design pattern to get the entity manager.
// Here we should provide the name of the persistence unit that we provided in the
// persistence.xml file.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("student-management-system");
EntityManager em = emf.createEntityManager();

// We can find a record in the database for a given id using the find method.
// for the find method we have to provide our entity class and the id.
Student student = em.find(Student.class, studentId);

// If there is no record found with the provided student id, then we throw a NoSuchElement
// exception.
if (student == null) {
throw new NoSuchElementException("NO DATA FOUND WITH THE ID " + studentId);
}

// If everything worked fine, return the result.
return student;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.cloud.sqlcommenter.grpc.backend.domain;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Entity
@Table(name = "student")
public class Student {
@Id private String studentId;
private String name;
private Integer age;
}
Loading