Cannot connect to mongoDB using Spring Data Reactive and Spring Boot 2.0 - ssl

I get the following error every time I trying to connect to MongoDB using Spring Data Reactive and Spring Boot 2.0.
Caused by: java.lang.UnsupportedOperationException: No SSL support in java.nio.channels.AsynchronousSocketChannel. For SSL support use com.mongodb.connection.netty.NettyStreamFactoryFactory
at com.mongodb.connection.AsynchronousSocketChannelStreamFactory.<init>(AsynchronousSocketChannelStreamFactory.java:41)
at com.mongodb.async.client.MongoClients.getStreamFactory(MongoClients.java:228)
at com.mongodb.async.client.MongoClients.create(MongoClients.java:177)
at com.mongodb.async.client.MongoClients.create(MongoClients.java:123)
at com.mongodb.reactivestreams.client.MongoClients.create(MongoClients.java:103)
at com.mongodb.reactivestreams.client.MongoClients.create(MongoClients.java:53)
at org.springframework.boot.autoconfigure.mongo.ReactiveMongoClientFactory.createNetworkMongoClient(ReactiveMongoClientFactory.java:123)
at org.springframework.boot.autoconfigure.mongo.ReactiveMongoClientFactory.createMongoClient(ReactiveMongoClientFactory.java:69)
at org.springframework.boot.autoconfigure.mongo.ReactiveMongoAutoConfiguration.reactiveStreamsMongoClient(ReactiveMongoAutoConfiguration.java:67)
at org.springframework.boot.autoconfigure.mongo.ReactiveMongoAutoConfiguration$$EnhancerBySpringCGLIB$$94536095.CGLIB$reactiveStreamsMongoClient$1(<generated>)
at org.springframework.boot.autoconfigure.mongo.ReactiveMongoAutoConfiguration$$EnhancerBySpringCGLIB$$94536095$$FastClassBySpringCGLIB$$2171f816.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358)
at org.springframework.boot.autoconfigure.mongo.ReactiveMongoAutoConfiguration$$EnhancerBySpringCGLIB$$94536095.reactiveStreamsMongoClient(<generated>)
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.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:587)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1246)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1093)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:534)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:491)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:250)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1128)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1056)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:833)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:740)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:466)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1246)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1093)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:534)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:491)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:250)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1128)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1056)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:833)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:740)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:466)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1246)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1093)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:534)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:491)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1604)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1349)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:574)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:491)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:250)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1128)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1056)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:570)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:358)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1337)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:574)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:491)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:751)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:865)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:809)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:404)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:347)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:128)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:102)
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:243)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:226)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:245)
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:189)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
The error message tells me to use NettyStreamFactoryFactory for SSL support. Does anyone have any examples on how to do this? The database I am trying to connect to is MongoDB Atlas, it strictly require a SSL connection.
Below is the rest of my code:
#SpringBootApplication
public class FlixMovieApiReactiveApplication {
public static void main(String[] args) {
SpringApplication.run(FlixMovieApiReactiveApplication.class, args);
}
// Add Data
#Bean
public CommandLineRunner initDatabase(MovieRepository repository) {
// entire process blocking, done in beginning
Flux<Movie> movieList = Flux.just(
new Movie("movie1", "1", "movie1"),
new Movie("movie2", "1", "movie2"),
new Movie("movie3", "5", "movie3"),
new Movie("movie4", "1", "movie4"),
new Movie("movie5", "3", "movie5"),
new Movie("movie6", "1", "movie6"),
new Movie("movie7", "2", "movie7"),
new Movie("movie8", "3", "movie8"),
new Movie("movie9", "1", "movie9"),
new Movie("movie10", "2", "movie10"),
new Movie("movie11", "1", "movie11"),
new Movie("movie12", "3", "movie12"),
new Movie("movie13", "1", "movie13"),
new Movie("movie14", "4", "movie14"),
new Movie("movie15", "1", "movie15"),
new Movie("movie16", "4", "movie16")
);
// delete then insert data. blockLast(), allows something to subscribe to pipeline, block for last emitted element
// data is written to the database.
return args -> repository.deleteAll().thenMany(repository.save(movieList)).blockLast();
}
}
#RestController
public class MovieRestController {
#Autowired
private MovieService movieService;
#GetMapping(value = "/movies")
public Flux<ResponseEntity<Movie>> list() {
return movieService.list().map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
#GetMapping(value = "/moviesByRating")
public Flux<ResponseEntity<Movie>> findByRating(
#RequestParam(value = "rating", required = false) final String rating) {
return movieService.findByRating(rating)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
#GetMapping("/movies/{movieId}")
public Mono<ResponseEntity<Movie>> read(
#PathVariable("movieId") final String movieId) {
return movieService.read(movieId)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK))
.defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
#DeleteMapping("/movies/{movieId}")
public Mono<ResponseEntity<Movie>> delete(
#PathVariable("movieId") final String movieId) {
return movieService.delete(movieId)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK))
.defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
#PutMapping("/movies/{movieId}")
public Mono<ResponseEntity<Movie>> update(
#PathVariable("movieId") final String movieId,
#RequestBody final MovieRequest movieRequest) {
return movieService.update(movieId, movieRequest)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK))
.defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
#PostMapping("/movies")
public Mono<ResponseEntity<Movie>> create(
#RequestBody final Mono<MovieRequest> movieRequest) {
return movieService.create(movieRequest)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK))
.defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
}
#Service
public class MovieServiceImpl implements MovieService {
#Autowired
private MovieRepository movieRepository;
#Override
public Flux<Movie> list(){
return movieRepository.findAll();
}
#Override
public Flux<Movie> findByRating(final String rating){
return movieRepository.findByRating(rating);
}
#Override
public Mono<Movie> update(String id, MovieRequest movieRequest) {
return movieRepository.findOne(id).map(existingMovie -> {
if(movieRequest.getDescription() != null){
existingMovie.setDescription(movieRequest.getDescription());
}
if(movieRequest.getRating() != null){
existingMovie.setRating(movieRequest.getRating());
}
if(movieRequest.getTitle() != null) {
existingMovie.setTitle(movieRequest.getTitle());
}
return existingMovie;
}).then(movieRepository::save);
}
#Override
public Mono<Movie> create(Mono<MovieRequest> movieRequest) {
return movieRequest.map(newMovie -> {
Movie movie = new Movie();
if(newMovie.getDescription() != null){
movie.setDescription(newMovie.getDescription());
}
if(newMovie.getRating() != null){
movie.setRating(newMovie.getRating());
}
if(newMovie.getTitle() != null) {
movie.setTitle(newMovie.getTitle());
}
return movie;
}).then(movieRepository::save);
}
#Override
public Mono<Movie> read(String id) {
return movieRepository.findOne(id);
}
#Override
public Mono<Movie> delete(String id) {
return movieRepository.findOne(id)
.flatMap(oldValue -> movieRepository.delete(id).then(Mono.just(oldValue)))
.singleOrEmpty();
}
}
#Repository
public interface MovieRepository extends ReactiveMongoRepository<Movie, String> {
Flux<Movie> findByRating(String rating);
}
#Document
public class Movie {
#Id
private String id;
private String title;
private String rating;
private String description;
public Movie(String title, String rating, String description) {
this.title = title;
this.rating = rating;
this.description = description;
}
public Movie() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getRating() {
return rating;
}
public void setRating(String rating) {
this.rating = rating;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
---
spring:
data:
mongodb:
uri: mongodb://admin:xxxxxx#movie-shard-00-00-xfzg4.mongodb.net:27017,movie-shard-00-01-xfzg4.mongodb.net:27017,movie-shard-00-02-xfzg4.mongodb.net:27017/movie?ssl=true&replicaSet=Movie-shard-0&authSource=admin
management:
context-path: /admin
server:
port: 8080
Below is the pom.xml file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.flix.movie</groupId>
<artifactId>flix-movie-api-reactive</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>flix-movie-api-reactive</name>
<description>Demo project for Spring Boot using Non-Blocking Reactive Spring Web MVC and Spring Data MongoDB</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<docker.image.prefix>flix</docker.image.prefix>
<docker.spotify.plugin.version>0.4.5</docker.spotify.plugin.version>
<swagger.version>2.4.0</swagger.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-dependencies-web-reactive</artifactId>
<version>0.1.0.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Package as a docker image -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>${docker.spotify.plugin.version}</version>
<configuration>
<serverId>docker-hub</serverId>
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<imageTags>
<imageTag>${project.version}</imageTag>
</imageTags>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>

Try
in connection String
xxxx?ssl=true&sslInvalidHostNameAllowed=true&streamType=netty
or Via MongoClientSettings
EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); // make sure application shuts this down
#Bean
public MongoClient getClient()
{
return MongoClients.create(MongoClientSettings.builder()
.clusterSettings(ClusterSettings.builder()
.hosts(Arrays.asList(new ServerAddress()))
.build())
.streamFactoryFactory(NettyStreamFactoryFactory.builder()
.eventLoopGroup(eventLoopGroup).build())
.sslSettings(SslSettings.builder()
.enabled(true)
.build())
.build());
}
#PreDestroy
public void shutDownEventLoopGroup() {
eventLoopGroup.shutdownGracefully();
}
Reference

This sounds like a Spring Data Mongo and/or Spring Boot issue.
At first it seems Spring Boot is giving the appropriate information to the Spring Data Mongo client configuration.
Could you create an issue on the dedicated issue tracker for Spring Data Mongo?

As mp911de mentioned above, adding Netty dependency in your pom will solve the problem.
For me, adding the spring-boot-starter-webflux resolved the issue.

It's the MongoClient who is responsible for managing the connection. In your case it is the default unprotected one, so if you have security enabled on your Mongo instance he will bounce back.
#Configuration
#EnableReactiveMongoRepositories
class MongoConfig : AbstractReactiveMongoConfiguration() {
override fun reactiveMongoClient(): MongoClient = MongoClients.create()
override fun getDatabaseName(): String = "mydb"
}
This is my configuration for reactive mongo in spring boot 2 M4. You can customize your client via MongoClients methods or appropriate constructor.

Related

Sleuth not working for websocket client

I have a microservice which is connecting to the WebSocket server, and receiving the messages from the server. I want to integrate Sleuth in this application, as this is the gateway for my set of microservices. But when I connect to the WebSocket server and start receiving messages, I can't traceId, spanid in the log in the log. I was expecting something like:
2018-08-09 11:26:20.222 INFO [kumarman-betsync-adapter-service-v2,0a011711c2470359,0a011711c2470359,true] 7230 --- [ient-SecureIO-2] c.b.b.a.service.BetSyncEventIdExtractor : SubscribeResponse feed received for eventId=7519016
2018-08-09 11:26:20.224 INFO [kumarman-betsync-adapter-service-v2,0a011711c2470359,2b028dadad5c440d,true] 7230 --- [ient-SecureIO-2] c.b.b.a.k.message.KafkaMessageSender : sent payload to topic='betsyncEventTopic'
But I am getting:
2018-08-09 11:26:20.222 INFO [kumarman-betsync-adapter-service-v2,,,] 7230 --- [ient-SecureIO-2] c.b.b.a.service.BetSyncEventIdExtractor : SubscribeResponse feed received for eventId=7519016
2018-08-09 11:26:20.224 INFO [kumarman-betsync-adapter-service-v2,,,] 7230 --- [ient-SecureIO-2] c.b.b.a.k.message.KafkaMessageSender : sent payload to topic='betsyncEventTopic'
my code is as follows:
#Service
#Slf4j
#AllArgsConstructor
public class BetsyncWebsocketAdapter {
private final BetsyncWebSocketHandler betsyncWebSocketHandler;
public void startNewConnection() {
try {
webSocketSession = new StandardWebSocketClient().doHandshake(
betsyncWebSocketHandler,
new WebSocketHttpHeaders(),
new URI(getBetsyncConnectionUrl()))
.get(KafkaAdminClient.MAX_TIME_LIMIT_TO_CONNECT, TimeUnit.SECONDS);
} catch (Exception e) {
log.error("exception occurred", e);
}
}
/**
* This will start the new connection after server start
*/
#EventListener(ApplicationReadyEvent.class)
public void onServerStart() {
startNewConnection();
}
}
#Slf4j
#Service
#AllArgsConstructor
public class BetsyncWebSocketHandler extends TextWebSocketHandler {
private static StringBuilder betSyncMessage = new StringBuilder();
private final LoginRequestBuilder loginRequestBuilder;
private final BetsyncMessageProcessing betsyncMessageProcessing;
#Override
public void afterConnectionEstablished(final WebSocketSession session) throws IOException {
session.sendMessage(new TextMessage(loginRequestBuilder.getLoginRequestDto()));
}
#Override
protected void handleTextMessage(final WebSocketSession session, final TextMessage message) {
betSyncMessage.append(message.getPayload());
if (message.isLast()) {
betsyncMessageProcessing.process(betSyncMessage.toString());
betSyncMessage = new StringBuilder();
} else {
log.debug("we have received a partial message starting with {}", getFirstXCharacter(message.getPayload(), 50));
}
}
#Override
protected void handlePongMessage(final WebSocketSession session, final PongMessage message) {
log.info("Response for Ping message received from the server");
}
#Override
public boolean supportsPartialMessages() {
return true;
}
#Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
log.error("server connection closed");
}
}
Our pom entries are:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<spring.boot.version>2.0.3.RELEASE</spring.boot.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
You're creating the socket handling by yourself
webSocketSession = new StandardWebSocketClient().doHandshake(
betsyncWebSocketHandler,
new WebSocketHttpHeaders(),
new URI(getBetsyncConnectionUrl()))
.get(KafkaAdminClient.MAX_TIME_LIMIT_TO_CONNECT, TimeUnit.SECONDS);
Spring Cloud Sleuth supports WebSockets, when you use Spring Integration components directly. Since you're doing things manually, you have to ensure that the tracing context gets propagated and that you can read it yourself.

