Proxy for MongoDB Client-Side Field Level Encrytion AWS KMS Connection - mongodb

We have implemented a Client-Side Field Level Encryption on a Spring Boot application, using AWS KMS to save the master key.
I followed the tutorial created by Visweshwar Ganesh and everything works perfectly.
MongoDB Client-Side Field Level Encryption using Java-Spring
The problem is that we need to connect to the AWS KMS through a proxy, and I can't find any documentation to inject proxy configs for MongoEncription.
Does anyone know how to solve this?
Regards!
Edit:
We are using: spring-boot-starter-data-mongodb-2.2.4.RELEASE which uses mongodb-driver 3.11.2
And this is the official MongoDB Documentation
We want to proxy the call to retrieve the CMK from Thrid-Party KMS (AWS) to Encrypt and Decrypt data:
When application starts it creates a mongoClient with the encryption settings and validates if alteady exists a vault with encrypton keys, if not tries to create one, and for that needs to have the CMK stored on AWS KMS
It's on this call that occurs on buildOrValidateVault() method that we want to inject the proxy.
PS: This application is running on a kubernetes container.
MongoEncryptionConfig
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bson.BsonDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.AutoEncryptionSettings;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoDriverInformation;
import com.mongodb.client.MongoClient;
import com.mongodb.client.internal.MongoClientImpl;
import com.mongodb.internal.build.MongoDriverVersion;
#Configuration
public class MongoEncryptionConfig extends AbstractMongoClientConfiguration {
#Value(value = "${mongodb.student.name}")
private String dbDatabase;
#Value(value = "${mongodb.student.uri}")
private String dbConnection;
#Value(value = "${encryption.schema-path}")
private String schemaPath;
#Autowired
private KmsHandlerAws kmsHandler;
private static Logger logger = LogManager.getLogger("MongoEncryptionConfig");
private MongoDriverInformation getMongoDriverInfo() {
return MongoDriverInformation.builder()
.driverName(MongoDriverVersion.NAME)
.driverVersion(MongoDriverVersion.VERSION)
.driverPlatform(java.lang.String.format("Java/%s/%s", java.lang.System.getProperty("java.vendor", "unknown-vendor"),
java.lang.System.getProperty("java.runtime.version", "unknown-version")))
.build();
}
private MongoClientSettings getAutoEncryptMongoClientSettings() {
return MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(dbConnection))
.autoEncryptionSettings(autoEncryptionSettings())
.build();
}
private AutoEncryptionSettings autoEncryptionSettings() {
return AutoEncryptionSettings.builder()
.keyVaultNamespace(kmsHandler.getEncryptionCollectionName())
.kmsProviders(kmsHandler.getKmsProvider())
.extraOptions(kmsHandler.getExtraOptsMap())
.schemaMap(buildOrValidateVault())
.build();
}
private Map<String, BsonDocument> buildOrValidateVault() {
try {
ObjectMapper objectMapper = new ObjectMapper();
for (Path path : loadSchemasPaths(this.schemaPath)) {
logger.debug("Path being iterated: " + path.getFileName().toString());
String encryptKey = this.kmsHandler.buildOrValidateVault();
JsonNode jsonDocument = objectMapper.readTree(Files.readString(path));
return Collections.singletonMap(
this.dbDatabase + "." + jsonDocument.get("metadata").get("collection").asText(),
BsonDocument.parse(String.format(objectMapper.writeValueAsString(jsonDocument.get("schema")), encryptKey)));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return null;
}
private List<Path> loadSchemasPaths(String encryptionPath) throws IOException {
List<Path> paths = new ArrayList<>();
logger.debug("Encryption Path: " + encryptionPath);
Files.list(Paths.get(encryptionPath))
.forEach(path -> {
logger.debug("Path trying to be add: " + path.getFileName());
if (path.getFileName().toString().endsWith(".json")) {
logger.debug(path.getFileName() + " ends with .json! Yes!");
paths.add(path);
} else {
logger.debug(path.getFileName() + " Doesn't end with .json :(");
}
});
return paths;
}
#Override
public MongoClient mongoClient() {
return new MongoClientImpl(getAutoEncryptMongoClientSettings(), getMongoDriverInfo());
}
#Override
protected String getDatabaseName() {
return dbDatabase;
}
}
KMSHandler
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.bson.BsonBinary;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
public abstract class KmsHandler {
Logger logger = LoggerFactory.getLogger(KmsHandler.class);
#Value(value = "${mongodb.student.uri}")
String dbConnection;
#Value(value = "${encryption.vault.database}")
String encryptionVaultDatabase;
#Value(value = "${encryption.vault.collection}")
String encryptionVaultCollection;
#Value(value = "${encryption.vault.name}")
String encryptionVaultName;
private String encryptionKeyBase64;
private UUID encryptionKeyUuid;
public String getEncryptionKeyBase64() {
return encryptionKeyBase64;
}
public void setEncryptionKeyBase64(String encryptionKeyBase64) {
this.encryptionKeyBase64 = encryptionKeyBase64;
}
public UUID getEncryptionKeyUuid() {
return encryptionKeyUuid;
}
public void setEncryptionKeyUuid(UUID encryptionKeyUuid) {
this.encryptionKeyUuid = encryptionKeyUuid;
}
public String getEncryptionCollectionName() {
return encryptionVaultDatabase + "." + encryptionVaultCollection;
}
public Map<String, Object> getExtraOptsMap() {
Map<String, Object> extraOps = new HashMap<>();
//extraOps.put("mongocryptdBypassSpawn", true);
//extraOps.put("mongocryptdURI", "mongodb://localhost:27020");
return extraOps;
}
/**
* Check in database if encryption was already created
* dd
*
* #return true or false
*/
protected String doesEncryptionKeyExist() {
MongoClient mongoClient = MongoClients.create(dbConnection);
MongoCollection<Document> collection = mongoClient.getDatabase(encryptionVaultDatabase).getCollection(encryptionVaultCollection);
Document doc = collection.find(Filters.in("keyAltNames", encryptionVaultName)).first();
if (doc != null) {
return Base64.getEncoder().encodeToString(new BsonBinary((UUID) doc.get("_id")).getData());
} else {
return null;
}
}
}
KMSHandlerAWS
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.bson.BsonBinary;
import org.bson.BsonDocument;
import org.bson.BsonString;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.mongodb.ClientEncryptionSettings;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.model.vault.DataKeyOptions;
import com.mongodb.client.vault.ClientEncryption;
import com.mongodb.client.vault.ClientEncryptions;
#Component
public class KmsHandlerAws extends KmsHandler implements IKmsHandler {
#Value(value = "${encryption.kms.aws.region}")
private String encryptionKmsRegion;
#Value(value = "${encryption.kms.aws.key}")
private String encryptionKmsKey;
#Value(value = "${encryption.kms.aws.iam.accessKeyId}")
private String encryptionKmsIamAccessKey;
#Value(value = "${encryption.kms.aws.iam.secretAccessKey}")
private String encryptionKmsIamSecretAccessKey;
public String buildOrValidateVault() {
try {
// Check if encryption key exists
String encryptKey = doesEncryptionKeyExist();
if (encryptKey != null) {
return encryptKey;
}
// Create Encryption Key
BsonBinary dataKeyId = getClientEncryption().createDataKey("aws", this.getDataKeyOptions());
// Save key in instance
this.setEncryptionKeyUuid(dataKeyId.asUuid());
logger.debug("DataKeyID [UUID]{}", dataKeyId.asUuid());
System.out.println("DataKeyID [UUID]: " + dataKeyId.asUuid());
String base64DataKeyId = Base64.getEncoder().encodeToString(dataKeyId.getData());
this.setEncryptionKeyBase64(base64DataKeyId);
logger.debug("DataKeyID [base64]: {}", base64DataKeyId);
System.out.println("DataKeyID [base64]: " + base64DataKeyId);
return super.getEncryptionKeyBase64();
} catch (Exception ex) {
String exceptionMessage = "Exception at buildOrValidateVault(): " + ex.getMessage();
System.out.println(exceptionMessage);
ex.printStackTrace();
return exceptionMessage;
}
}
public Map<String, Map<String, Object>> getKmsProvider() {
Map<String, Object> providerDetails = new HashMap<>();
providerDetails.put("accessKeyId", new BsonString(this.encryptionKmsIamAccessKey).getValue());
providerDetails.put("secretAccessKey", new BsonString(this.encryptionKmsIamSecretAccessKey).getValue());
Map<String, Map<String, Object>> kmsProviders = new HashMap<>();
kmsProviders.put("aws", providerDetails);
return kmsProviders;
}
public ClientEncryption getClientEncryption() {
return ClientEncryptions.create(ClientEncryptionSettings.builder()
.keyVaultMongoClientSettings(MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(this.dbConnection))
.build())
.keyVaultNamespace(this.encryptionVaultDatabase + "." + this.encryptionVaultCollection)
.kmsProviders(this.getKmsProvider())
.build());
}
public DataKeyOptions getDataKeyOptions() {
return new DataKeyOptions().masterKey(
new BsonDocument()
.append("region", new BsonString(this.encryptionKmsRegion))
.append("key", new BsonString(this.encryptionKmsKey))
)
.keyAltNames(Collections.singletonList(this.encryptionVaultName));
}
}
Log Error:
Exception at buildOrValidateVault(): Exception opening connection to Key Management Service
com.mongodb.MongoSocketOpenException: Exception opening connection to Key Management Service
at com.mongodb.client.internal.KeyManagementService.stream(KeyManagementService.java:57)
at com.mongodb.client.internal.Crypt.decryptKey(Crypt.java:299)
at com.mongodb.client.internal.Crypt.decryptKeys(Crypt.java:289)
at com.mongodb.client.internal.Crypt.executeStateMachine(Crypt.java:242)
at com.mongodb.client.internal.Crypt.createDataKey(Crypt.java:155)
at com.mongodb.client.internal.ClientEncryptionImpl.createDataKey(ClientEncryptionImpl.java:50)
at com.example.student.nosql.config.kms.KmsHandlerAws.buildOrValidateVault(KmsHandlerAws.java:40)
at com.example.student.nosql.config.MongoEncryptionConfig.buildOrValidateVault(MongoEncryptionConfig.java:77)
at com.example.student.nosql.config.MongoEncryptionConfig.autoEncryptionSettings(MongoEncryptionConfig.java:68)
at com.example.student.nosql.config.MongoEncryptionConfig.getAutoEncryptMongoClientSettings(MongoEncryptionConfig.java:59)
at com.example.student.nosql.config.MongoEncryptionConfig.mongoClient(MongoEncryptionConfig.java:110)
at org.springframework.data.mongodb.config.AbstractMongoClientConfiguration.mongoDbFactory(AbstractMongoClientConfiguration.java:71)
at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d.CGLIB$mongoDbFactory$3(<generated>)
at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d$$FastClassBySpringCGLIB$$6e240ce0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d.mongoDbFactory(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:484)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$172/0x00000000b0807980.getObject(Unknown Source)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.resolveBeanReference(ConfigurationClassEnhancer.java:394)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:366)
at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d.mongoDbFactory(<generated>)
at org.springframework.data.mongodb.config.AbstractMongoClientConfiguration.mongoTemplate(AbstractMongoClientConfiguration.java:58)
at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d.CGLIB$mongoTemplate$2(<generated>)
at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d$$FastClassBySpringCGLIB$$6e240ce0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d.mongoTemplate(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:484)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$172/0x00000000b0807980.getObject(Unknown Source)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:330)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:113)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1699)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1444)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$172/0x00000000b0807980.getObject(Unknown Source)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1287)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:885)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:228)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1358)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$172/0x00000000b0807980.getObject(Unknown Source)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:454)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:543)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:513)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:653)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:224)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$172/0x00000000b0807980.getObject(Unknown Source)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1287)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:885)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:228)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1358)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$172/0x00000000b0807980.getObject(Unknown Source)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
at com.example.student.StudentApplication.main(StudentApplication.java:16)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:51)
at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:597)
Caused by: java.net.SocketTimeoutException: connect timed out
at java.base/java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.base/java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.base/java.net.SocksSocketImpl.connect(Unknown Source)
at java.base/java.net.Socket.connect(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.connect(Unknown Source)
at com.mongodb.client.internal.KeyManagementService.stream(KeyManagementService.java:54)
... 131 more

I don't think this is supported.
The contents of the KMS request is constructed by libmongocrypt; the request itself is performed by the driver. The payload being sent is opaque to the driver. This is described under MONGOCRYPT_CTX_NEED_KMS state in https://github.com/mongodb/libmongocrypt/blob/master/integrating.md.
I find it unlikely that you would be able to use a proxy with the described integration flow because:
The payload must be correctly constructed by libmongocrypt to account for the request being proxied (for example, to use the full URL including the protocol and host in the HTTP URI).
The driver needs to be told about the proxy. To my knowledge there isn't any such guidance across drivers. Generally speaking, proxy configuration in different environments is different.
The language as written doesn't (to me) have any indicators that the proxy use case was considered.
Looking at the Ruby driver implementation of this flow (https://github.com/mongodb/mongo-ruby-driver/blob/master/lib/mongo/crypt/encryption_io.rb feed_kms method), the driver creates a socket directly to the requested host/port. There is no provision for using proxies.
If you are a paying customer I suggest submitting this request through official support channels. Otherwise I suggest adding it to https://feedback.mongodb.com/.

Related

How to use multiple Zookeeper with distributed state machine?

I'm trying to use distributed states in my application with zookeeper just like in the Spring document, with only one difference. My application works fine with one zookeeper but I need multiple zookeeper address. Here is my configuration:
import jpapersistsm.enums.Events;
import jpapersistsm.enums.States;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachineFactory;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.data.jpa.JpaPersistingStateMachineInterceptor;
import org.springframework.statemachine.data.jpa.JpaStateMachineRepository;
import org.springframework.statemachine.ensemble.StateMachineEnsemble;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.persist.StateMachineRuntimePersister;
import org.springframework.statemachine.service.DefaultStateMachineService;
import org.springframework.statemachine.service.StateMachineService;
import org.springframework.statemachine.state.State;
import org.springframework.statemachine.zookeeper.ZookeeperStateMachineEnsemble;
import java.util.EnumSet;
#Slf4j
#Configuration
#EnableStateMachineFactory
public class JpaPersistStateMachineConfiguration extends StateMachineConfigurerAdapter<States, Events> {
#Autowired
public JpaStateMachineRepository jpaStateMachineRepository;
private Logger logger = LoggerFactory.getLogger(JpaPersistStateMachineConfiguration.class);
#Override
public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception{
states
.withStates()
.initial(States.ORDERED)
.end(States.PAYED)
.end(States.CANCELLED)
.states(EnumSet.allOf(States.class));
}
#Override
public void configure(StateMachineTransitionConfigurer<States,Events> transitions) throws Exception {
transitions
.withExternal().source(States.ORDERED).target(States.ASSEMBLED).event(Events.assemble).and()
.withExternal().source(States.ASSEMBLED).target(States.DELIVERED).event(Events.deliver).and()
.withExternal().source(States.DELIVERED).target(States.PAYED).event(Events.payment_received).and()
.withExternal().source(States.ORDERED).target(States.CANCELLED).event(Events.cancel).and()
.withExternal().source(States.ASSEMBLED).target(States.CANCELLED).event(Events.cancel).and()
.withExternal().source(States.DELIVERED).target(States.CANCELLED).event(Events.cancel);
}
#Override
public void configure(StateMachineConfigurationConfigurer<States,Events> config) throws Exception{
config
.withDistributed()
.ensemble(stateMachineEnsemble())
.and()
.withPersistence()
.runtimePersister(stateMachineRuntimePersister())
.and()
.withConfiguration()
.autoStartup(true);
}
#Bean
public StateMachineEnsemble<States, Events> stateMachineEnsemble() throws Exception {
return new ZookeeperStateMachineEnsemble<States, Events>(curatorClient(), "/app");
}
#Bean
public CuratorFramework curatorClient() throws Exception {
CuratorFramework client = CuratorFrameworkFactory
.builder()
.defaultData(new byte[0])
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
.connectString("localhost:2181,localhost:2182,localhost:2183")
.build();
client.start();
return client;
}
#Bean
public StateMachineRuntimePersister<States,Events,String> stateMachineRuntimePersister(){
return new JpaPersistingStateMachineInterceptor<>(jpaStateMachineRepository);
}
#Bean
public StateMachineService<States,Events> stateMachineService (
StateMachineFactory<States,Events> stateMachineFactory,
StateMachineRuntimePersister<States,Events,String> stateMachineRuntimePersister){
return new DefaultStateMachineService<>(stateMachineFactory, stateMachineRuntimePersister);
}
#Bean
public StateMachineListener<States, Events> listener() {
return new StateMachineListenerAdapter<States, Events>() {
#Override
public void stateChanged(State<States, Events> from, State<States, Events> to) {
logger.info("*** listener: in state changed");
if (from == null) logger.info("*** state machine initialised in state {}", to.getId());
else logger.info("*** state changed from {} to {}", from.getId(), to.getId());
}
};
}
}
And my REST Controller class is:
import jpapersistsm.enums.Events;
import jpapersistsm.enums.States;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.service.StateMachineService;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
#RestController
#RequestMapping("/jpapersist")
public class RestServiceController {
#Autowired
public StateMachineService<States, Events> stateMachineService;
#Autowired
public StateMachineListener listener;
public StateMachine<States, Events> stateMachine;
public Logger logger = LoggerFactory.getLogger(RestServiceController.class);
#RequestMapping(value="/init", method= RequestMethod.POST)
public void init(#RequestBody Map<String,String> parameters){
logger.info("\n*** inside of state machine controller : INIT ");
try {
stateMachine = getStateMachine(parameters.get("guid"));
} catch (Exception e) {
e.printStackTrace();
}
logger.info("\n*** state machine initialized to state: {}", stateMachine.getState().getId().name());
}
/***
Synchronized method to obtain persisted state machine from database.
*/
public synchronized StateMachine<States,Events> getStateMachine(String machineId) throws Exception {
if (stateMachine == null) {
stateMachine = stateMachineService.acquireStateMachine(machineId);
stateMachine.addStateListener(listener);
stateMachine.start();
} else if (!ObjectUtils.nullSafeEquals(stateMachine.getId(), machineId)) {
stateMachineService.releaseStateMachine(stateMachine.getId());
stateMachine.stop();
stateMachine = stateMachineService.acquireStateMachine(machineId);
stateMachine.addStateListener(listener);
stateMachine.start();
}
return stateMachine;
}
}
When I send a request for initialize a state machine, getting an error like:
Unable to persist stateMachineContext
Caused by: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): org.springframework.statemachine.data.jpa.JpaRepositoryStateMachine
at org.hibernate.id.Assigned.generate(Assigned.java:33) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:119) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:800) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_222]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_222]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_222]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_222]
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350) ~[spring-orm-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at com.sun.proxy.$Proxy117.persist(Unknown Source) ~[na:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_222]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_222]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_222]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_222]
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:309) ~[spring-orm-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at com.sun.proxy.$Proxy117.persist(Unknown Source) ~[na:na]
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:535) ~[spring-data-jpa-2.1.10.RELEASE.jar:2.1.10.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_222]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_222]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_222]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_222]
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:359) ~[spring-data-commons-2.1.10.RELEASE.jar:2.1.10.RELEASE]
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200) ~[spring-data-commons-2.1.10.RELEASE.jar:2.1.10.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:644) ~[spring-data-commons-2.1.10.RELEASE.jar:2.1.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:608) ~[spring-data-commons-2.1.10.RELEASE.jar:2.1.10.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$invoke$3(RepositoryFactorySupport.java:595) ~[spring-data-commons-2.1.10.RELEASE.jar:2.1.10.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:595) ~[spring-data-commons-2.1.10.RELEASE.jar:2.1.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.1.10.RELEASE.jar:2.1.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295) ~[spring-tx-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.1.9.RELEASE.jar:5.1.9.RELEASE]
... 111 common frames omitted
The state of the machine seems to changed, but could not persist on db. As I said, the problem is my curator configuration. Because it works fine when I define connectString with single Zookeeper like
.connectString("localhost:2181")
I'm new to Zookeeper and Curator, and open to any help. Thanks in advance.
The problem is with this configuration:
.withConfiguration()
.autoStartup(true);
Because it tries to start the machine, before having a machine id.

Unexpected error while Controller unit test

I am learning unit testing. I have implemented unit test for the spring boot controller in my sample project. When I run the test class, every time it returns 400 status (Expected 200). After i did a research and I have found that if(entity.getStatusCode().equals(HttpStatus.OK)) { is line which gives exception. It might be because it uses return of Service2.
However, code is working fine without running test cases. I have attached MyController and MyControllerTest classes.
My Controller
#RestController
#RequestMapping("/user")
public class UserController {
private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);
#Autowired
private UserManagementService userManageService;
#Autowired
private AdminManagementService adminManageService;
#Autowired
private AuthenticateManagementService authService;
#PutMapping("/change-password")
public ResponseEntity<?> changePassword(#RequestHeader("Authorization") String token,
#RequestBody PasswordChangeRequestDTO passwordChangeRequestDTO) {
ResponseDTO finalResponse = new ResponseDTO();
try {
LOGGER.info("Changing user password.");
KeycloakLoginResponseDTO keycloakResponse = authService.auhtenticate(passwordChangeRequestDTO.getLoginRequestDTO());
ResponseEntity<?> logoutEntity = authService.logout(token, keycloakResponse.getSession_state());
if(logoutEntity.getStatusCode().equals(HttpStatus.OK)) {
LOGGER.info("User password matched");
}
String userId = adminManageService.getUserByName(token, passwordChangeRequestDTO.getLoginRequestDTO().getUsername());
ResponseEntity<?> entity = userManageService.changePassword(token, passwordChangeRequestDTO, userId);
LOGGER.info("USER : " + "" +"has successfully changed password.");
finalResponse.setMessageCode(HttpStatus.OK);
finalResponse.setMessage("Password changed successfully");
finalResponse.setError(false);
ResponseEntity<ResponseDTO> finalEntity = ResponseEntity.ok().body(finalResponse);
return finalEntity;
}catch (Exception e) {
e.printStackTrace();
LOGGER.error("Error has occured while changing password of USER : " + "" + ".");
finalResponse.setMessageCode(HttpStatus.EXPECTATION_FAILED);
finalResponse.setMessage("Oops! Looks like you have entered the wrong password in the 'Old Password' field");
finalResponse.setMessageDetail(e.getMessage());
finalResponse.setError(true);
ResponseEntity<ResponseDTO> finalEntity = ResponseEntity.badRequest().body(finalResponse);
return finalEntity;
}
}
}
Controller Unit test class
#RunWith(SpringRunner.class)
#WebMvcTest(UserController.class)
public class UserControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private UserManagementService userManageService;
#MockBean
private AdminManagementService adminManageService;
#MockBean
private AuthenticateManagementService authService;
#InjectMocks
private UserController userController;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testChangePasswordhappyPath() throws Exception {
PasswordChangeRequestDTO passwordChangeRequestDTO = new PasswordChangeRequestDTO();
LoginRequestDTO loginRequestDTO = new LoginRequestDTO();
loginRequestDTO.setClient_id("test_client");
loginRequestDTO.setGrant_type("test_grant_type");
loginRequestDTO.setPassword("test_password");
loginRequestDTO.setUsername("test_user");
CredentialsRequestDTO credentialsRequestDTO = new CredentialsRequestDTO();
credentialsRequestDTO.setTemporary(false);
credentialsRequestDTO.setType("password");
credentialsRequestDTO.setValue("test_password");
passwordChangeRequestDTO.setLoginRequestDTO(loginRequestDTO);
passwordChangeRequestDTO.setCredentialsRequestDTO(credentialsRequestDTO);
ResponseEntity<String> mockResponse = new ResponseEntity<String>("", HttpStatus.OK);
when(userManageService.changePassword("Token", passwordChangeRequestDTO, "UserId")).thenReturn(mockResponse);
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(passwordChangeRequestDTO);
mockMvc.perform(put("/user/change-password", passwordChangeRequestDTO)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.header("Authorization", "Token")
.content(json)
.characterEncoding("utf-8"))
.andExpect(status().isOk()).andReturn();
}
}
What am i doing wrong here. Is there anything to add to my MyControllerTest class or How can i cover this test case. Any help would be grateful.
UPDATED
I have also added e.printStackTrace()
java.lang.NullPointerException
at com.mycode.controller.UserController.changePassword(UserController.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:919)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:663)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:71)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:166)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:182)
at com.mycode.controller.UserControllerTest.testChangePasswordhappyPath(UserControllerTest.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

Why does JerseyTest throw ConstraintViolationException instead of returning 400 Bad Request?

I am using Jersey version 2.23.2 and I am unable to figure out how to use JerseyTest to test the responses for when validation fails. For some reason, the below test throws a ConstraintViolationException which is wrapped in a ProcessingException instead of returning 400 Bad Request. I could modify the test to check that the ProcessingException is thrown, but I really want to test the response. When I run HelloResource in Grizzly without JerseyTest, I get the appropriate 400 Bad Request response. Any ideas on how to fix the badRequestResponse() test below?
package example;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import static org.junit.Assert.assertEquals;
public class BadRequestTest extends JerseyTest {
#XmlAccessorType(XmlAccessType.FIELD)
public static class Hello {
#NotNull(message = "Name is a required field.")
private final String name;
private Hello() {
this(null);
}
public Hello(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
#Path("hello")
public static class HelloResource {
#POST
public String sayHelloToMe(#Valid Hello hello) {
return "Hello " + hello.getName() + "!";
}
}
#Override
protected Application configure() {
return new ResourceConfig(HelloResource.class).property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
}
/** Test OK Response. This Works!*/
#Test
public void okResponse() {
Response response = target("hello")
.request(MediaType.TEXT_PLAIN)
.post(Entity.json(new Hello("Tiny Tim")));
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
assertEquals("Hello Tiny Tim!", response.readEntity(String.class));
}
/** Test Bad Request Response. This Fails! */
#Test
public void badRequestResponse() {
Response response = target("hello")
.request(MediaType.TEXT_PLAIN)
.post(Entity.json(new Hello(null)));
assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
}
}
Here's the exception I am getting:
javax.ws.rs.ProcessingException:
Exception Description: Constraints violated on marshalled bean:
example.BadRequestTest$Hello#456abb66
-->Violated constraint on property name: "Name is a required field.".
Internal Exception: javax.validation.ConstraintViolationException
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:261)
at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:684)
at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:681)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:681)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:437)
at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:343)
at example.BadRequestTest.badRequestResponse(BadRequestTest.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: Exception [EclipseLink-7510] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.BeanValidationException
Exception Description: Constraints violated on marshalled bean:
example.BadRequestTest$Hello#456abb66
-->Violated constraint on property name: "Name is a required field.".
Internal Exception: javax.validation.ConstraintViolationException
at org.eclipse.persistence.exceptions.BeanValidationException.constraintViolation(BeanValidationException.java:53)
at org.eclipse.persistence.jaxb.JAXBBeanValidator.buildConstraintViolationException(JAXBBeanValidator.java:385)
at org.eclipse.persistence.jaxb.JAXBBeanValidator.validate(JAXBBeanValidator.java:273)
at org.eclipse.persistence.jaxb.JAXBMarshaller.validateAndTransformIfNeeded(JAXBMarshaller.java:588)
at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:481)
at org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.writeTo(MOXyJsonProvider.java:949)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:265)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:250)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1130)
at org.glassfish.jersey.client.ClientRequest.doWriteEntity(ClientRequest.java:517)
at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:499)
at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:388)
at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:285)
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:252)
... 39 more
Caused by: javax.validation.ConstraintViolationException
at org.eclipse.persistence.jaxb.JAXBBeanValidator.buildConstraintViolationException(JAXBBeanValidator.java:383)
... 52 more
This is a client side problem. As you've discovered MOXy has bean validation on by default. So you are getting bean validation on the client. So the request is not even going through as the error is happening on the client. You could test this by just sending a string
Entity.json("{}")
That should get rid of the error. But if you want to use the bean, as you mentioned in the comment, you should disable the bean validation on the client with MOXy
#Override
protected void configureClient(final ClientConfig config) {
super.configureClient(config);
config.register(new MoxyJsonConfig()
.property(MarshallerProperties.BEAN_VALIDATION_MODE,
BeanValidationMode.NONE).resolver());
}

