I've been trying to use Resilience4j + OpenFeign to call services. When I get an error, the timeout is working properly, however, in case of success it always returning null and I couldn't find why. Can someone please help me on this?
Creating the builder:
public AgentesAPI getAPI(String name, String url) {
CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults(name);
RateLimiter rateLimiter = RateLimiter.ofDefaults(name);
FeignDecorators decorators =
FeignDecorators.builder()
.withCircuitBreaker(circuitBreaker)
.withRateLimiter(rateLimiter)
.withFallback(new AgentesAPIFallback())
.build();
return Resilience4jFeign.builder(decorators)
.logger(new Slf4jLogger())
.logLevel(Level.BASIC)
.target(AgentesAPI.class, url);
}
Getting a CompletableFuture with RateLimiter:
public class AgentesAPITimeLimiterService {
public CompletableFuture getCompletableFuture(String name, long miliseconds, Supplier supplier) {
TimeLimiter timeLimiter = getTimeLimiter(name, miliseconds);
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
return timeLimiter.executeCompletionStage(
scheduler, () -> CompletableFuture.supplyAsync(supplier))
.toCompletableFuture();
}
private TimeLimiter getTimeLimiter(String name, long miliseconds) {
return TimeLimiter.of(name,
TimeLimiterConfig.custom().timeoutDuration(
Duration.ofMillis(miliseconds)).build());
}
}
Calling the service and getting always null results:
public Agencias getAgencias(Map<String, Integer> queryMap) {
try {
CompletableFuture<Agencias> result =
_agentesAPITimeLimiterService.getCompletableFuture(configuration.backendName(),
configuration.timeout(), (() -> agentesAPI.getAgencias(queryMap)));
return result.get();
} catch (Exception e) {
throw new RuntimeException("Error getting Agencias!");
}
}
public interface AgentesAPI {
#RequestLine("POST /obtiene_agencias")
#Headers("Content-Type: application/x-www-form-urlencoded")
Agencias getAgencias(#QueryMap Map<String, Integer> queryMap);
}
The API is returning something, however, I couldn't make work in this way. Is there something that I'm missing here?
I'm using the versions below:
compileInclude group: "io.github.openfeign", name: "feign-core", version: "11.0"
compileInclude group: "io.github.openfeign", name: "feign-gson", version: "11.0"
compileInclude group: "io.github.openfeign", name: "feign-slf4j", version: "11.0"
compileInclude group: "io.github.resilience4j", name: "resilience4j-all", version: "1.5.0"
compileInclude group: "io.github.resilience4j", name: "resilience4j-feign", version: "1.5.0"
compileInclude group: "io.github.resilience4j", name: "resilience4j-timelimiter", version: "1.5.0"
compileInclude group: "org.slf4j", name: "slf4j-api", version: "1.7.30"
compileInclude group: "org.slf4j", name: "slf4j-simple", version: "1.7.30"
Thanks in advance.
It was resolved adding a decoder to the builder.
Related
I have no idea what's happening here, there shouldn't be a connection. Not one that manifests this specifically, anyways.
After moving the buildscript of a major spring-boot project from groovy to kotlin-DSL, some unit tests are throwing NullPointerException. It's all the unit tests that deal with methods that have manual transaction management using a TransactionTemplate. This has not happened before the move, and by now I have compared the old and the new buildscript a dozen times over and am pretty confident that I didn't forget anything.
Let's start out by comparing the two versions of the build scripts.
Old groovy:
buildscript {
ext {
kotlinVersion = '1.4.10'
springBootVersion = '2.3.3.RELEASE'
awsSdkVersion = '1.11.381'
springfoxVersion = '2.9.2'
kotlintestVersion = '3.1.7'
}
repositories {
mavenLocal()
jcenter()
mavenCentral()
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion"
classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlinVersion"
// liquibase stuff
classpath 'mysql:mysql-connector-java:5.1.44'
classpath 'org.yaml:snakeyaml:1.19'
classpath('org.liquibase:liquibase-gradle-plugin:1.2.3') {
exclude group: "org.liquibase", module: "liquibase-core"
}
classpath "org.liquibase:liquibase-core:3.5.3" // should be in sync with the version included in spring boot
}
}
plugins {
id 'net.researchgate.release' version '2.6.0'
}
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'kotlin-jpa'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'jacoco'
apply plugin: 'org.liquibase.gradle'
apply plugin: 'idea'
group = 'webcam.yellow.service'
sourceCompatibility = 1.8
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
jacocoTestReport {
reports {
xml.enabled = true
html.enabled = true
}
}
check.dependsOn jacocoTestReport
repositories {
mavenLocal()
mavenCentral()
jcenter()
maven { url = "http://clojars.org/repo/" }
maven {
credentials {
username "${mavenUser}"
password "${mavenPassword}"
}
url = "https://artifactory.yellow.webcam/artifactory/releases"
}
maven {
credentials {
username "${mavenUser}"
password "${mavenPassword}"
}
url = "https://artifactory.yellow.webcam/artifactory/snapshots"
}
}
idea {
module {
// if you hate browsing Javadoc
downloadJavadoc = false
// and love reading sources :)
downloadSources = true
}
}
dependencies {
// avisec libraries
compile "webcam.yellow.api:webcam-api:3.2.0"
compile "webcam.yellow.authentication:messaging-authentication:1.5"
// Spring Boot
compile 'org.springframework.boot:spring-boot-starter-actuator'
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-security'
compile 'org.springframework.boot:spring-boot-starter-activemq'
compile 'org.springframework.boot:spring-boot-starter-validation'
compile 'io.micrometer:micrometer-registry-influx'
compile 'com.fasterxml.jackson.module:jackson-module-kotlin'
compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda'
// Joda
compile 'joda-time:joda-time'
compile 'org.jadira.usertype:usertype.core:6.0.1.GA'
// Libraries
compile group: 'org.apache.commons', name: 'commons-text', version: '1.1'
compile group: 'org.apache.commons', name: 'commons-csv', version: '1.8'
// Kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}"
compile "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}"
// Mail
compile group: 'org.springframework.boot', name: 'spring-boot-starter-mail', version: '2.2.4.RELEASE'
compile group: 'org.apache.commons', name: 'commons-email', version: '1.5'
compile group: 'javax.mail', name: 'mail', version: '1.5.0-b01'
// AWS
compile "com.amazonaws:aws-java-sdk-s3:$awsSdkVersion"
compile group: 'com.amazonaws', name: 'aws-java-sdk-sqs', version: '1.11.558'
compile group: 'software.amazon.awssdk', name: 's3', version: '2.10.61'
compile group: 'com.amazonaws', name: 'aws-java-sdk-ec2', version: '1.11.740'
// Support old pw hash lib
compile group: 'buddy', name: 'buddy-hashers', version: '1.3.0'
// Hazelcast
compile group: 'com.hazelcast', name: 'hazelcast-spring'
compile group: 'com.hazelcast', name: 'hazelcast-aws', version: '2.4'
// Swagger
compile group: 'io.springfox', name: 'springfox-swagger2', version: springfoxVersion
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: springfoxVersion
// Database
runtime 'mysql:mysql-connector-java'
runtime 'org.liquibase:liquibase-core'
compile 'org.influxdb:influxdb-java:2.13'
// HTML Generation
compile group: 'org.jetbrains.kotlinx', name: 'kotlinx-html-jvm', version: '0.6.10'
// ActiveMQ
compile group: 'org.messaginghub', name: 'pooled-jms'
// Development
compile "org.springframework.boot:spring-boot-devtools"
// Testing
testCompile 'org.springframework.boot:spring-boot-starter-test'
testCompile 'org.springframework.security:spring-security-test'
testCompile 'com.h2database:h2'
testCompile 'io.kotlintest:kotlintest:2.0.7'
testCompile 'com.nhaarman:mockito-kotlin:1.6.0'
// GSON
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6'
}
liquibase {
activities {
main {
changeLogFile '/db/changelog/db.changelog-master.yaml'
url 'jdbc:mysql://localhost:3307/yellow'
username 'user'
password 'secret'
classpath 'src/main/resources'
}
}
}
springBoot {
buildInfo()
}
task ebextensions(type: Exec) {
executable "sh"
args "-c", "jar uf build/libs/webcam-service*.jar .ebextensions"
}
bootJar.finalizedBy ebextensions
afterReleaseBuild.dependsOn bootJar
test {
minHeapSize = "1024m"
maxHeapSize = "1024m"
jvmArgs = ["-Xloggc:build/gclog-%p.log", "-XX:+PrintGCDetails"]
}
And the new kotlin one:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
buildscript {
dependencies {
classpath("org.jfrog.buildinfo:build-info-extractor-gradle:4.9.6")
classpath("org.jetbrains.kotlin:kotlin-allopen:1.4.10")
// liquibase stuff
classpath("mysql:mysql-connector-java:5.1.44")
classpath("org.yaml:snakeyaml:1.19")
classpath("org.liquibase:liquibase-gradle-plugin:1.2.3") {
exclude("org.liquibase", "liquibase-core")
}
classpath("org.liquibase:liquibase-core:3.8.9") // should be in sync with the version included in spring boot
}
}
val awsSdkVersion = "1.11.740"
val springfoxVersion = "2.9.2"
plugins {
id("org.springframework.boot") version "2.3.3.RELEASE"
id("io.spring.dependency-management") version "1.0.9.RELEASE"
id("net.researchgate.release") version "2.6.0"
kotlin("jvm") version "1.4.10"
kotlin("plugin.spring") version "1.4.10"
`maven-publish`
id("com.jfrog.artifactory") version "4.14.1"
id("org.liquibase.gradle") version "2.0.4"
id("org.jetbrains.kotlin.plugin.noarg") version "1.4.10"
id("org.jetbrains.kotlin.plugin.jpa") version "1.4.10"
}
group = "webcam.yellow.service"
java.sourceCompatibility = JavaVersion.VERSION_1_8
val mavenUser: String by project
val mavenPassword: String by project
val artifactoryRepository = System.getenv("ARTIFACTORY_REPO") ?: "snapshots"
repositories {
mavenCentral()
jcenter()
maven {
credentials {
username = mavenUser
password = mavenPassword
}
url = uri("https://artifactory.yellow.webcam/artifactory/releases")
}
maven {
credentials {
username = mavenUser
password = mavenPassword
}
url = uri("https://artifactory.yellow.webcam/artifactory/snapshots")
}
}
dependencies {
// Spring Boot
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-activemq")
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-mail")
implementation("io.micrometer:micrometer-registry-influx")
// Kotlin
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.6.8")
// Yellow Dependencies
implementation("webcam.yellow.api:webcam-api:3.2.0")
implementation("webcam.yellow.authentication:messaging-authentication:1.5")
// AWS
implementation("com.amazonaws:aws-java-sdk-s3:$awsSdkVersion")
implementation("software.amazon.awssdk:s3:2.10.61") // does not yet incorporate all functionality of 1.11.X
implementation("com.amazonaws:aws-java-sdk-sqs:$awsSdkVersion")
implementation("com.amazonaws:aws-java-sdk-ec2:$awsSdkVersion")
// Support old pw hash lib
implementation("buddy:buddy-hashers:1.3.0")
// Jackson
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-joda")
// Hazelcast
implementation("com.hazelcast:hazelcast-spring")
implementation("com.hazelcast:hazelcast-aws:2.4")
// Other Libs
implementation("org.apache.commons:commons-text:1.1")
implementation("org.apache.commons:commons-csv:1.8")
implementation("org.messaginghub:pooled-jms")
implementation("org.influxdb:influxdb-java:2.13")
implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.6.10")
implementation("org.springframework.boot:spring-boot-devtools")
implementation("com.google.code.gson:gson:2.8.6")
implementation("joda-time:joda-time")
implementation("org.jadira.usertype:usertype.core:6.0.1.GA")
// Swagger
implementation("io.springfox:springfox-swagger2:$springfoxVersion")
implementation("io.springfox:springfox-swagger-ui:$springfoxVersion")
// Database
runtimeOnly("mysql:mysql-connector-java")
runtimeOnly("org.liquibase:liquibase-core")
implementation("org.influxdb:influxdb-java:2.13")
// Test
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.security:spring-security-test")
testImplementation("com.h2database:h2")
testImplementation("com.nhaarman:mockito-kotlin:1.6.0")
testImplementation("io.kotlintest:kotlintest:2.0.7")
}
tasks.withType<Test> {
useJUnitPlatform()
}
springBoot {
buildInfo()
}
liquibase {
activities.register("main") {
arguments = mapOf(
"changeLogFile" to "/db/changelog/db.changelog-master.yaml",
"url" to "jdbc:mysql://localhost:3307/yellow",
"username" to "user",
"password" to "secret",
"classpath" to "src/main/resources"
)
}
}
tasks {
withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
bootJar {
from("./.ebextensions") { into(".ebextensions") }
launchScript()
}
afterReleaseBuild {
dependsOn(bootJar)
}
test {
minHeapSize = "1024m"
maxHeapSize = "1024m"
jvmArgs = listOf("-Xloggc:build/gclog-%p.log", "-XX:+PrintGCDetails")
}
}
Some things needed different handling, like moving some plugins from the classpath to the plugins section, the .ebsextensions are handled differently, and Jacoco isn't in there anymore because we never really used those reports in jenkins. All in all, pretty normal. Everything works, except for this one thing in the unit tests.
Here's a class initialisation and one of the tested methods:
#Service
class ImageService(private val imageRepository: ImageRepository,
private val imageSetRepository: ImageSetRepository,
private val permissionService: PermissionService,
private val s3Service: S3Service,
private val entityManager: EntityManager,
private val panoFeedRepository: PanoFeedRepository,
private val panoImageRepository: PanoImageRepository,
private val jobFacade: JobFacade,
private val jdbcTemplate: NamedParameterJdbcTemplate,
transactionManager: PlatformTransactionManager,
#Value("\${service.cleanup.enabled}")
private val cleanupEnabled: Boolean) {
private val readTransaction = org.springframework.transaction.support.TransactionTemplate(
transactionManager,
DefaultTransactionDefinition().apply {
isReadOnly = true
propagationBehavior = TransactionDefinition.PROPAGATION_REQUIRES_NEW
})
private val writeTransaction = org.springframework.transaction.support.TransactionTemplate(
transactionManager,
DefaultTransactionDefinition().apply {
isReadOnly = false
propagationBehavior = TransactionDefinition.PROPAGATION_REQUIRES_NEW
})
/**
* Deletes all passed images from the database while removing them from S3 asynchronously.
* Does not check any permissions.
* This opens its own write transaction, which could take a long time. If individual transactions take too long,
* invoke this method multiple times with smaller chunks to avoid issues with table locking.
* Since this is potentially long-running, commit preceding transactions beforehand.
*/
#Transactional(propagation = Propagation.NEVER)
internal fun delete(images: List<ImageIdAndImageKeyAndImagePreviewKey>) {
images.chunked(500).forEach { chunk ->
log.debug("Deleting s3 files of {} images", chunk.size)
jobFacade.executeAsync {
val keysToDelete = chunk
.flatMap { listOf(it.getImageKey(), it.getImagePreviewKey()) }
.asSequence()
.filterNotNull()
.filter { !it.isBlank() }
.toList()
s3Service.deleteImages(keysToDelete)
log.trace("deleted {} s3 files of {} images", keysToDelete.size, chunk.size)
}
log.debug("Deleting {} images from database", chunk.size)
writeTransaction.execute {
imageRepository.deleteAllByIdIn(chunk.map { it.getId()!! })
} // <---- Exception happens in here
log.trace("Deleted {} images from database", chunk.size)
}
}
}
And here's a test setup and a test that tests tat method:
class ImageServiceTest {
private val imageRepository: ImageRepository = mock()
private val imageSetRepository: ImageSetRepository = mock()
private val permissionService: PermissionService = mock()
private val s3Service: S3Service = mock()
private val hazelCastInstance: HazelcastInstance = mock()
private val panoFeedRepository: PanoFeedRepository = mock()
private val panoImageRepository: PanoImageRepository = mock()
private val jdbcTemplate: NamedParameterJdbcTemplate = mock()
private val transactionManager: PlatformTransactionManager = mock()
private val jobFacade: JobFacade
private val sut: ImageService
init {
val imap: IMap<String, String> = mock()
`when`(hazelCastInstance.getMap<String, String>(any())).thenReturn(imap)
jobFacade = JobFacade(hazelCastInstance)
sut = ImageService(
imageRepository, imageSetRepository, permissionService, s3Service, mock(),
panoFeedRepository, panoImageRepository, jobFacade, jdbcTemplate, transactionManager, false)
}
#Test
fun `deleting multiple images invokes S3Service in chunks and deletes images from DB`() {
val user = TestModelFactory.userWithOneCameraAndTablePermission()
val table = user.tablePermissions.first().table!!
val images = (1..800).map { TestModelFactory.image(table = table) }
sut.delete(images.map { ImageIdentifiers(it.id, it.imageKey, it.imagePreviewKey) })
Thread.sleep(2000) //leave enough time for S3 uploads to finish
val idChunks = images.map { it.id }.chunked(500)
verify(imageRepository, times(1)).deleteAllByIdIn(eq(idChunks[0]))
verify(imageRepository, times(1)).deleteAllByIdIn(eq(idChunks[1]))
verify(s3Service, times(2)).deleteImages(any())
}
And finally, the error:
java.lang.NullPointerException: Parameter specified as non-null is null: method webcam.yellow.service.service.ImageService$delete$$inlined$forEach$lambda$2.doInTransaction, parameter it
Now, there's several things I'm currently looking into about what might go wrong, involving the mocked TransactionManager and the non-mocked TransactionTemplates... But the really frustrating thing is that this simply didn't happen before migrating the build script, and nothing else changed.
It turns out that the transactionTemplate (which is not mocked) invoked a method on the mock of the platformTransactionManager, which returned null (obviously), and that caused the NullPointerException.
It was fixed relatively easily by configuring the mock instance to return a value instead:
given(transactionManager.getTransaction(any())).willReturn(mock())
What I don't know is why this ever worked before. This problem should always have been there, but it wasn't... Only when I migrated the build file did it show its head, which doesn't really make much sense.
newbie to Springboot with gradle, I am creating a restful service which queries the db2 database and returns the result in json.
The desired output
{
resource: {
results: [
{
currencyCode: "JPY",
conversionRateToUSD: "0.010286580",
conversionRateFromUSD: "97.214040040",
startDate: "2011-01-01",
endDate: "2011-01-29"
}
]
}
}
The api i am trying to build is http://localhost:8080/apis/exchange-rates/referenceDate=2015-01-01¤cyCode=JPY
I have created the below controller class
#RestController
#Slf4j
#RequestMapping("/apis")
public class IndividualExchangeRateController {
#Autowired
private IndividualExchangeRateService individualExchangeRateService;
public IndividualExchangeRateController(IndividualExchangeRateService individualExchangeRateService) {
this.individualExchangeRateService = individualExchangeRateService;
}
#RequestMapping(value = "/exchange-rates", method = RequestMethod.GET)
#ResponseStatus(HttpStatus.OK)
public #ResponseBody IndividualResource getIndividual(#RequestParam("referenceDate") #DateTimeFormat(pattern = "YYYY-MM-DD")Date referenceDate,
#RequestParam(value = "currencyCode", required = false) String currencyCode){
try {
System.out.println("Inside Controller");
return individualExchangeRateService.getIndividualExchangeRate(referenceDate, currencyCode);
}
catch (HttpClientErrorException e){
throw new InvalidRequestException(e.getMessage());
}
}
}
I am getting the below error when i call the api
javax.servlet.ServletException: Circular view path [error]: would dispatch back to the current handler URL [/error] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
Can anybody help out on this ?
As the output is json i do not have thymeleaf dependencies on my application
Below is the gradle build file
plugins {
id 'org.springframework.boot' version '2.1.7.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.abc.service'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
maven { url "http://artifactory.abcinc.dev/artifactory/maven-repos" }
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compileOnly 'org.projectlombok:lombok:1.18.8'
annotationProcessor 'org.projectlombok:lombok:1.18.8'
runtime 'com.ibm.db2.jcc:db2jcc4:4.19.49'
compile group: 'org.springframework', name: 'spring-jdbc', version: '5.1.9.RELEASE'
compile group: 'com.zaxxer', name: 'HikariCP', version: '3.3.1'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.9'
}
public class IndividualExchangeRate {
private String currencyCode;
private double conversionRateFromUSD;
private double conversionRateToUSD;
}
public class IndividualResource {
private List<IndividualExchangeRate> individualExchangeRates;
}
All the classes are annotated with lombok.
Spring Boot uses a default Whitelabel error page in case server error.So there might be some code snippets which is breaking your appliaction flow.
Add server.error.whitelabel.enabled=false in your application.properties file .
OR add the following code snippets :
#Controller
public class AppErrorController implements ErrorController{
private static final String PATH = "/error";
#RequestMapping(value = PATH)
public String error() {
return "Error handling";
}
#Override
public String getErrorPath() {
return PATH;
}
}
I'm building an application that uses Spring boot and neo4j ogm.
When i run it from spring tool suite or from gradle boot run, it works fine. However, after packaging it into a jar I get this error.
java.lang.NullPointerException: null
at org.neo4j.ogm.session.delegates.LoadOneDelegate.lookup(LoadOneDelegate.java:56) ~[neo4j-ogm-core-2.0.4.jar!/:na]
at org.neo4j.ogm.session.delegates.LoadOneDelegate.load(LoadOneDelegate.java:49) ~[neo4j-ogm-core-2.0.4.jar!/:na]
at org.neo4j.ogm.session.Neo4jSession.load(Neo4jSession.java:142) ~[neo4j-ogm-core-2.0.4.jar!/:na]
at comds.service.GenericService.find(GenericService.java:32) ~[classes!/:na]
at comds.service.UserServiceImpl.find(UserServiceImpl.java:36) ~[classes!/:na]
at comds.service.UserServiceImpl.find(UserServiceImpl.java:25) ~[classes!/:na]
at comds.linkedIn.LinkedInSaveUser.saveUser(LinkedInSaveUser.java:84) ~[classes!/:na]
at comds.controller.LinkedInController.home(LinkedInController.java:64) ~[classes!/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.2.7.RELEASE.jar!/:4.2.7.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-4.2.7.RELEASE.jar!/:4.2.7.RELEASE]
I suspect this is to do with the ogm configuration as the packages are used to define the meta data in ogm, which seems to be null:
package comds;
import org.neo4j.ogm.config.Configuration;
import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
public class Neo4jSessionFactory {
private final static String [] packages = {"comds.domain"};
private final static SessionFactory sessionFactory = new SessionFactory(getConfiguration(),packages);
private static Neo4jSessionFactory factory = new Neo4jSessionFactory();
public static Neo4jSessionFactory getInstance() {
return factory;
}
private Neo4jSessionFactory() {
}
private static Configuration getConfiguration() {
Configuration configuration = new Configuration();
configuration.driverConfiguration()
.setDriverClassName("org.neo4j.ogm.drivers.http.driver.HttpDriver")
.setURI("http://neo4j:test#localhost:7474");
return configuration;
}
public Session getNeo4jSession() {
return sessionFactory.openSession();
}
}
For some reason the COMDS user class is not being read:
#Service("userService")
public class UserServiceImpl extends GenericService<COMDSUser> implements UserService{
#Override
public Class<COMDSUser> getEntityType() {
return COMDSUser.class;
}
#Override
public COMDSUser find(Long id) {
COMDSUser user = super.find(id);
if(user != null){
return applyPrivacySettings(user);
}
return null;
}
//... more stuff
public class COMDSUser extends COMDSEntity{
public enum privacySettings{
SHOW_ALL, HIDE_PERSONAL_INFO,HIDE_ALL;
}
private String firstName;
private String lastName;
/// .. more stuff
package comds.domain;
import org.neo4j.ogm.annotation.GraphId;
public abstract class COMDSEntity {
#GraphId
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || id == null || getClass() != o.getClass()) return false;
COMDSEntity entity = (COMDSEntity) o;
if (!id.equals(entity.id)) return false;
return true;
}
#Override
public int hashCode() {
return (id == null) ? -1 : id.hashCode();
}
}
And gradle build:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.6.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'war'
war {
baseName = 'COM_DS'
version = '0.1.0'
}
jar {
baseName = 'COM_DS'
version = '0.1.0'
}
repositories {
mavenCentral()
maven { url "https://repo.spring.io/libs-release" }
maven{ url "https://mvnrepository.com/artifact"}
maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local/' }
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:1.3.6.RELEASE")
compile "io.springfox:springfox-swagger2:2.5.1-SNAPSHOT"
compile("io.springfox:springfox-swagger-ui:2.5.0")
compile 'org.neo4j.driver:neo4j-java-driver:1.0.1'
compile group: 'org.neo4j', name: 'neo4j', version: '3.0.3'
compile group: 'org.neo4j', name: 'neo4j-ogm-core', version: '2.0.4'
compile group: 'org.neo4j', name: 'neo4j-ogm-api', version: '2.0.4'
compile group: 'org.neo4j', name: 'neo4j-ogm-http-driver', version: '2.0.4'
compile group: 'org.neo4j', name: 'neo4j-ogm-bolt-driver', version: '2.0.4'
compile group: 'org.neo4j', name: 'neo4j-ogm-embedded-driver', version: '2.0.4'
compile group: 'com.voodoodyne.jackson.jsog', name: 'jackson-jsog', version: '1.1'
compile("org.hibernate:hibernate-validator")
compile("org.springframework.boot:spring-boot-starter-social-facebook")
compile('org.springframework.boot:spring-boot-devtools')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-test')
compile "org.springframework.social:spring-social-core:1.1.4.RELEASE"
compile("org.springframework.social:spring-social-security:1.1.4.RELEASE")
compile("org.springframework.social:spring-social-config:1.1.4.RELEASE")
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
compile group: 'joda-time', name: 'joda-time', version: '2.9.4'
testCompile 'junit:junit:4.10'
compile group: 'org.springframework', name: 'spring-test', version: '4.3.2.RELEASE'
compile fileTree(dir: 'resources', include: ['*.jar'])
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
}
task wrapper(type: Wrapper) {
gradleVersion = '2.3'
}
Note Im a using a custom spring social linked in class, that is being imported in the last compile
Your help would be greatly appreciated :)
Found a work around solution. Instead of exporting to a war, I exported just a jar. The issue was that exporting the file as a war changed the file structure meaning the ogm mapping couldn't be done properly. My new gradle build looks like this:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.6.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
jar {
baseName = 'name'
version = '0.1.0'
}
repositories {
mavenCentral()
maven { url "https://repo.spring.io/libs-release" }
maven{ url "https://mvnrepository.com/artifact"}
maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local/'}
maven { url 'https://oss.sonatype.org/content/repositories/snapshots'}
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:1.3.6.RELEASE")
compile "io.springfox:springfox-swagger2:2.5.1-SNAPSHOT"
compile("io.springfox:springfox-swagger-ui:2.5.0")
compile 'org.neo4j.driver:neo4j-java-driver:1.0.1'
compile group: 'org.neo4j', name: 'neo4j', version: '3.0.3'
compile group: 'org.neo4j', name: 'neo4j-ogm-core', version: '2.0.4'
compile group: 'org.neo4j', name: 'neo4j-ogm-api', version: '2.0.4'
compile group: 'org.neo4j', name: 'neo4j-ogm-http-driver', version: '2.0.4'
compile group: 'org.neo4j', name: 'neo4j-ogm-bolt-driver', version: '2.0.4'
compile group: 'org.neo4j', name: 'neo4j-ogm-embedded-driver', version: '2.0.4'
compile group: 'org.pac4j', name: 'spring-webmvc-pac4j', version: '1.1.1'
compile group: 'org.pac4j', name: 'pac4j-oauth', version: '1.9.2-SNAPSHOT'
compile group: 'org.pac4j', name: 'pac4j-core', version: '1.9.2-SNAPSHOT'
compile group: 'com.voodoodyne.jackson.jsog', name: 'jackson-jsog', version: '1.1'
compile("org.hibernate:hibernate-validator")
compile('org.springframework.boot:spring-boot-devtools')
compile group: 'javax.servlet.jsp.jstl', name: 'jstl', version: '1.2'
compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '8.5.4'
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-test')
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
testCompile 'junit:junit:4.10'
compile group: 'org.springframework', name: 'spring-test', version: '4.3.2.RELEASE'
compile fileTree(dir: 'resources', include: ['*.jar'])
}
task wrapper(type: Wrapper) {
gradleVersion = '2.3'
}
I am trying to write some tests for my Spring Boot 1.4.0 with Spock and my application-test-properties file is not being picked up.
I have this in my gradle:
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-web')
compile 'org.codehaus.groovy:groovy-all:2.4.1'
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.spockframework:spock-spring:1.0-groovy-2.4') {
}
Then I have this in
/src/test/groovy/resources:
# JWT Key
jwt.key=MyKy#99
And finally my Spock test:
#SpringBootTest(classes = MyApplication.class, webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT)
#TestPropertySource("application-test.properties")
public class TokenUtilityTest extends Specification {
#Autowired
private TokenUtility tokenUtility
def "test a valid token creation"() {
def userDetails = new User(username: "test", password: "password", accountNonExpired: true, accountNonLocked: true,
);
when:
def token = tokenUtility.buildToken(userDetails)
then:
token != null
}
}
Which is testing this class:
#Component
public class TokenUtility {
private static final Logger LOG = LoggerFactory.getLogger( TokenUtility.class );
#Value("${jwt.key}")
private String jwtKey;
public String buildToken(UserDetails user) {
return Jwts.builder()
.setSubject(user.getUsername())
.signWith(SignatureAlgorithm.HS512, jwtKey)
.compact();
}
public boolean validate(String token) {
try {
Jwts.parser().setSigningKey(jwtKey).parseClaimsJws(token);
return true;
} catch (SignatureException e) {
LOG.error("Invalid JWT found: " + token);
}
return false;
}
}
I originally instantiated the TokenUtility on my test but the application-test.properties was never loaded (I am assuming since jwtKey was null). So I am trying #Autowired my class under test, but now that is null.
It looks like Spring Boot 1.4 changed a lot for testing, so perhaps I am not wiring this up correctly?
There are several things wrong with your test code; first, your dependencies are bad - Spock 1.0 does not support #SpringBootTest annotation so no context will be initialized and no post-processing will be done, hence the null pointer exception: nothing will be autowired.
Support for that annotation was added in Spock 1.1, which is still release-candidate, so you'll have to use that:
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-web')
compile group: 'io.jsonwebtoken', name: 'jjwt', version: '0.6.0'
compile('org.codehaus.groovy:groovy')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.spockframework:spock-core:1.1-groovy-2.4-rc-1')
testCompile('org.spockframework:spock-spring:1.1-groovy-2.4-rc-1')
testCompile group: 'com.h2database', name: 'h2', version: '1.4.192'
}
Then, your path to the application-test.properties is wrong and should be /application-test.properties since it is in the root of the classpath:
#SpringBootTest(classes = DemoApplication.class,
webEnvironment = WebEnvironment.RANDOM_PORT)
#TestPropertySource("/application-test.properties")
public class TokenUtilityTest extends Specification {
#Autowired
TokenUtility tokenUtility
def "test a valid token creation"() {
def userDetails = new User("test", "password", Collections.emptyList());
when:
def token = tokenUtility.buildToken(userDetails)
then:
token != null
}
}
I had the similar problem, but for me, the solution was to change double quotes ".." to single quotes '..' inside the #Value annotation when working with Spock. Please find the example below:
#Value('${jwt.key}')
private String jwtKey;
PS - This is not the exact answer to the question. I am posting this for someone who faces a similar problem like mine and ends up here.
I am trying to use DetachedCriteria to retreive Database details from the SQl server DB like below. the nvarcharID is of String Type
List<POJO> pojoObj = (List<POJO>) getHibernateTemplate().findByCriteria(DetachedCriteria.forClass(
POJO.class).add(Restrictions.idEq(nvarcharID)));
In My POJO I have following attributes
#Id
#GeneratedValue
#Column(name = "ID")
private double ID;
#Nationalized
#Column(name = "Column1")
private String string1;
#Nationalized
#Column(name = "column2")
private String string2;
Both column1 and column 2 are of type nvarchar inSql serverDB. and nvarcharID used above in the Criteria is another field in DB which is of type nvarchar in DB and I have mapped it as String. While populating the POJO, I do not want navarcharID field to be part of my POJO.
For hibernate I have following dependencies in my gradle file
compile group: 'org.hibernate', name: 'hibernate-entitymanager', version: '4.3.11.Final'
compile group: 'javax.validation', name: 'validation-api', version: '1.0.0.GA'
compile group: 'org.hibernate', name: 'hibernate-validator-annotation-processor', version: '4.3.2.Final'
compile group: 'org.hibernate', name: 'hibernate-validator', version: '4.3.2.Final'
compile 'org.hibernate:hibernate-core:4.3.11.Final'
and my Spring dependencies are
compile group: 'org.springframework', name: 'spring-orm', version:'4.1.6.RELEASE'
compile group: 'org.springframework', name: 'spring-webmvc', version: '4.1.6.RELEASE'
compile group: 'org.springframework.security', name: 'spring-security-web', version: '4.0.2.RELEASE'
I am also setting following properties in my Hibernate config file for Dialect and ddl operations.
#Bean
public LocalSessionFactoryBean sessionFactoryBean() {
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
localSessionFactoryBean.setDataSource(dataSource);
localSessionFactoryBean.setPackagesToScan(new String[] { "com.wk.cdi" });
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.SQLServer2012Dialect");
properties.setProperty("hibernate.use_nationalized_character_data", "true");
properties.setProperty("hibernate.hbm2ddl.auto", "update");
properties.setProperty("hibernate.format_sql", "true");
properties.setProperty("hibernate.show_sql", "true");
localSessionFactoryBean.setHibernateProperties(properties);
return localSessionFactoryBean;
}
When I try to use hibernateTemplate to retreive the data I am getting
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Double and it throws the error while using DetachedCriteria ealborated above
PLease ignore this as there was something else.
It happens to be that the Restrcition.idEq needed to be replaced by Restrictions.eq