Jersey 2 - with .target HTTPS

I've been trying to perform a POST from a jersey client but continue to run into the following exception:
Caused by: java.lang.IllegalStateException: Already connected
at sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(HttpURLConnection.java:3071)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.setRequestProperty(HttpsURLConnectionImpl.java:325)
at org.glassfish.jersey.client.internal.HttpUrlConnector.setOutboundHeaders(HttpUrlConnector.java:424)
at org.glassfish.jersey.client.internal.HttpUrlConnector.lambda$_apply$0(HttpUrlConnector.java:381)
at org.glassfish.jersey.message.internal.CommittingOutputStream.commitStream(CommittingOutputStream.java:195)
at org.glassfish.jersey.message.internal.CommittingOutputStream.commitStream(CommittingOutputStream.java:189)
at org.glassfish.jersey.message.internal.CommittingOutputStream.commit(CommittingOutputStream.java:257)
at org.glassfish.jersey.message.internal.OutboundMessageContext.commitStream(OutboundMessageContext.java:825)
at org.glassfish.jersey.client.ClientRequest.doWriteEntity(ClientRequest.java:553)
at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:498)
at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:384)
at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:282)
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:278)
... 63 more
I've tried a ton of answers and solutions in SO with no luck.
Going crazy here, please help!
public class JerseyWithSSL {
public static javax.ws.rs.client.Client getRESTClient() {
try {
TrustManager[] trustMgr = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted1(X509Certificate[] certs,
String authType) {
}
public void checkServerTrusted1(X509Certificate[] certs,
String authType) {
}
#Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
#Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
}};
SSLContext context = SSLContext.getInstance("SSL");
context.init(null, trustMgr, null);
javax.ws.rs.client.Client client = ClientBuilder.newBuilder().sslContext(context)
.hostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String arg0, SSLSession arg1) {
// TODO Auto-generated method stub
return true;
}
}).build();
return client;
} catch (NoSuchAlgorithmException | KeyManagementException ex) {
Logger.getLogger(JerseyWithSSL.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}
Code which uses the above class (exception thrown here):
// send notification to all subscriptors for event: attendee.create
if (!subscriptions.isEmpty()) {
try {
Client client = JerseyWithSSL.getRESTClient();
for (Subscription sub : subscriptions) {
System.out.println("Subscription: \n" + sub.getEventName() + "\n" + sub.getTargetUrl());
Response resp = client.target(sub.getTargetUrl())
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(newAttdee, MediaType.APPLICATION_JSON));
System.out.println("Status: " + resp.getStatus());
System.out.println(resp.getEntity().toString());
resp.close();
}
} catch (Exception ex) {
Logger.getLogger(AttendeeResource.class.getName()).log(Level.SEVERE, null, ex);
}
}
Adding pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ON24Hooks</groupId>
<artifactId>ON24_Zapier_Hooks</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>ON24_Zapier_Hooks</name>
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>jersey-apache-connector</artifactId>
<version>2.16</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${endorsed.dir}</outputDirectory>
<silent>true</silent>
<artifactItems>
<artifactItem>
<groupId>javax</groupId>
<artifactId>javaee-endorsed-api</artifactId>
<version>7.0</version>
<type>jar</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
The IllegalStateException: Already connected is probably masking a SSLHandshakeException, as described in the issue #3000 (previously referenced as JERSEY-2728).
According to the release notes, it was fixed in Jersey 2.23. I would upgrade Jersey to the most recent version though.
I spent some time to figure it out how it is been done in Jersey 2.x. Thanks to Jersey Migration Guide to help me out.
Below is code snippet for how client is build in Jersey 2.x for HTTPS call
public Client getRESTClient() {
TrustManager[] trustMgr= new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted1(X509Certificate[] certs,
String authType) {
}
public void checkServerTrusted1(X509Certificate[] certs,
String authType) {
}
#Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
#Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
} };
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, trustMgr, null);
Client client = ClientBuilder.newBuilder().sslContext(context)
.hostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String arg0, SSLSession arg1) {
// TODO Auto-generated method stub
return true;
}
}).build();
return client;
}
Just exception can be occur at any point while it may be SSL certificate validation also which can also current socket layer connection to validate SSLContext.Please debug out try catch block thoroughly also make the execution of your http request with other client also as well from Java Url URLCONNECTION
The IllegalStateException: Already connected is probably masking a SSLHandshakeException. The way to verify/debug this is to use the following JVM flags:
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack
This will cause the JVM to print out a whole bunch of debug information regarding SSL and will show the SSL exception if there is one.

