Spring data Cassandra Rest Id must be assignable to Serializable!: null - spring-boot

Given below Entity and Repository, I get Id must be assignable to Serializable!: null error when I access rest resource for repository.
curl -H 'Accept: application/json' http://localhost:8080/properties
{"cause":null,"message":"Id must be assignable to Serializable!: null"}
Groovy code
#Component
interface PropertyRepository extends CassandraRepository<Property, String> {
}
#Table("property_v1")
#Canonical
class Property {
#PrimaryKeyColumn(value = "name", type = PARTITIONED)
String name
#PrimaryKeyColumn(value = "environment", type = CLUSTERED)
String environment
#Column("value")
String value
}
I tried adding #Id annotation to primary key field but spring does not allow #Id and #PrimaryKeyColumn annotations on the same entity.
I get #Table types must not define both #Id and #PrimaryKeyColumn properties error.
How do I access spring data Cassandra entities over rest?
I tried using RepositoryRestResource annotation as well on Repository class but received same error.
#RepositoryRestResource(path = "/properties", collectionResourceRel = "properties")
Versions:
Spring boot: 2.0.1.RELEASE
Uses spring-boot-starter-data-cassandra, spring-boot-starter-data-rest moduldes
Exception Stacktrace:
java.lang.IllegalArgumentException: Id must be assignable to Serializable!: null
at org.springframework.util.Assert.instanceCheckFailed(Assert.java:637)
at org.springframework.util.Assert.isInstanceOf(Assert.java:537)
at org.springframework.data.rest.webmvc.support.RepositoryEntityLinks.linkToSingleResource(RepositoryEntityLinks.java:135)
at org.springframework.data.rest.core.support.DefaultSelfLinkProvider.createSelfLinkFor(DefaultSelfLinkProvider.java:68)
at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.getSelfLinkFor(PersistentEntityResourceAssembler.java:99)
at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.wrap(PersistentEntityResourceAssembler.java:76)
at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.toResource(PersistentEntityResourceAssembler.java:55)
at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.entitiesToResources(AbstractRepositoryRestController.java:110)
at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.toResources(AbstractRepositoryRestController.java:80)
at org.springframework.data.rest.webmvc.RepositoryEntityController.getCollectionResource(RepositoryEntityController.java:209)
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.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)

Figured out the issue.
If an entity class has a composite key, spring data rest works only if I have a dedicated class for Primary Key columns.
Changing the class structure to below, enabled rest resources for spring data entities. I used a nested static class for key. But it could be very well a public class of its own.
I feel this boiler plate should be removed from developers and instead spring could look into partition key column and use it as Id.
#Component
interface PropertyRepository extends CassandraRepository<Property, Property.PropertyKey> {
}
#Table("property_v1")
#Canonical
class Property {
#PrimaryKey
PropertyKey key
#Column("value")
String value
#PrimaryKeyClass
#Canonical
static class PropertyKey implements Serializable {
#PrimaryKeyColumn(value = "name", type = PARTITIONED)
String name
#PrimaryKeyColumn(value = "environment", type = CLUSTERED)
String environment
}
}

Related

Spring boot Mongo on update: E11000 duplicate key error with #Version annotation

I have a Spring boot (v2.3.0.RELEASE) application with spring-data-mongodb (v3.0.0).
Basically when I add #Version annotation in my document, the application fails when I am trying to update an existing document and the code is as follows:
My document is as follows:
#Id
private String paymentId;
private String transactionId;
private String transactionTypeCode;
#Version
private Integer version;
My repository is as follows:
public interface PaymentRepository extends MongoRepository<Payment, String>, PaymentRepositoryCustom {
}
The update that fails is as follows:
Optional<Payment> paymentSaved = Optional.ofNullable(paymentRepository.findMaxIdByRefer(request.getAdd().getRefer()));
populatePayment(paymentSaved, payment);
paymentRepository.save(payment);
public static void populatePayment( Optional<Payment> paymentSaved, Payment payment) {
if (paymentSaved.isPresent() && !ObjectUtils.isEmpty(payment)) {
payment.setTransactionId(paymentSaved.get().getTransactionId());
payment.setCreationDate(paymentSaved.get().getCreationDate());
payment.setPaymentId(paymentSaved.get().getPaymentId());
}
}
The application fails on paymentRepository.save(payment) method with the following exception:
org.springframework.dao.DuplicateKeyException: E11000 duplicate key error collection: test.payment index: _id_ dup key: { _id: ObjectId('627a35b7f1ea29549008487e') }; nested exception is com.mongodb.MongoWriteException: E11000 duplicate key error collection: test.payment index: _id_ dup key: { _id: ObjectId('627a35b7f1ea29549008487e') }
at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:99)
at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2863)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:568)
at org.springframework.data.mongodb.core.MongoTemplate.insertDocument(MongoTemplate.java:1436)
at org.springframework.data.mongodb.core.MongoTemplate.doInsert(MongoTemplate.java:1236)
at org.springframework.data.mongodb.core.MongoTemplate.insert(MongoTemplate.java:1168)
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:84)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.springframework.data.repository.core.support.ImplementationInvocationMetadata.invoke(ImplementationInvocationMetadata.java:72)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:382)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:205)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:549)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:155)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke
It looks like it is trying to do an insert instead of update when I add the #Version annotation, any idea how i can resolve this issue please?
However, I cannot remove the #Version annotation.
I have found the issue basically on update the version was null that is why it was trying to create a new payment instead of update.I have retrieved the version from DB and now the update works fine.