Servlet.service() for servlet [FitbitApiAuthExampleServlet] in context with path [/Webfit]

I'm having a problem.
I'm developing web application in Eclipse IDE and using Tomcat 7.
Everything was working fine, when suddenly my debugger doesn't work anymore as it should and everything collapsed to pieces. I was looking for same errors, but I haven't found soulution yet. Please help me.
I'm getting this error:
SEVERE: Servlet.service() for servlet [FitbitApiAuthExampleServlet] in context with path [/Webfit] threw exception
java.lang.NullPointerException
at java.net.URLEncoder.encode(Unknown Source)
at com.fitbit.api.client.http.OAuth.encode(OAuth.java:254)
at com.fitbit.api.client.http.OAuth.encodeParameters(OAuth.java:233)
at com.fitbit.api.client.http.OAuth.encodeParameters(OAuth.java:217)
at com.fitbit.api.client.http.OAuth.normalizeRequestParameters(OAuth.java:196)
at com.fitbit.api.client.http.OAuth.generateAuthorizationHeader(OAuth.java:85)
at com.fitbit.api.client.http.OAuth.generateAuthorizationHeader(OAuth.java:129)
at com.fitbit.api.client.http.HttpClient.setHeaders(HttpClient.java:522)
at com.fitbit.api.client.http.HttpClient.httpRequest(HttpClient.java:422)
at com.fitbit.api.client.http.HttpClient.get(HttpClient.java:398)
at com.fitbit.api.client.FitbitApiClientAgent.httpGet(FitbitApiClientAgent.java:2563)
at com.fitbit.api.client.FitbitApiClientAgent.httpGet(FitbitApiClientAgent.java:2513)
at com.fitbit.api.client.FitbitApiClientAgent.getLoggedHeartRate(FitbitApiClientAgent.java:1779)
at com.fitbit.web.FitbitApiAuthExampleServlet.doGet(FitbitApiAuthExampleServlet.java:108)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Servlet code:
package com.fitbit.web;
import com.fitbit.api.FitbitAPIException;
import com.fitbit.api.client.*;
import com.fitbit.api.client.service.FitbitAPIClientService;
import com.fitbit.api.common.model.body.Body;
import com.fitbit.api.common.model.body.BodyWithGoals;
import com.fitbit.api.common.model.bp.Bp;
import com.fitbit.api.common.model.heart.Heart;
import com.fitbit.api.common.model.user.UserInfo;
import com.fitbit.api.model.APIResourceCredentials;
import com.fitbit.api.model.FitbitUser;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.joda.time.LocalDate;
import java.io.IOException;
import java.util.Properties;
/**
* Created by IntelliJ IDEA.
* User: Kiryl
* Date: 6/22/11
* Time: 7:05 AM
*/
public class FitbitApiAuthExampleServlet extends HttpServlet {
public static final String OAUTH_TOKEN = "oauth_token";
public static final String OAUTH_VERIFIER = "oauth_verifier";
private FitbitAPIEntityCache entityCache = new FitbitApiEntityCacheMapImpl();
private FitbitApiCredentialsCache credentialsCache = new FitbitApiCredentialsCacheMapImpl();
private FitbitApiSubscriptionStorage subscriptionStore = new FitbitApiSubscriptionStorageInMemoryImpl();
private String apiBaseUrl;
private String fitbitSiteBaseUrl;
private String exampleBaseUrl;
private String clientConsumerKey;
private String clientSecret;
private FitbitUser fitbitUser = new FitbitUser("-");
private int year = 2012;
private int month = 5;
private int day = 5;
public void init(ServletConfig config) throws ServletException {
super.init(config);
try {
Properties properties = new Properties();
properties.load(getClass().getClassLoader().getResourceAsStream("config.properties"));
apiBaseUrl = properties.getProperty("apiBaseUrl");
fitbitSiteBaseUrl = properties.getProperty("fitbitSiteBaseUrl");
exampleBaseUrl = properties.getProperty("exampleBaseUrl").replace("/app", "");
clientConsumerKey = properties.getProperty("clientConsumerKey");
clientSecret = properties.getProperty("clientSecret");
} catch (IOException e) {
throw new ServletException("Exception during loading properties", e);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
FitbitAPIClientService<FitbitApiClientAgent> apiClientService = new FitbitAPIClientService<FitbitApiClientAgent>(
new FitbitApiClientAgent(apiBaseUrl, fitbitSiteBaseUrl, credentialsCache),
clientConsumerKey,
clientSecret,
credentialsCache,
entityCache,
subscriptionStore
);
if (request.getParameter("completeAuthorization") != null) {
// Get temporary token and verifier returned by Fitbit from query string
String tempTokenReceived = request.getParameter(OAUTH_TOKEN);
String tempTokenVerifier = request.getParameter(OAUTH_VERIFIER);
// Fetch user credentials from cache by temporary token from query string
APIResourceCredentials resourceCredentials = apiClientService.getResourceCredentialsByTempToken(tempTokenReceived);
/*Handle error when there is no record of credentials in cache for the temporary token provided
As implementation of the credentials cache in this example is not persistant,
this error will popup if you restart application, while user's browser will be on Fitbit*/
if (resourceCredentials == null) {
throw new ServletException("Unrecognized temporary token when attempting to complete authorization: " + tempTokenReceived);
}
// Call method of Fitbit4J to get token credentials only if necessary (they haven't been cached yet)
if (!resourceCredentials.isAuthorized()) {
resourceCredentials.setTempTokenVerifier(tempTokenVerifier); // The verifier token is required in the request to get token credentials
try {
apiClientService.getTokenCredentials(new LocalUserDetail(resourceCredentials.getLocalUserId())); // get token credentials for user
} catch (FitbitAPIException e) {
throw new ServletException("Unable to finish authorization with Fitbit.", e);
}
}
try {
// get UserInfo
UserInfo userInfo = apiClientService.getClient().getUserInfo(new LocalUserDetail(resourceCredentials.getLocalUserId()));
request.setAttribute("userInfo", userInfo);
//get HeartRate
Heart heartInfo = apiClientService.getClient().getLoggedHeartRate(new LocalUserDetail(resourceCredentials.getLocalUserId()), fitbitUser, new LocalDate(year,month,day));
//HeartRate heartAverage = new HeartRate(heartInfo.getTrackerAverage());
request.setAttribute("heartRate", heartInfo);
/*double weight = apiClientService.getClient().getWeight(new LocalUserDetail(resourceCredentials.getLocalUserId()), new FitbitUser("-"), new LocalDate(2012,5,5));
request.setAttribute("weight", weight);*/
// get BodyInfo (weight, fat, bmi)
Body bodyInfo = apiClientService.getClient().getBody(new LocalUserDetail(resourceCredentials.getLocalUserId()), fitbitUser, new LocalDate(year,month,day));
//BodyWithGoals bodyGoals = apiClientService.getClient().getBodyWithGoals(new LocalUserDetail(resourceCredentials.getLocalUserId()), new FitbitUser("-"), new LocalDate(year,month,day));
request.setAttribute("bodyInfo", bodyInfo);
// get BloodPressure (BP) Info
Bp bloodPressureInfo = apiClientService.getClient().getLoggedBp(new LocalUserDetail(resourceCredentials.getLocalUserId()), fitbitUser, new LocalDate(year,month,day));
request.setAttribute("bloodPressureInfo", bloodPressureInfo);
// forward result to .jsp page
request.getRequestDispatcher("/fitbitApiAuthExample.jsp").forward(request, response);
} catch (FitbitAPIException e) {
throw new ServletException("Exception during getting user info", e);
}
} else {
try {
response.sendRedirect(apiClientService.getResourceOwnerAuthorizationURL(new LocalUserDetail("-"), exampleBaseUrl + "/fitbitApiAuthExample?completeAuthorization="));
} catch (FitbitAPIException e) {
throw new ServletException("Exception during performing authorization", e);
}
}
}
}

GWT Uncaught exception escaped

I have created a new google application using GWT, and it runs fine. But when i click a button that is responsible for performing some action with the server side, it throws an unusual error. Please could someone offer some help? Thank you in advance :(
Here is the code:
package com.ukstudentfeedback.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.ukstudentfeedback.shared.FieldVerifier;
import com.ukstudentfeedback.client.MailClient;
import com.ukstudentfeedback.client.MailClientAsync;
public class Ukstudentfeedback implements EntryPoint{
private static final String SERVER_ERROR = "An error occurred while "
+ "attempting to contact the server. Please check your network "
+ "connection and try again.";
/**
* Create a remote service proxy to talk to the server-side Greeting service.
*/
private final MailClientAsync sendMessage = GWT
.create(MailClient.class);
// ...
public void onModuleLoad()
{
java.lang.System.out.println("I finally worked!");
final Button sendButton;
final TextBox toField, fromField, subjectField, messageField;
final Label errorLabel = new Label();
sendButton = new Button("Send");
toField = new TextBox();
fromField = new TextBox();
subjectField = new TextBox();
messageField = new TextBox();
sendButton.addStyleName("sendButton");
toField.setText("Testing");
// Add the nameField and sendButton to the RootPanel
// Use RootPanel.get() to get the entire body element
RootPanel.get("sendButton").add(sendButton);
RootPanel.get("To").add(toField);
RootPanel.get("From").add(fromField);
RootPanel.get("Subject").add(subjectField);
RootPanel.get("Message").add(messageField);
RootPanel.get("errorLabelContainer").add(errorLabel);
// Focus the cursor on the to field when the app loads
toField.setFocus(true);
toField.selectAll();
//sendButton.setEnabled(true);
// Create the popup dialog box
final DialogBox dialogBox = new DialogBox();
dialogBox.setText("Message Sent");
dialogBox.setAnimationEnabled(true);
final Button closeButton = new Button("Close");
// We can set the id of a widget by accessing its Element
closeButton.getElement().setId("closeButton");
final Label textToServerLabel = new Label();
final HTML serverResponseLabel = new HTML();
VerticalPanel dialogVPanel = new VerticalPanel();
dialogVPanel.addStyleName("dialogVPanel");
dialogVPanel.add(new HTML("<b>Message Sent:</b>"));
dialogVPanel.add(textToServerLabel);
dialogVPanel.add(new HTML("<br><b>Server replies:</b>"));
dialogVPanel.add(serverResponseLabel);
dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
dialogVPanel.add(closeButton);
dialogBox.setWidget(dialogVPanel);
// Add a handler to close the DialogBox
closeButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
dialogBox.hide();
sendButton.setEnabled(true);
sendButton.setFocus(true);
}
});
// Create a handler for the sendButton and nameField
class MyHandler implements ClickHandler{
/**
* Fired when the user clicks on the sendButton.
*/
public void onClick(ClickEvent event) {
java.lang.System.out.println("I have been clicked");
sendMessageToServer();
}
public void sendMessageToServer()
{
errorLabel.setText("");
String to = toField.getText();
String from = fromField.getText();
String subject = subjectField.getText();
String message = messageField.getText();
if (!FieldVerifier.isValidName(to, from, subject, message)) {
errorLabel.setText("Please enter at least four characters");
return;
}
sendButton.setEnabled(false);
textToServerLabel.setText("Hello");
serverResponseLabel.setText("");
sendMessage.sendMessage(to, from, subject, message, new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
// Show the RPC error message to the user
dialogBox
.setText("Message sending Failed");
serverResponseLabel
.addStyleName("serverResponseLabelError");
serverResponseLabel.setHTML(SERVER_ERROR);
dialogBox.center();
closeButton.setFocus(true);
}
public void onSuccess(String result) {
dialogBox.setText("Message Sent");
serverResponseLabel
.removeStyleName("serverResponseLabelError");
serverResponseLabel.setHTML(result);
dialogBox.center();
closeButton.setFocus(true);
}
});
}
}
// Add a handler to send the name to the server
MyHandler handler = new MyHandler();
sendButton.addClickHandler(handler);
}
}
Server side:
package com.ukstudentfeedback.server;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.ukstudentfeedback.shared.FieldVerifier;
#SuppressWarnings("serial")
public class MailServerImpl extends RemoteServiceServlet{
public void sendMessage(String to, String from, String subject, String message) throws IllegalArgumentException
{
// Verify that no input is null.
if (!FieldVerifier.isValidName(to, from, subject, message)) {
// If the input is not valid, throw an IllegalArgumentException back to
// the client.
throw new IllegalArgumentException(
"Name must be at least 4 characters long");
}
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
try
{
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from, "Admin"));
msg.addRecipient(Message.RecipientType.TO,
new InternetAddress(to, "Mr. User"));
msg.setSubject(subject);
msg.setText(message);
Transport.send(msg);
}
catch (AddressException e)
{
// ...
e.printStackTrace();
} catch (MessagingException e)
{
// ...
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Error Stack:
23:26:55.817 [ERROR] [ukstudentfeedback] Uncaught exception escaped
com.google.gwt.event.shared.UmbrellaException: One or more exceptions caught, see full set in UmbrellaException#getCauses
at com.google.gwt.event.shared.HandlerManager.fireEvent(HandlerManager.java:129)
at com.google.gwt.user.client.ui.Widget.fireEvent(Widget.java:129)
at com.google.gwt.event.dom.client.DomEvent.fireNativeEvent(DomEvent.java:116)
at com.google.gwt.user.client.ui.Widget.onBrowserEvent(Widget.java:177)
at com.google.gwt.user.client.DOM.dispatchEventImpl(DOM.java:1351)
at com.google.gwt.user.client.DOM.dispatchEvent(DOM.java:1307)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:337)
at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:218)
at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:213)
at sun.reflect.GeneratedMethodAccessor27.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:292)
at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:546)
at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:363)
at java.lang.Thread.run(Thread.java:680)
Caused by: com.google.gwt.user.client.rpc.ServiceDefTarget$NoServiceEntryPointSpecifiedException: Service implementation URL not specified
at com.google.gwt.user.client.rpc.impl.RemoteServiceProxy.doPrepareRequestBuilderImpl(RemoteServiceProxy.java:430)
at com.google.gwt.user.client.rpc.impl.RemoteServiceProxy.doInvoke(RemoteServiceProxy.java:368)
at com.google.gwt.user.client.rpc.impl.RemoteServiceProxy$ServiceHelper.finish(RemoteServiceProxy.java:74)
at com.ukstudentfeedback.client.MailClient_Proxy.sendMessage(MailClient_Proxy.java:38)
at com.ukstudentfeedback.client.Ukstudentfeedback$1MyHandler.sendMessageToServer(Ukstudentfeedback.java:118)
at com.ukstudentfeedback.client.Ukstudentfeedback$1MyHandler.onClick(Ukstudentfeedback.java:98)
at com.google.gwt.event.dom.client.ClickEvent.dispatch(ClickEvent.java:54)
at com.google.gwt.event.dom.client.ClickEvent.dispatch(ClickEvent.java:1)
at com.google.gwt.event.shared.GwtEvent.dispatch(GwtEvent.java:1)
at com.google.web.bindery.event.shared.EventBus.dispatchEvent(EventBus.java:40)
at com.google.web.bindery.event.shared.SimpleEventBus.doFire(SimpleEventBus.java:193)
at com.google.web.bindery.event.shared.SimpleEventBus.fireEvent(SimpleEventBus.java:88)
at com.google.gwt.event.shared.HandlerManager.fireEvent(HandlerManager.java:127)
at com.google.gwt.user.client.ui.Widget.fireEvent(Widget.java:129)
at com.google.gwt.event.dom.client.DomEvent.fireNativeEvent(DomEvent.java:116)
at com.google.gwt.user.client.ui.Widget.onBrowserEvent(Widget.java:177)
at com.google.gwt.user.client.DOM.dispatchEventImpl(DOM.java:1351)
at com.google.gwt.user.client.DOM.dispatchEvent(DOM.java:1307)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:337)
at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:218)
at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:213)
at sun.reflect.GeneratedMethodAccessor27.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:292)
at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:546)
at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:363)
at java.lang.Thread.run(Thread.java:680)
To find the cause of an UmbrellaException look for "Caused by":
Caused by:
com.google.gwt.user.client.rpc.ServiceDefTarget$NoServiceEntryPointSpecifiedException:
Service implementation URL not specified
Specify the remote service URL by doing either of the following:
Adding a RemoteServiceRelativePath annotation to your MailClientAsync interface.
Calling ServiceDefTarget#setServiceEntryPoint:
((ServiceDefTarget)sendMessage).
setServiceEntryPoint("http://www.example.com/service");