Null Pointer Exception in POST method in jersey

I am building a web project using jersey and hibernate. I am testing crud operations in postman. For POST method i get a null pointer exception and I don't know how to solve. Please help me. I am new in jersey.
Below is my code and my full stack trace.
BookRepository.com
package com.bookstrore.repository;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Transaction;
import org.hibernate.Session;
import org.hibernate.Query;
import com.bookstrore.model.Book;
import com.bookstrore.model.SessionUtil;
//import com.pluralsight.model.User;
public class BookRepositoryStub {
public void createBook(Book book) {
Session session = SessionUtil.getSession();
Transaction tx = session.beginTransaction();
createBook(session,book);
tx.commit();
session.close();
}
private void createBook(Session session, Book bo){
Book book=new Book();
book.setBook_id(bo.getBook_id());
book.setBook_title(bo.getBook_title());
book.setBook_author(bo.getBook_author());
book.setBook_description(bo.getBook_description());
book.setBook_price(bo.getBook_price());
session.save(book);
}
public List<Book> getBooks(){
Session session = SessionUtil.getSession();
Query query = session.createQuery("from Book");
List<Book> books = query.list();
session.close();
return books;
}
public int delete(int book_id){
Session session = SessionUtil.getSession();
Transaction tx = session.beginTransaction();
String hql = "delete from Book where book_id = :book_id";
Query query = session.createQuery(hql);
query.setInteger("book_id",book_id);
int rowCount = query.executeUpdate();
System.out.println("Rows affected: " + rowCount);
tx.commit();
session.close();
return rowCount;
}
public int update(int book_id, Book bo){
if(book_id <=0)
return 0;
Session session = SessionUtil.getSession();
Transaction tx = session.beginTransaction();
String hql = "update Book set book_title = :book_title, book_author = :book_author, book_description = :book_description, book_price = :book_price, where book_id = :book_id";
Query query = session.createQuery(hql);
query.setInteger("book_id", book_id);
query.setString("book_title",bo.getBook_title());
query.setString("book_author",bo.getBook_author());
query.setString("book_description",bo.getBook_description());
query.setInteger("book_price",bo.getBook_price());
int rowCount = query.executeUpdate();
System.out.println("Rows affected: " + rowCount);
tx.commit();
session.close();
return rowCount;
}
}
BookResource.java
package com.bookstrore;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import com.bookstrore.model.Book;
//import com.ebook.model.User;
//import com.ebook.repository.BookRepository;
import com.bookstrore.repository.BookRepositoryStub;
#Path("books")
public class BookResource {
//private BookRepository bookRepository=new BookRepositoryStub();
#GET
#Produces("application/json")
public List<Book> getBook() {
BookRepositoryStub book = new BookRepositoryStub();
List books = book.getBooks();
return books;
}
#DELETE
#Path("{bookId}")
#Consumes("application/json")
public Response delete(#PathParam("bookId") int book_id){
BookRepositoryStub book = new BookRepositoryStub();
int count = book.delete(book_id);
if(count==0){
return Response.status(Response.Status.BAD_REQUEST).build();
}
return Response.ok().build();
}
#PUT
#Path("{bookId}")
//#Consumes(MediaType.APPLICATION_JSON)
#Consumes("application/json")
public Response update(#PathParam("bookId") int book_id, Book bo){
BookRepositoryStub book = new BookRepositoryStub();
int count = book.update(book_id, bo);
if(count==0){
return Response.status(Response.Status.BAD_REQUEST).build();
}
return Response.ok().build();
}
#POST
#Path("book")
#Consumes("application/json")
//#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response createBook(Book bo){
bo.setBook_title(bo.getBook_title());
bo.setBook_author(bo.getBook_author());
bo.setBook_description(bo.getBook_description());
bo.setBook_price(bo.getBook_price());
BookRepositoryStub book = new BookRepositoryStub();
book.createBook(bo);
return Response.ok().build();
}
}
Book.java
package com.bookstrore.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="book")
public class Book {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int book_id;
#Column
private String book_title;
#Column
private String book_author;
#Column
private String book_description;
#Column
private int book_price;
public int getBook_id() {
return book_id;
}
public void setBook_id(int book_id) {
this.book_id = book_id;
}
public String getBook_title() {
return book_title;
}
public void setBook_title(String book_title) {
this.book_title = book_title;
}
public String getBook_author() {
return book_author;
}
public void setBook_author(String book_author) {
this.book_author = book_author;
}
public String getBook_description() {
return book_description;
}
public void setBook_description(String book_description) {
this.book_description = book_description;
}
public int getBook_price() {
return book_price;
}
public void setBook_price(int book_price) {
this.book_price = book_price;
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bookstore</groupId>
<artifactId>BookStore</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>BookStore</name>
<build>
<finalName>BookStore</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
<version>2.22.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.10.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
</dependencies>
<properties>
<jersey.version>2.22.1</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.bookstrore</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/webapi/*</url-pattern>
</servlet-mapping>
</web-app>
Stack Trace:
<pre>java.lang.NullPointerException
com.bookstrore.BookResource.createBook(BookResource.java:72)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144)
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161)
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160)
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99)
org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389)
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347)
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
org.glassfish.jersey.internal.Errors.process(Errors.java:315)
org.glassfish.jersey.internal.Errors.process(Errors.java:297)
org.glassfish.jersey.internal.Errors.process(Errors.java:267)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:471)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:425)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:383)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:336)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:223)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
</pre>
I am looking forward for your help! Please! Thank you!
I believe that there are two problems in your code that by changing them, your problem will be solved.
First of all, in your class "Book" you need to write the constructor with all the parameters, besides the id (that is auto-generated by hibernate), and also have a no-argument constructor. So add this:
And on the other hand, you have to declare your class "Book" as #XmlRootElement as you did with #Entity and #Table.
This video explains the why of all of this and it is also a great tutorial for beginners with web services and jersey:
https://www.youtube.com/watch?v=BaZdlJSts5A&list=PLqq-6Pq4lTTZh5U8RbdXq0WaYvZBz2rbn&index=14
Hope this helps! Your Book class should look like this:
#Entity
#Table(name="book")
#XmlRootElement
public class Book {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int book_id;
#Column
private String book_title;
#Column
private String book_author;
#Column
private String book_description;
#Column
private int book_price;
public Book(){ }
public Book(String title, String author, String description, int price){
book_title = title;
book_author = author;
book_description = description;
book_price = price;
}
public int getBook_id() {
return book_id;
}
public void setBook_id(int book_id) {
this.book_id = book_id;
}
public String getBook_title() {
return book_title;
}
public void setBook_title(String book_title) {
this.book_title = book_title;
}
public String getBook_author() {
return book_author;
}
public void setBook_author(String book_author) {
this.book_author = book_author;
}
public String getBook_description() {
return book_description;
}
public void setBook_description(String book_description) {
this.book_description = book_description;
}
public int getBook_price() {
return book_price;
}
public void setBook_price(int book_price) {
this.book_price = book_price;
}
}

Spring Data Rest Not Mapped

I am trying to use spring data rest. I have included its dependency in pom and defined following bean but no mapping is being created for repos. From where do I began to look for problem?
#Bean
public RepositoryRestConfigurer repositoryRestConfigurer(){
return new RepositoryRestConfigurerAdapter(){
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config){
config.setBasePath("/api");
}
};
}
following is pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<springframework.version>4.3.1.RELEASE</springframework.version>
<springsecurity.version>4.2.0.RELEASE</springsecurity.version>
<hibernate.core.version>4.3.11.Final</hibernate.core.version>
<hibernate.validator.version>5.1.3.Final</hibernate.validator.version>
<mysql.connector.version>5.1.31</mysql.connector.version>
<postgresql.version>9.4-1200-jdbc41</postgresql.version>
<joda-time.version>2.3</joda-time.version>
<jackson-version>2.7.5</jackson-version>
<maven-compiler-plugin-version>3.2</maven-compiler-plugin-version>
<maven-war-plugin-version>2.4</maven-war-plugin-version>
<source-jdk>1.8</source-jdk>
<target-jdk>1.8</target-jdk>
<war-source-directory>src/main/webapp</war-source-directory>
<war-name>dmapp</war-name>
<final-name>dmapp</final-name>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.7.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-webmvc</artifactId>
<version>2.6.1.RELEASE</version>
</dependency>
<!-- SPRING SECURITY -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.core.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.11.Final</version>
</dependency>
<!-- jsr303 validation -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate.validator.version}</version>
</dependency>
<!-- Javax Transactions -->
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
<!-- POSTGRESQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
<!-- Joda-Time -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda-time.version}</version>
</dependency>
<!-- To map JodaTime with database type -->
<dependency>
<groupId>org.jadira.usertype</groupId>
<artifactId>usertype.core</artifactId>
<version>3.0.0.CR1</version>
</dependency>
<!-- Servlet+JSP+JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version>
</dependency> -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin-version}</version>
<configuration>
<source>${source-jdk}</source>
<target>${target-jdk}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin-version}</version>
<configuration>
<warSourceDirectory>${war-source-directory}</warSourceDirectory>
<warName>${war-name}</warName>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
<finalName>${final-name}</finalName>
</build>
AppConfig.java
package com.pdma.dmapp.configuration;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.pdma.dmapp")
public class AppConfig extends WebMvcConfigurerAdapter{
#Bean(name="multipartResolver")
public StandardServletMultipartResolver resolver(){
return new StandardServletMultipartResolver();
}
#Override
public void configureViewResolvers(ViewResolverRegistry registry){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
registry.viewResolver(viewResolver);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
registry.addResourceHandler("/webResources/**").addResourceLocations("/webResources/");
registry.addResourceHandler("/app/**").addResourceLocations("/app/");
}
}
PersistenceContext.java
package com.pdma.dmapp.configuration;
#Configuration
#EnableTransactionManagement
#PropertySource(value = {"classpath:db.properties"})
#EnableJpaRepositories("com.pdma.dmapp.module")
public class PersistenceContext {
#Autowired
private Environment environment;
#Bean
#Autowired
public LocalSessionFactoryBean sessionFactory(){
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String [] {"com.pdma.dmapp.module"});
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
#Autowired
LocalContainerEntityManagerFactoryBean entityManagerFactory(
DataSource dataSource,
Environment env){
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean =
new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan(new String [] {"com.pdma.dmapp.module"});
entityManagerFactoryBean.setJpaProperties(hibernateProperties());
return entityManagerFactoryBean;
}
#Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName( environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl( environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername( environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword( environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
private Properties hibernateProperties(){
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager hibernateTXManager(SessionFactory sessionFactory){
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
#Bean
#Autowired
JpaTransactionManager jpaTXManager(EntityManagerFactory entityManagerFactory){
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
/* Same Bean Created as above because CrudRepository Methods are annotated with #Transactional
* So they require a bean named transactionManager*/
#Bean
#Autowired
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory){
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
#Bean
#Autowired
public RepositoryRestConfigurer repositoryRestConfigurer(){
return new RepositoryRestConfigurerAdapter(){
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config){
config.setBasePath("/api");
}
};
}
}
SecurityConfiguration.java
package com.pdma.dmapp.configuration;
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception
{
auth.inMemoryAuthentication()
.withUser("Admin")
.password("admin123")
.roles("Admin");
}
#Override
public void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.antMatchers("/login","/webResources/**").permitAll()
.antMatchers("/**").access("hasRole('Admin')")
.and().formLogin()
.loginPage("/login")
.usernameParameter("username")
.passwordParameter("password")
.and().csrf()
.and().exceptionHandling().accessDeniedPage("/accessDenied");
http.sessionManagement()
.maximumSessions(1)
.expiredUrl("/login.html");
}
}
AppInitializer.java
package com.pdma.dmapp.configuration;
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
private static final String LOCATION = "D:/uploads/";
private static final long MAX_FILE_SIZE = 1024*1024*200;
private static final long MAX_REQUEST_SIZE = 1024*1024*200;
private static final int FILE_SIZE_THRESHOLD = 0;
#Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return new Class [] {AppConfig.class, PersistenceContext.class, SecurityConfiguration.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
// TODO Auto-generated method stub
return null;
}
#Override
protected String[] getServletMappings() {
// TODO Auto-generated method stub
return new String [] {"/"};
}
#Override
protected void customizeRegistration(ServletRegistration.Dynamic registration){
registration.setMultipartConfig(getMultipartConfigElement());
}
private MultipartConfigElement getMultipartConfigElement(){
MultipartConfigElement element = new MultipartConfigElement(LOCATION,
MAX_FILE_SIZE,
MAX_REQUEST_SIZE,
FILE_SIZE_THRESHOLD);
return element;
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.addListener(new SessionListener());
}
}
Repository
package com.pdma.dmapp.module.surveys.repo;
#Transactional("jpaTXManager")
#RepositoryRestResource(exported = true)
public interface SurveyorRepo extends CrudRepository<Surveyor, Integer> {
Surveyor findByDeviceImeiNo1OrDeviceImeiNo2(String deviceImeiNo1, String deviceImeiNo2);
List<Surveyor> findByDistrictDistrictId(Integer districtId);
}
First, try to configure Sprint Data REST in the following way:
#Configuration
public class CustomRepositoryRestConfiguration extends RepositoryRestMvcConfiguration {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config){
config.setBasePath("/api");
}
...
}
Also, make sure your repository beans are available in Spring context and annotate them with #RepositoryRestResource annotation.
EDIT: I think the main problem is how you mix MVC with Spring Data REST. Use RepositoryRestMvcConfiguration instead of RepositoryRestConfigurerAdapter. You can find the detailed guide on how to setup both in official guides here and here.
UPDATE: With newer version of Spring Data REST the base path is set in different way:
#Configuration
public class RestDataConfig extends RepositoryRestMvcConfiguration {
#Override
#Bean
public BaseUri baseUri() {
config().setBasePath("/api");
return new BaseUri(config().getBaseUri());
}
}
Worth mentioning is the fact that in Spring Data REST 3.+ API of RepositoryRestMvcConfiguration changed and in case people seeking the answer for versions 3+ could:
#Import RepositoryRestMvcConfiguration
#Import( ...,
RepositoryRestMvcConfiguration.class,
...)
public class YourConfig { //snip }
Register a RepositoryRestConfigurer #Bean by extending RepositoryRestConfigurerAdapter and overriding basePath
#Bean
public RepositoryRestConfigurer repositoryRestConfigurer() {
return new RepositoryRestConfigurerAdapter() {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config){
// snip
config.setBasePath("/data");
// snip
}
Worth noting is the fact that the same approach can be used to expose IDs for entities and managing other features RepositoryRestConfigurer is responsible for.

Allure. How to get screenshot on testFailure event. Use Java+Junit4+Maven

If I want to get screenshot when my Tests are failed, so what the best practice is? I try to do this next way:
1)overridre AllureRunListener:
public class SimpleScreenshotTestListener extends AllureRunListener{
#Override
public void testFailure(Failure failure) {
if (failure.getDescription().isTest()) {
fireTestCaseFailure(failure.getException());
} else {
startFakeTestCase(failure.getDescription());
fireTestCaseFailure(failure.getException());
finishFakeTestCase();
}
makeScreenshot("Failure screenshot");
}
}
The method makeScreenshot("Failure screenshot") is a static method in Util Class:
public final class Util {
private Util() {}
#Attachment(value = "{0}", type = "image/png")
public static byte[] makeScreenshot(String name) {
return ((TakesScreenshot) <Thread Local Driver>).getScreenshotAs(OutputType.BYTES);
}
}
3) In my pom file I use created listener
SimpleScreenshotTestListener:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<testFailureIgnore>false</testFailureIgnore>
<argLine>
-javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
</argLine>
<properties>
<property>
<name>listener</name>
<value>cms.fireFox.Tps.SimpleScreenshotTestListener</value>
</property>
</properties>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
And my question is : Is this way is the best way or should I do this easier.
Just use JUnit Rules like the following:
public class ScreenshotOnFailureRule implements TestRule {
public Statement apply(final Statement statement, final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
try {
statement.evaluate();
} catch (Throwable t) {
captureScreenshot();
throw t;
}
}
#Attachment
private byte[] captureScreenshot() {
try {
return ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
} catch (Exception e) {
// No need to crash the tests if the screenshot fails
}
}
};
}
}
So far as captureScreenshot() method is run on failure Allure will attach resulting PNG byte stream to test case. Further reading about rules.