The `JAX-RS` resource throwing org.glassfish.jersey.server.model.ModelValidationException after Progard Obfuscation

I am having a Spring boot multi-module maven project running with Java8. This below class is being used to determine which resources we should be registering for our Jersey set-up-
#Slf4j
#Configuration
#Component
#ApplicationPath("/")
public class JerseyConfig extends ResourceConfig {
#Autowired
private AutowireCapableBeanFactory beanFactory;
#PostConstruct
public void initialize() {
// We will just look for all the classes in our resources
// package annotated with #Path
Reflections reflections = new Reflections("org.example.resource");
Set<Class<? extends Object>> resources =
reflections.getTypesAnnotatedWith(Path.class);
resources.forEach(r -> {
log.debug("Registering resource " + r);
register(beanFactory.getBean(r));
});
register(ConstraintViolationExceptionMapper.class);
}
}
Whereas, the REST endpoint looks like below:
#Component
#Api(value = "/api/1/summary", description = "Manage Summary")
#Path("/api/1/summary")
#Produces(MediaType.APPLICATION_JSON)
public class SummaryResource extends AbstractUpdatableDomainResource<Summary> {
#ApiOperation(value = "Create new summary", notes = "Create a new summary and return with its unique id", response = Summary.class)
#POST
#Override
public User create(Summary newInstance) {
}
}
Now, if I ran with -dontobfuscate then everything is working as excepted but when obfuscate it ends up with the following errors:
[http-nio-8080-exec-1] ERROR o.a.c.c.C.[.[localhost].[/web-context-path] - org.apache.juli.logging.DirectJDKLog - Servlet.init() for servlet [org.example.JerseyConfig] threw exception
org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.
[[HINT] A HTTP GET method, public void org.example.resource.FDService.a(javax.servlet.http.HttpServletResponse,javax.servlet.http.HttpServletRequest), returns a void type. It can be intentional and perfectly fine, but it is a little uncommon that GET method returns always "204 No Content".; source='ResourceMethod{httpMethod=GET, consumedTypes=[], producedTypes=[application/pdf], suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class org.example.resource.FDService, handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor#508c06e3]}, definitionMethod=public void org.example.resource.FDService.a(javax.servlet.http.HttpServletResponse,javax.servlet.http.HttpServletRequest), parameters=[Parameter [type=interface javax.servlet.http.HttpServletResponse, source=null, defaultValue=null], Parameter [type=interface javax.servlet.http.HttpServletRequest, source=null, defaultValue=null]], responseType=void}, nameBindings=[]}'
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:394)
at org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$1(ApplicationHandler.java:316)
at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:256)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:315)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:282)
at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:335)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:178)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:370)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1122)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:777)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:135)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
So my question is, what makes it NOT run if the code obfuscates? Why does obfuscation break the application? How to ignore ModelValidationException? What needs to tell proguard to exclude to make it run?

Sort Not Working - Accessing Data with JPA

I've been playing with the Spring "Accessing Data with JPA" starter, adding my own entity and the corresponding repository.
#RepositoryRestResource(collectionResourceRel = "orders", path = "orders")
#CrossOrigin(maxAge = 3600)
public interface OrderRepository extends PagingAndSortingRepository<Order, Long> {
The controllerless routes work fine for simple paging, but there is nothing I can do to get sorting working.
There are two cases. One:
http://192.168.0.163:8080/orders?sort=order_id&order_id.dir=desc
In this case the sort argument has no effect. No matter what combination I try, the sort order is unaffected. I have turned on show queries in STS, and no "order by" clause is generated.
The second case is for some field names in sort=, there is a null pointer exception in Spring:
2016-10-07 14:32:48.426 DEBUG 8292 --- [nio-8080-exec-8] .w.s.m.m.a.ServletInvocableHandlerMethod : Error resolving argument [1] [type=org.springframework.data.rest.webmvc.support.DefaultedPageable]
HandlerMethod details:
Controller [org.springframework.data.rest.webmvc.RepositoryEntityController]
Method [public org.springframework.hateoas.Resources<?> org.springframework.data.rest.webmvc.RepositoryEntityController.getCollectionResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.support.DefaultedPageable,org.springframework.data.domain.Sort,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler) throws org.springframework.data.rest.webmvc.ResourceNotFoundException,org.springframework.web.HttpRequestMethodNotSupportedException]
java.lang.NullPointerException: null
at org.springframework.data.rest.webmvc.json.JacksonMappingAwareSortTranslator$SortTranslator.translateSort(JacksonMappingAwareSortTranslator.java:101) ~[spring-data-rest-webmvc-2.5.3.RELEASE.jar:na]
at org.springframework.data.rest.webmvc.json.JacksonMappingAwareSortTranslator.translateSort(JacksonMappingAwareSortTranslator.java:70) ~[spring-data-rest-webmvc-2.5.3.RELEASE.jar:na]
at org.springframework.data.rest.webmvc.json.MappingAwareDefaultedPageableArgumentResolver.resolveArgument(MappingAwareDefaultedPageableArgumentResolver.java:73) ~[spring-data-rest-webmvc-2.5.3.RELEASE.jar:na]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161) [spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) [spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
...
I just downloaded STS and the starter this week so they should be the latest versions.
Too late, however.... avoid using underscores (e.g. 'aaa_bbb') inside property/field/getters-setters names of your Entities....

Ribbon with Spring Cloud and Eureka: java.lang.IllegalStateException: No instances available for Samarths-MacBook-Pro.local

I am working on Spring Boot Eureka Client Application with Ribbon Load Balancer.
I have two instances of the server registered with Eureka with the name "TEST". On the client side, I have the following code to fetch the server from Eureka.
#Configuration
#ComponentScan
#EnableAutoConfiguration
#EnableEurekaClient
#RestController
public class EurekaConsumerApplication {
#Autowired
DiscoveryClient discoveryClient;
#Autowired
RestTemplate restTemplate;
#RequestMapping(value = "/",method = RequestMethod.GET)
String consumer(){
InstanceInfo instance = discoveryClient.getNextServerFromEureka("TEST", false);
URI uri = UriComponentsBuilder.fromUriString(instance.getHomePageUrl() + "baseDir")
.build()
.toUri();
String baseDir = restTemplate.getForObject(uri, String.class);
return baseDir;
}
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class, args);
}
}
application.yml
spring:
application:
name: consumer
info:
component: Consumer to fetch configuration
server:
port: 8090
eureka:
instance:
leaseRenewalIntervalInSeconds: 3
metadataMap:
instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${random.value}}}
client:
# Default values comes from org.springframework.cloud.netflix.eurek.EurekaClientConfigBean
region: default
registryFetchIntervalSeconds: 5
instanceInfoReplicationIntervalSeconds: 5
initialInstanceInfoReplicationIntervalSeconds: 5
serviceUrl:
defaultZone: http://localhost:8761/eureka/
availabilityZones:
default: ${APPLICATION_DOMAIN:${DOMAIN:defaultZone}}
However, when I hit the restful endpoint by using the following command, it gives an error:
curl http://localhost:8090/
This is the error:
{"exception":"java.lang.IllegalStateException","message":"org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: No instances available for Samarths-MacBook-Pro.local","path":"/"}
Stacktrace:
2015-07-22 14:37:35.005 INFO 13841 --- [tp1334391583-19] c.netflix.loadbalancer.BaseLoadBalancer : Client:Samarths-MacBook-Pro.local instantiated a LoadBalancer:DynamicServerListLoadBalancer:{NFLoadBalancer:name=Samarths-MacBook-Pro.local,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2015-07-22 14:37:35.009 INFO 13841 --- [tp1334391583-19] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client Samarths-MacBook-Pro.local initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=Samarths-MacBook-Pro.local,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList#681eda37
2015-07-22 14:37:35.029 WARN 13841 --- [tp1334391583-19] o.eclipse.jetty.servlet.ServletHandler :
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: No instances available for Samarths-MacBook-Pro.local
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:808)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)
at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:295)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:102)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty..ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:68)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:499)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: No instances available for Samarths-MacBook-Pro.local
at org.springframework.cloud.netflix.ribbon.RibbonClientHttpRequestFactory.createRequest(RibbonClientHttpRequestFactory.java:64)
at org.springframework.http.client.support.HttpAccessor.createRequest(HttpAccessor.java:76)
at org.springframework.web.client.Rlate.doExecute(RestTemplate.java:565)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:545)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:253)
at com.securityscorecard.eureka.consumer.EurekaConsumerApplication.consumer(EurekaConsumerApplication.java:53)
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:497)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
... 38 common frames omitted
Looks like my server list is empty.
The RestTemplate you autowired is already connected to Ribbon. So you do a lookup by hand and then RestTemplate is trying to lookup the hostname passed in to ribbon. You have two options: 1) Don't use the netflix DiscoveryClient and pass the serviceId as a logical hostname to ribbon (http://TEST/myservice), 2) Don't use the autowired RestTemplate, create a new one for your class. My choice would be #1.
I got this working. The only change I had to make was in the way I was using RestTemplate api.
Error Code:
#Autowired
RestTemplate restTemplate;
#RequestMapping(value = "/",method = RequestMethod.GET)
String consumer(){
String baseDir = restTemplate.getForObject("TEST", String.class);
return baseDir;
}
Working Code:
#Autowired
RestTemplate restTemplate;
#RequestMapping(value = "/",method = RequestMethod.GET)
String consumer(){
String baseDir = restTemplate.getForObject("http://TEST", String.class);
return baseDir;
}
Solution:
The first parameter to restTemplate.getForObject should have the format of a URL. And the domain name should be the name of the service you want to discover.
Ex: http://TEST. Here, TEST is the name of my server registered to eureka registry
The question is already answered, but I found a workaround that seems neat and fixed our problem.
First declare a new #Component class and in it create a method that returns RestTemplate:
#Component
public class RestTemplateComponentFix{
#Autowired
SomeConfigurationYouNeed someConfiguration;
#LoadBalanced
public RestTemplate getRestTemplate() {
// TODO set up your restTemplate
rt.setRequestFactory( new HttpComponentsClientHttpRequestFactory() );
return rt;
}
}
After that just Autowire the restTemplateComponentFix in your class and when when you need the rest template call the restTemplate() method. Something like this:
#Service
public class someClass{
#Autowired
RestTemplateComponentFix restTemplateComponentFix;
public void methodUsingRestTemplate(){
// Some code...
RestTemplate rt = restTemplateComponentFix.getRestTemplate();
// Some code...
}
}
After that you can unit test with something like:
RestTemplate rt = Mockito.mock(RestTemplate.class)
when(restTemplateComponentFix.getRestTemplate()).thenReturn(rt);
when(rt.someMethod()).thenReturn(something);
Removing #LoadBalanced Annotation from RestTemplate works for me.
P.S: #LoadAnnotation is supposed to be applied only to Eureka Server which is your discovery server.
The question is already answered by #spencergibb, after trying #spencergibb way if you are still struggling with no instance avialable for ..MS... make sure that in pom.xml if you are using Netflix Eureka then avoid adding dependency for Netflix ribbon as Eureka itself internally uses ribbon.
This was causing problems for me.
RestTemplateBuilder works for me. As below-
#Service
public class someClass{
#Autowired
RestTemplateBuilder restTemplateBuilder;
public void methodUsingRestTemplate(){
restTemplateBuilder.build().getForObject("http://TEST", String.class);
}
}
Can be due to outdated release used in dependencies.
I was using a project from GitHub blog to understand the working of Microservices registry and discovery.
The dependency of netflix in that project was outdated,
spring-cloud-starter-netflix-eureka-server', version: '2.0.1.RELEASE'
After removing version, issue was solved as latest version would be used.

Jooq, Spring, And BoneCP connection closed twice error

I am using Spring 4.0.0, along with jOOQ 3.2.0 and BoneCP 0.8.0 for a web application.
I have the PersistenceContext configured the same as this guide (please skim read it's a little too much code to paste here)
http://www.petrikainulainen.net/programming/jooq/using-jooq-with-spring-configuration/
but with a smaller number of max connections and closeConnectionWatch = true for error checking.
From what I can deduce, this guide is a non-XML version of the jOOQ website's own guide seen here
http://www.jooq.org/doc/3.2/manual/getting-started/tutorials/jooq-with-spring/
My problem comes from probably not knowing how to use the jOOQ generated DAOs or the #Transactional annotation. I am coming across loads of "connection closed twice" exceptions, which makes my application fundamentally broken. The following stack trace doesn't actually say it is closed twice, but the output of closeConnectionWatch says something along the lines of
bonecp connection closed twice detected: first location connection was closed in thread[blah]
closed again in thread[blah2]
Stack trace of SQL Exception after the connection watch does its thing:
Jan 28, 2014 10:51:51 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/application] threw exception [Request processing failed; nested exception is org.springframework.jdbc.UncategorizedSQLException: jOOQ; uncategorized SQLException for SQL
<snip> error code [0]; Connection is closed!; nested exception is java.sql.SQLException: Connection is closed!] with root cause java.sql.SQLException: Connection is closed!
at com.jolbox.bonecp.ConnectionHandle.checkClosed(ConnectionHandle.java:459)
at com.jolbox.bonecp.ConnectionHandle.prepareStatement(ConnectionHandle.java:1011)
at sun.reflect.GeneratedMethodAccessor40.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy$LazyConnectionInvocationHandler.invoke(LazyConnectionDataSourceProxy.java:376)
at com.sun.proxy.$Proxy73.prepareStatement(Unknown Source)
at sun.reflect.GeneratedMethodAccessor40.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy$TransactionAwareInvocationHandler.invoke(TransactionAwareDataSourceProxy.java:240)
at com.sun.proxy.$Proxy73.prepareStatement(Unknown Source)
at org.jooq.impl.ProviderEnabledConnection.prepareStatement(ProviderEnabledConnection.java:112)
at org.jooq.impl.SettingsEnabledConnection.prepareStatement(SettingsEnabledConnection.java:76)
at org.jooq.impl.AbstractResultQuery.prepare(AbstractResultQuery.java:224)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:295)
at org.jooq.impl.AbstractResultQuery.fetch(AbstractResultQuery.java:324)
at org.jooq.impl.SelectImpl.fetch(SelectImpl.java:1034)
at org.jooq.impl.DAOImpl.fetch(DAOImpl.java:249)
----> at com.myapplication.spring.services.UserService.authenticate(UserService.java:32)
at com.myapplication.spring.controllers.LoginController.doLogin(LoginController.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:214)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:748)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:931)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:833)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:807)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.github.dandelion.datatables.core.web.filter.DatatablesFilter.doFilter(DatatablesFilter.java:73)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:931)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
The line where I have arrowed is the line in the service that makes the call to the database. I have #Autowired DAO objects in the service, as below
#Service("UserService")
public class UserService implements UserServiceInterface{
#Autowired UsersDao userDao;
#Autowired PasswordServiceInterface passwordService;
#Override
public Users authenticate(String user,String password) {
boolean allowedIn = false;
List<Users> users = userDao.fetch(USERS.USERNAME, user);
//do something here
Other functions I use in similar services contain calls using the DSLContext object like
DSL.select(SOMETHING).from(SOMETABLE).fetch()
The DAO and DSLContext are stored as beans in PersistenceContext like so.
I am autowiring as a DSLContext and not a *Default*DSLContext as the jOOQ guide has a test method down the bottom showing only a DSLContext.
#Bean
public DefaultDSLContext dsl() {
return new DefaultDSLContext(configuration());
}
#Bean
public UsersDao userDao() { //bad because UsersDao isn't an interface???
return new UsersDao(configuration());
}
And this is the controller
#Controller
public class LoginController {
#Autowired UserServiceInterface userService;
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login() {
return "login";
}
#RequestMapping(value = "/login/doLogin", method = RequestMethod.POST)
public String doLogin(#RequestParam("username")String username, #RequestParam("password") String password, HttpSession session) {
Users u = userService.authenticate(username, password);
if(u == null)
return "redirect:/error";
else {
session.setAttribute("user", u.getUserid());
session.setAttribute("role", u.getRoleid());
session.setAttribute("retailgroup", u.getGroupid());
return "redirect:/dashboard";
}
}
UserService is not the only service I get errors in -- all of my services are similar in that they contain one/both a DAO and a DSLContext Autowired object, with the same DAO configuration constructor as usersDao(), for example productsDao(). The Products service has this DAO and a DSLContext object, and much the same as the UsersService it makes calls to the database.
Sometimes I'll get this connection issue logging in, other times it will be fine and I can browse the site and look at products for a little while, but then randomly I'll get a 'connection is closed!' error coming from another service (there are about 5 that are written in the same way).
So my questions are
Where do I use the #Transactional annotation, and what does it actually do. Does my omission of the #Transactional annotation mean I am causing myself problems? I have previously added it in at all locations that use the DB, but I cant be sure if it was actually helping as I was still getting the same errors.
Is it an issue with my scope for something? I know beans are default as singleton - I've written my controllers in such a way that they use session stored attributes to pass to the services (which are all left as default singletons), so that they may only select data that a certain user is allowed to see.
Since the connectionPool is closing a connection twice, does this mean that the issue is that thread A and thread B go for a connection at the same time, do something with it, and then both close? Why is this happening using the configuration from the above guide? How do I ensure thread safety or is that not the problem?
Are the DAO beans supposed to be interfaces, as from my brief history with Spring I am led to believe a lot(many/all?) #Autowired beans should be? Am I supposed to be using the interface org.jooq.DAOImpl which is the interface that all the jOOQ generated DAOs seem to implement?
#Bean
public org.jooq.impl.DAOImpl usersDao() {
return new usersDao(configuration());
}
Apologies for the long question, any help would be greatly appreciated. Thanks.
Edit: This is my configuration in PersistenceContext class
#Configuration
#PropertySource("classpath:config.properties")
public class PersistenceContext {
#Autowired
private Environment env;
#Bean(destroyMethod = "close")
public DataSource dataSource() {
BoneCPDataSource dataSource = new BoneCPDataSource();
dataSource.setDriverClass(env.getRequiredProperty("db.driver"));
dataSource.setJdbcUrl(env.getRequiredProperty("db.url"));
dataSource.setUsername(env.getRequiredProperty("db.username"));
dataSource.setPassword(env.getRequiredProperty("db.password"));
dataSource.setMaxConnectionsPerPartition(20);
dataSource.setPartitionCount(2);
dataSource.setCloseConnectionWatch(true);
return dataSource;
}
#Bean
public LazyConnectionDataSourceProxy lazyConnectionDataSource() {
return new LazyConnectionDataSourceProxy(dataSource());
}
#Bean
public TransactionAwareDataSourceProxy transactionAwareDataSource() {
return new TransactionAwareDataSourceProxy(lazyConnectionDataSource());
}
#Bean
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(lazyConnectionDataSource());
}
#Bean
public DataSourceConnectionProvider connectionProvider() {
return new DataSourceConnectionProvider(transactionAwareDataSource());
}
#Bean
public JOOQToSpringExceptionTransformer jooqToSpringExceptionTransformer() {
return new JOOQToSpringExceptionTransformer();
}
#Bean
public DefaultConfiguration configuration() {
DefaultConfiguration jooqConfiguration = new DefaultConfiguration();
jooqConfiguration.set(connectionProvider());
jooqConfiguration.set(new DefaultExecuteListenerProvider(
jooqToSpringExceptionTransformer()
));
String sqlDialectName = env.getRequiredProperty("jooq.sql.dialect");
SQLDialect dialect = SQLDialect.valueOf(sqlDialectName);
jooqConfiguration.set(dialect);
return jooqConfiguration;
}
#Bean
public DefaultDSLContext dsl() {
return new DefaultDSLContext(configuration());
}
#Bean
public UsersDao userDao() {
return new UsersDao(configuration());
}
}
After re-reading your question and your chat, I can tell that it is really most likely due to your using version 3.2.0, which had this rather severe bug here:
https://github.com/jOOQ/jOOQ/issues/2863
That bug was fixed in 3.2.2, to which (or later) you should upgrade.

Resources