I use spring boot 2.1.8 and neo4j server 3.5,and write some spring data neo4j repository to query neo4j.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
</dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
</dependencies>
I had a service with a transaction type of Propagation.REQUIRES_NEW
#Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public class SomeServiceImpl implements SomeService {
#Autowired
SomeMapper someMapper;
#Override
public HashMap getData() {
String tbname = someMapper.getTableSpaceName("admin");
return someMapper.getData(tbname);
}
}
Before I add neo4j dependency,I can call the getData method,after I add neo4j,once I call it,I got an exception:
15:33:56 [http-nio-8092-exec-1] ERROR c.h.d.c.e.h.GlobalExceptionHandler - org.springframework.transaction.IllegalTransactionStateException: Neo4jTransactionManager only supports 'required' propagation.
at org.springframework.data.neo4j.transaction.Neo4jTransactionManager.doBegin(Neo4jTransactionManager.java:177)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:378)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:475)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:289)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
at com.heren.bi.service.impl.EltLogServiceImpl$$EnhancerBySpringCGLIB$$2.getDataBaseInfo(<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.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
at org.springframework.cloud.context.scope.GenericScope$LockedScopedProxyFactoryBean.invoke(GenericScope.java:499)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
But in the SomeServiceImpl,there is no business with neo4j,why can not I use Propagation.REQUIRES_NEW,does it mean once I add neo4j dependency,I must use required propagation everywhere in my whole application? If I use a service with a neo4j repository,I can understand I must use a required propagation transaction,but in other service,I should be able to use Propagation.REQUIRES_NEW.
When I boot the application,I see many logs like:
14:19:55 [main] DEBUG o.s.d.n.mapping.Neo4jMappingContext - Creating Neo4jPersistentEntity from type information ....DTO
I am not sure is it because I put the pojo or repository in a wrong place which is the same as other common pojo,then it will create too many Neo4jMappingContext for many mapper and pojo class,etc,
How can I use Propagation.REQUIRES_NEW after I add neo4j dependency?
Related
The Springboot migration from 2.7.x to 3.0.1 is not going smoothly on my project.
I'm currently facing multiple issues regarding the interpretation of the custom queries used in our repositories. Those queries were working fine before the migration.
I can't get my head around the migration of this kind of query :
#Query("""
SELECT DISTINCT new com.dto.NameIdDto(ws.id, ws.name)
FROM UserRole ur
JOIN ur.workspace ws
WHERE (COALESCE(:workspaceIds) IS NULL OR ws.id IN (:workspaceIds))
""")
List<NameIdDto> findWorkspacesWithUsers(Collection<Long> workspaceIds);
#Entity
public class UserRole {
#Id
#GeneratedValue(generator = MY_SEQUENCE)
private Long id;
#ManyToOne(optional = false)
#JoinColumn(name = "workspace_id")
private Workspace workspace;
}
#Entity
public class Workspace {
#Id
#GeneratedValue(generator = MY_SEQUENCE)
private Long id;
#OneToMany(fetch = LAZY, mappedBy = "workspace", cascade = ALL, orphanRemoval = true)
private Set<UserRole> userRoles = new HashSet<>();
}
When running the following tests
#Test
public void shouldReturnEmptyForNullParameter() {
assertThat(workspaceRepository.findWorkspacesWithUsers(null)).isEmpty();
}
#Test
public void shouldReturnEmptyForEmptyParameter() {
assertThat(workspaceRepository.findWorkspacesWithUsers(Collections.emptyList())).isEmpty();
}
shouldReturnEmptyForEmptyParameter fails with the exceptions :
org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [[]] did not match expected type [BasicSqmPathSource(id : Long) ]
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:371)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:235)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:134)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:218)
at jdk.proxy2/jdk.proxy2.$Proxy121.findWorkspacesWithUsers(Unknown Source)
at com.example.TestApplicationTests.shouldReturnEmptyForNullOrEmptyParameter(TestApplicationTests.java:26)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
Caused by: java.lang.IllegalArgumentException: Parameter value [[]] did not match expected type [BasicSqmPathSource(id : Long) ]
at org.hibernate.query.internal.QueryParameterBindingImpl.setBindValue(QueryParameterBindingImpl.java:119)
at org.hibernate.query.spi.AbstractCommonQueryContract.setParameter(AbstractCommonQueryContract.java:860)
at org.hibernate.query.spi.AbstractSelectionQuery.setParameter(AbstractSelectionQuery.java:708)
at org.hibernate.query.sqm.internal.QuerySqmImpl.setParameter(QuerySqmImpl.java:1222)
at org.hibernate.query.sqm.internal.QuerySqmImpl.setParameter(QuerySqmImpl.java:129)
at org.springframework.data.jpa.repository.query.QueryParameterSetter$BindableQuery.setParameter(QueryParameterSetter.java:322)
at org.springframework.data.jpa.repository.query.QueryParameterSetter$NamedOrIndexedQueryParameterSetter.lambda$setParameter$4(QueryParameterSetter.java:113)
at org.springframework.data.jpa.repository.query.QueryParameterSetter$ErrorHandling$1.execute(QueryParameterSetter.java:136)
at org.springframework.data.jpa.repository.query.QueryParameterSetter$NamedOrIndexedQueryParameterSetter.setParameter(QueryParameterSetter.java:113)
at org.springframework.data.jpa.repository.query.ParameterBinder.bind(ParameterBinder.java:83)
at org.springframework.data.jpa.repository.query.ParameterBinder.bind(ParameterBinder.java:75)
at org.springframework.data.jpa.repository.query.ParameterBinder.bindAndPrepare(ParameterBinder.java:97)
at org.springframework.data.jpa.repository.query.AbstractStringBasedJpaQuery.doCreateQuery(AbstractStringBasedJpaQuery.java:107)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.createQuery(AbstractJpaQuery.java:234)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:127)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:90)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:148)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:136)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:77)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
... 78 more
Caused by: org.hibernate.type.descriptor.java.CoercionException: Cannot coerce value `[]` [java.util.Collections$EmptyList] as Long
at org.hibernate.type.descriptor.java.LongJavaType.coerce(LongJavaType.java:155)
at org.hibernate.type.descriptor.java.LongJavaType.coerce(LongJavaType.java:24)
at org.hibernate.query.internal.QueryParameterBindingImpl.coerce(QueryParameterBindingImpl.java:144)
at org.hibernate.query.internal.QueryParameterBindingImpl.setBindValue(QueryParameterBindingImpl.java:111)
... 107 more
OR (yes OR, I've not identified the reason why when executing the same test multiple times, I get one or the other exception)
java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
at org.hibernate.persister.entity.AbstractEntityPersister.isSelectable(AbstractEntityPersister.java:2039)
at org.hibernate.persister.entity.AbstractEntityPersister.fetchProcessor(AbstractEntityPersister.java:2012)
at org.hibernate.loader.ast.internal.LoaderSqlAstCreationState.visitFetches(LoaderSqlAstCreationState.java:118)
at org.hibernate.sql.results.graph.AbstractFetchParent.afterInitialize(AbstractFetchParent.java:32)
at org.hibernate.sql.results.graph.entity.AbstractEntityResultGraphNode.afterInitialize(AbstractEntityResultGraphNode.java:100)
at org.hibernate.persister.entity.AbstractEntityPersister.createDomainResult(AbstractEntityPersister.java:1300)
at org.hibernate.persister.entity.AbstractEntityPersister.selectFragment(AbstractEntityPersister.java:1892)
at org.hibernate.query.sql.internal.SQLQueryParser.resolveProperties(SQLQueryParser.java:236)
at org.hibernate.query.sql.internal.SQLQueryParser.substituteBrackets(SQLQueryParser.java:159)
at org.hibernate.query.sql.internal.SQLQueryParser.process(SQLQueryParser.java:63)
at org.hibernate.query.sql.internal.NativeSelectQueryPlanImpl.<init>(NativeSelectQueryPlanImpl.java:54)
at org.hibernate.engine.query.internal.NativeQueryInterpreterStandardImpl.createQueryPlan(NativeQueryInterpreterStandardImpl.java:39)
at org.hibernate.query.sql.internal.NativeQueryImpl.createQueryPlan(NativeQueryImpl.java:649)
at org.hibernate.query.sql.internal.NativeQueryImpl.lambda$resolveSelectQueryPlan$7(NativeQueryImpl.java:610)
at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.resolveSelectQueryPlan(QueryInterpretationCacheStandardImpl.java:83)
at org.hibernate.query.sql.internal.NativeQueryImpl.resolveSelectQueryPlan(NativeQueryImpl.java:608)
at org.hibernate.query.sql.internal.NativeQueryImpl.doList(NativeQueryImpl.java:602)
at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:363)
at org.hibernate.query.Query.getResultList(Query.java:94)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:401)
at jdk.proxy2/jdk.proxy2.$Proxy136.getResultList(Unknown Source)
at com.example.repository.CatalogItemRepository.findModelingAndHarmDefinitions(CatalogItemRepository.java:26)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703)
at com.example.repository.CatalogItemRepository$$SpringCGLIB$$0.findModelingAndHarmDefinitions(<generated>)
at com.example.TestApplicationTests.shouldBuildNamedQuery(TestApplicationTests.java:31)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
There's nothing fancy in my 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>com.example</groupId>
<artifactId>MyExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
<testcontainers.version>1.17.6</testcontainers.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.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>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Nor in my application.properties
spring.datasource.password=postgres
spring.datasource.username=postgres
spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver
spring.datasource.url=jdbc:tc:postgresql:12:///
spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
The issue clearly comes from the fact that the collection is empty.
I've therefore tried to update the query to :
WHERE (COALESCE(:workspaceIds,NULL) IS NULL OR :#{#workspaceIds.size()} = 0 OR ws.id IN (:workspaceIds) )
The test shouldReturnEmptyForNullParameter then fails with the following exception :
org.springframework.expression.spel.SpelEvaluationException: EL1011E: Method call: Attempted to call method size() on null context object
at org.springframework.expression.spel.ast.MethodReference.throwIfNotNullSafe(MethodReference.java:154)
at org.springframework.expression.spel.ast.MethodReference.getValueRef(MethodReference.java:83)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:70)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:91)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:117)
Am I missing something?
Thank you for you help.
An empty collection can't be null, and thus will lead to an illegal query with an empty in in your query.
We would argue that it succeeds falsely in previous versions of Hibernate.
The expression cannot work as it will be called for null so you would need to check for that case as well.
Try writing two methods and dispatch to one or the other, depending on whether it returns null or not; or better use the Criteria API to dynamically generate query.
Thank you for your answers. Using the Criteria API would imply a lot of refactoring some involving complex recursive queries.
After posting my message here, I found the following explanation https://hibernate.atlassian.net/browse/HHH-15743
The proposed solution involves using Spring Data Specification which would in my case also implies some refactoring. Too bad empty lists are not supported anymore.
I ended renaming the existing method as follow :
#Query("""
SELECT DISTINCT new com.dto.NameIdDto(ws.id, ws.name)
FROM UserRole ur
JOIN ur.workspace ws
WHERE (COALESCE(:workspaceIds) IS NULL OR ws.id IN (:workspaceIds))
""")
List<NameIdDto> findWorkspacesWithUsersInternal(Collection<Long> workspaceIds);
And adding the following method :
default List<NameIdDto> findWorkspacesWithUsersInternal(Collection<Long> workspaceIds) {
return findWorkspacesWithUsersInternal(CollectionUtils.isEmpty(workspaceIds) ? null : workspaceIds);
}
I'm upgrading Spring Cloud from Greenwich to 2020.0.5 as part of Spring Boot version upgrade from 2.1.x.RELEASE to 2.5.12.
I have the error below if the RestTemplate connects to another microservices.
Caused by: java.lang.AbstractMethodError: org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.choose(Ljava/lang/String;Lorg/springframework/cloud/client/loadbalancer/Request;)Lorg/springframework/cloud/client/ServiceInstance;
at org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor.lambda$intercept$2(RetryLoadBalancerInterceptor.java:107)
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329)
org.springframework.retry.RetryException: Could not recover; nested exception is java.lang.AbstractMethodError: org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.choose(Ljava/lang/String;Lorg/springframework/cloud/client/loadbalancer/Request;)Lorg/springframework/cloud/client/ServiceInstance;
at org.springframework.cloud.client.loadbalancer.LoadBalancedRecoveryCallback.recover(LoadBalancedRecoveryCallback.java:56)
at org.springframework.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:539)
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:387)
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:225)
at org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor.intercept(RetryLoadBalancerInterceptor.java:79)
at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:93)
at org.springframework.boot.actuate.metrics.web.client.MetricsClientHttpRequestInterceptor.intercept(MetricsClientHttpRequestInterceptor.java:86)
at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:93)
at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:77)
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:776)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:711)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:602)
at com.testingApp.filter.MyPreFilter.run(MyPreFilter.java:140)
at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:117)
at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:193)
at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:157)
at com.netflix.zuul.FilterProcessor.preRoute(FilterProcessor.java:133)
at com.netflix.zuul.ZuulRunner.preRoute(ZuulRunner.java:105)
at com.netflix.zuul.http.ZuulServlet.preRoute(ZuulServlet.java:125)
at com.netflix.zuul.http.ZuulServlet.service(ZuulServlet.java:74)
Code:
_restTemplate.exchange(_url, HttpMethod.GET, _httpEntity, JSONObject.class);
pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.12</version>
</parent>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
If try to upgrade to Hoxton, it can be upgraded without issue. Is it due to Zuul and Ribbon no longer supported in 2020.0.5? Is it possible to make it compatible without change code to Spring Cloud Gateway and Loadbalancer?
I have tried to make sure ribbon is new version which is spring-cloud-starter-netflix-ribbon-2.2.10.RELEASE.jar.
Hi someone a clue how to integrate a MetadataContributor in a Spring Boot application without errors?
I got:
java.util.ServiceConfigurationError: org.hibernate.boot.spi.MetadataContributor: Provider com.example.demo.TestContributor not found
at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:588) ~[na:na]
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.nextProviderClass(ServiceLoader.java:1211) ~[na:na]
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1220) ~[na:na]
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1264) ~[na:na]
at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1299) ~[na:na]
at java.base/java.util.ServiceLoader$ProviderSpliterator.tryAdvance(ServiceLoader.java:1483) ~[na:na]
at java.base/java.util.Spliterators$1Adapter.hasNext(Spliterators.java:681) ~[na:na]
at org.hibernate.boot.registry.classloading.internal.AggregatedServiceLoader$ClassPathAndModulePathAggregatedServiceLoader.hasNextIgnoringServiceConfigurationError(AggregatedServiceLoader.java:241) ~[hibernate-core-5.4.27.Final.jar!/:5.4.27.Final]
at org.hibernate.boot.registry.classloading.internal.AggregatedServiceLoader$ClassPathAndModulePathAggregatedServiceLoader.loadAll(AggregatedServiceLoader.java:219) ~[hibernate-core-5.4.27.Final.jar!/:5.4.27.Final]
at org.hibernate.boot.registry.classloading.internal.AggregatedServiceLoader$ClassPathAndModulePathAggregatedServiceLoader.getAll(AggregatedServiceLoader.java:187) ~[hibernate-core-5.4.27.Final.jar!/:5.4.27.Final]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.loadJavaServices(ClassLoaderServiceImpl.java:251) ~[hibernate-core-5.4.27.Final.jar!/:5.4.27.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:290) ~[hibernate-core-5.4.27.Final.jar!/:5.4.27.Final]
...
I have a fresh spring boot project with just
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Added a contributor
package com.example.demo;
public class TestContributor implements MetadataContributor {
Logger logger = LoggerFactory.getLogger(TestContributor.class);
#Override
public void contribute(InFlightMetadataCollector metadataCollector, IndexView jandexIndex) {
logger.info("Still works");
}
}
And added src/main/resources/META-INF/services/org.hibernate.boot.spi.MetadataContributor file with class definition
com.example.demo.TestContributor
When I start the project via Intellij everything works.
But when I build a jar mvn clean package and try to start it via jar java -jar demo-0.0.1-SNAPSHOT.jar I get the problem from above.
It still works cause the other classloaders seems to work fine. I tried to debug into Hibernate but I don't understand what the problem is. Someone has an idea?
I've added an interceptor to my JAX-RS / Resteasy Java SDK13 project running on Wildfly 18 in order to use annotations (e.g. #RolesAllowed). While the security implementation is way better than the programmatic approach, I'm getting an invocation error when Resteasy tries to call the matched function (deleteAll()). I've traced through the Interceptor flow just prior to the attempted invocation and the Interceptor approves the user and passes control onward. Then I get this error, which seems to be a security failure, despite my interceptor having approved the user.
I changed the Wildfly setting
<default-missing-method-permissions-deny-access value="false"/> but this hasn't changed the behavior.
Java Source being called with /consumers/deleteall with nothing in the body and no query string.
Security Interceptor
#Provider
#ServerInterceptor
public class SecurityInterceptor implements ContainerRequestFilter
{
private static final String AUTHORIZATION_PROPERTY = "Authorization";
private static final String AUTHENTICATION_SCHEME = "xxx";
private static final ServerResponse ACCESS_DENIED = new ServerResponse("Access denied for this resource", 401, new Headers<Object>());;
private static final ServerResponse ACCESS_FORBIDDEN = new ServerResponse("Nobody can access this resource", 403, new Headers<Object>());;
private static final ServerResponse SERVER_ERROR = new ServerResponse("INTERNAL SERVER ERROR", 500, new Headers<Object>());;
#Inject
private GenericUserDAO guDAO;
#Override
public void filter(ContainerRequestContext requestContext)
{
ResourceMethodInvoker methodInvoker = (ResourceMethodInvoker) requestContext.getProperty("org.jboss.resteasy.core.ResourceMethodInvoker");
Method method = methodInvoker.getMethod();
if (method != null)
System.out.println("Access attempt to "+method.getName());
//Access allowed for all
if( ! method.isAnnotationPresent(PermitAll.class))
{
//Access denied for all
if(method.isAnnotationPresent(DenyAll.class))
{
requestContext.abortWith(ACCESS_FORBIDDEN);
return;
}
//Get request headers
final MultivaluedMap<String, String> headers = requestContext.getHeaders();
//Fetch authorization header
final List<String> authorization = headers.get(AUTHORIZATION_PROPERTY);
//If no authorization information present; block access
if(authorization == null || authorization.isEmpty())
{
requestContext.abortWith(ACCESS_DENIED);
return;
}
//Get encoded username and password
final String token = authorization.get(0).replaceFirst(AUTHENTICATION_SCHEME + " ", "");
//Verify user access
if(method.isAnnotationPresent(RolesAllowed.class))
{
RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
Set<String> rolesSet = new HashSet<String>(Arrays.asList(rolesAnnotation.value()));
//Is user valid?
if( ! isUserAllowed(token, rolesSet))
{
requestContext.abortWith(ACCESS_DENIED);
return;
}
}
}
System.out.println("approved");
}
private boolean isUserAllowed(final String token, final Set<String> rolesSet)
{
User user = guDAO.findUserByToken(token);
if (user.getClass() == SuperUser.class)
return true;
String userRole = user.getClass().getSimpleName();
System.out.println("User role is "+userRole+" Role set is "+rolesSet.toString());
return rolesSet.contains(userRole);
}
}
JAX_RS Handlers
#LocalBean
#Stateless
#Path("/consumers")
#RolesAllowed({"SuperUser","Consumer"})
public class ConsumerEndpoint extends UserEndpoint {
/**
* Delete all consumers
* #param token
* #return
*/
#DELETE
#Path("/deleteall")
#RolesAllowed({"SuperUser","Consumer"})
public Response deleteAll() {
Response.ResponseBuilder builder = null;
if (!consumerDAO.deleteAll()) {
Map<String, String> responseObj = new HashMap<String, String>();
responseObj.put("error", "Error executing deletion");
builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(responseObj);
return builder.build();
}
return Response.ok().build();
}
}
LOG DATA
23:29:23,661 ERROR [org.jboss.as.ejb3.invocation] (default task-1) WFLYEJB0034: EJB Invocation failed on component ConsumerEndpoint for method public javax.ws.rs.core.Response com.eventhorizon.eva.rest.responder.ConsumerEndpoint.deleteAll(): javax.ejb.EJBAccessException: WFLYEJB0364: Invocation on method: public javax.ws.rs.core.Response com.eventhorizon.eva.rest.responder.ConsumerEndpoint.deleteAll() of bean: ConsumerEndpoint is not allowed
at org.jboss.as.ejb3#18.0.0.Final//org.jboss.as.ejb3.security.AuthorizationInterceptor.processInvocation(AuthorizationInterceptor.java:134)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
23:29:23,665 ERROR [io.undertow.request] (default task-1) UT005023: Exception handling request to /eva/rest/consumers/deleteall: org.jboss.resteasy.spi.UnhandledException: javax.ejb.EJBAccessException: WFLYEJB0364: Invocation on method: public javax.ws.rs.core.Response com.eventhorizon.eva.rest.responder.ConsumerEndpoint.deleteAll() of bean: ConsumerEndpoint is not allowed
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:82)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:346)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:193)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:456)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:229)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:135)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:356)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:138)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:215)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:227)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at javax.servlet.api#2.0.0.Final//javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at io.opentracing.contrib.opentracing-jaxrs2//io.opentracing.contrib.jaxrs2.server.SpanFinishingFilter.doFilter(SpanFinishingFilter.java:52)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow#18.0.0.Final//org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.core#2.0.26.Final//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.core#2.0.26.Final//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.core#2.0.26.Final//io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.core#2.0.26.Final//io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.core#2.0.26.Final//io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.core#2.0.26.Final//io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.core#2.0.26.Final//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow#18.0.0.Final//org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.core#2.0.26.Final//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow#18.0.0.Final//org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
at io.undertow.core#2.0.26.Final//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.core#2.0.26.Final//io.undertow.server.handlers.MetricsHandler.handleRequest(MetricsHandler.java:64)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.core.MetricsChainHandler.handleRequest(MetricsChainHandler.java:59)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at org.wildfly.extension.undertow#18.0.0.Final//org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
at org.wildfly.extension.undertow#18.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow#18.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow#18.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow#18.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow#18.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78)
at io.undertow.servlet#2.0.26.Final//io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99)
at io.undertow.core#2.0.26.Final//io.undertow.server.Connectors.executeRootHandler(Connectors.java:376)
at io.undertow.core#2.0.26.Final//io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
at org.jboss.threads#2.3.3.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads#2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
at org.jboss.threads#2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
at org.jboss.threads#2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: javax.ejb.EJBAccessException: WFLYEJB0364: Invocation on method: public javax.ws.rs.core.Response com.eventhorizon.eva.rest.responder.ConsumerEndpoint.deleteAll() of bean: ConsumerEndpoint is not allowed
at org.jboss.as.ejb3#18.0.0.Final//org.jboss.as.ejb3.security.AuthorizationInterceptor.processInvocation(AuthorizationInterceptor.java:134)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.as.ejb3#18.0.0.Final//org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:100)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.as.ejb3#18.0.0.Final//org.jboss.as.ejb3.deployment.processors.StartupAwaitInterceptor.processInvocation(StartupAwaitInterceptor.java:22)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.as.ejb3#18.0.0.Final//org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.as.ejb3#18.0.0.Final//org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:67)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.as.ee#18.0.0.Final//org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:60)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:438)
at org.wildfly.security.elytron-private#1.10.3.Final//org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:627)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.AccessCheckingInterceptor.processInvocation(AccessCheckingInterceptor.java:57)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.invocation#1.5.2.Final//org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:53)
at org.jboss.as.ee#18.0.0.Final//org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:198)
at org.jboss.as.ee#18.0.0.Final//org.jboss.as.ee.component.ViewDescription$1.processInvocation(ViewDescription.java:185)
at org.jboss.as.ee#18.0.0.Final//org.jboss.as.ee.component.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:81)
at deployment.eva.war//com.eventhorizon.eva.rest.responder.ConsumerEndpoint$$$view8.deleteAll(Unknown Source)
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:567)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:138)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:517)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:406)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$0(ResourceMethodInvoker.java:370)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:356)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:372)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:344)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:317)
at org.jboss.resteasy.resteasy-jaxrs#3.9.0.Final//org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:440)
... 59 more
23:29:23,670 INFO [io.undertow.request.dump] (default task-1)
----------------------------REQUEST---------------------------
URI=/eva/rest/consumers/deleteall
characterEncoding=null
contentLength=0
contentType=[application/json]
header=Accept=application/json
header=Connection=keep-alive
header=Authorization=ApiKey-v1 AC0gP9D-2jrCRDXfzyTayDb5LuUTTX9_Z2NwMDcwM0BnbWFpbC5jb20=
header=Content-Type=application/json
header=Content-Length=0
header=User-Agent=Java/13.0.1
header=Host=localhost:8080
locale=[]
method=DELETE
protocol=HTTP/1.1
queryString=
remoteAddr=/127.0.0.1:53053
remoteHost=localhost
scheme=http
host=localhost:8080
serverPort=8080
isSecure=false
--------------------------RESPONSE--------------------------
contentLength=-1
contentType=text/html;charset=UTF-8
header=Connection=keep-alive
header=Transfer-Encoding=chunked
header=Content-Type=text/html;charset=UTF-8
header=Date=Tue, 14 Jan 2020 06:29:23 GMT
status=500
==============================================================
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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.eventhorizon</groupId>
<artifactId>eva</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>Eva REST Interface</name>
<properties>
<!-- Explicitly declaring the source encoding eliminates the following
message: -->
<!-- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered
resources, i.e. build is platform dependent! -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- You can reference property in pom.xml or filtered resources (must
enable third-party plugin if using Maven < 2.1) -->
<!-- JBoss dependency versions -->
<version.jboss.maven.plugin>7.9.Final</version.jboss.maven.plugin>
<!-- Define the version of the JBoss BOMs we want to import to specify
tested stacks. -->
<version.jboss.bom>1.0.7.Final</version.jboss.bom>
<!-- Other dependency versions -->
<version.org.eclipse.m2e>1.0.0</version.org.eclipse.m2e>
<version.ro.isdc.wro4j>1.4.4</version.ro.isdc.wro4j>
<!-- other plugin versions -->
<version.surefire.plugin>2.10</version.surefire.plugin>
<version.war.plugin>2.2</version.war.plugin>
<!-- maven-compiler-plugin -->
<maven.compiler.target>12</maven.compiler.target>
<maven.compiler.source>12</maven.compiler.source>
</properties>
<dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.wildfly.bom/wildfly-jakartaee8-with-tools-builder -->
<dependency>
<groupId>org.wildfly.bom</groupId>
<artifactId>wildfly-jakartaee8-with-tools-builder</artifactId>
<version>18.0.1.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.spec.javax.management.j2ee/jboss-j2eemgmt-api_1.1_spec-parent -->
<dependency>
<groupId>org.jboss.spec.javax.management.j2ee</groupId>
<artifactId>jboss-j2eemgmt-api_1.1_spec-parent</artifactId>
<version>2.0.0.Final</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-bom</artifactId>
<version>1.1.8.Final</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180130</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>com.sendgrid</groupId>
<artifactId>sendgrid-java</artifactId>
<version>4.4.1</version>
</dependency>
<dependency>
<groupId>com.sendgrid</groupId>
<artifactId>java-http-client</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
</dependencies>
<build>
<!-- Maven will append the version to the finalName (which is the name
given to the generated war, and hence the context root) -->
<!-- <finalName>${project.artifactId}</finalName> -->
<finalName>eva</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<!-- Java EE 6 doesn't require web.xml, Maven needs to catch up! -->
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
You are using an EJB (#LocalBean) annotation. And you applied #RolesAllowed annotation. This means, your EJB / REST service invocation is automatically protected by the JEE runtime.
Basically, what you are doing in your interceptor is already performed by Wildfly. But in a different way. Now you accidentally have two ways or levels of authentication. I suggest you stick to a single implementation.
Either you go with JAAS framework or use your custom interceptor. You should not use both at the same time.
My recommended approach would be to setup a JAAS Login module in Wildfly. There should be plenty of examples of how to do that, e.g. use https://docs.wildfly.org/18/WildFly_Elytron_Security.html#Database_Authentication_Migration or JBoss Wildfly - database login module
Do not use JAAS and provide your custom security interceptor. Basically you could keep your interceptor class. In order to make it work, you could use your own set of annotations to check for access.
The CrudRepository bean
#Repository
public interface UserDao extends CrudRepository<User, Long>
{
List<User> findByFirstNameAndLastName(String firstName, String lastName);
}
for the User resource
#Entity
#Table(name="User")
public class User
{
#Id
#GeneratedValue
private long id;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
/* --- Getters,setters,default constructor -------*/
}
is not created when I start my Spring boot app
Field dao in base.package.service.UserService required a bean
of type 'base.package.dao.UserDao' that could not be found.
but the packages are definitely scanned
#SpringBootApplication(scanBasePackages= {"base.package"})
I got the strong suspicion that it has to do something with the embedded database h2 that I am using. I am trying to create the User table in schema.sql
CREATE TABLE IF NOT EXISTS User (
id INTEGER NOT NULL AUTO_INCREMENT,
first_name VARCHAR(128) NOT NULL,
last_name VARCHAR(128) NOT NULL,
PRIMARY KEY (id)
);
but as soon as I uncomment IF NOT EXISTS it throws an error (table already exists). So this firstly means that spring takes charge of created the schema. But I get the feeling that the table is not recreated because in the data.sql script
INSERT INTO User (id,first_name,last_name) VALUES (1,'Vincent', 'Vega');
I always have to manually increment the id on startup otherwise i get a
org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.USER(ID)"
Here are the jpa properties from application.properties
# below properties create schema, so schema.sql is redundant
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.datasource.initialization-mode=always
spring.jpa.database=H2
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.show-sql=true
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:~/testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE
spring.datasource.name=testdb
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
The reason why I think that the table is never recreated on startup is because I get this error when the app closes
2018-02-02 09:27:47.907 INFO [restartedMain] [StandardService] Stopping service [Tomcat]
2018-02-02 09:27:47.907 WARN [localhost-startStop-1] [WebappClassLoaderBase] The web application [ROOT] appears to have started a thread named [MVStore background writer nio:C:/Users/user/testdb.mv.db] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
This is followed by the exception that UserDao bean is not created.
***************************
APPLICATION FAILED TO START
***************************
Description:
Field dao in base.package.user.service.UserService required a bean of type 'base.package.user.dao.UserDao' that could not be found.
Action:
Consider defining a bean of type 'base.package.user.dao.UserDao' in your configuration.
POM.XML
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.M7</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>
<spring-cloud.version>Finchley.M5</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
/* .... */
EDIT
Here is the UserService
#Service
public class UserService
{
#Autowired private UserDao dao;
public List<User> findByFirstNameAndLastName(String firstName, String lastName)
{
return dao.findByFirstNameAndLastName(firstName, lastName);
}
public User save(final User user)
{
return dao.save(user);
}
}
EDIT 2
Now I am getting
Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.project.bot.user.User
at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:472)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:72)
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:169)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:107)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:90)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:300)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$3(RepositoryFactoryBeanSupport.java:287)
at org.springframework.data.util.Lazy.getNullable(Lazy.java:141)
at org.springframework.data.util.Lazy.get(Lazy.java:63)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:290)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:102)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1769)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1706)
... 102 common frames omitted
The table not being created should not have any impact on whether the bean is defined or not.
I think the problem you have here is that you are not instatiating your repository beans. Spring Data JPA repository beans are not picked up by component scans since they are only interfaces. The #Repository annotation actually does nothing here.
Spring Data JPA repo beans are created dynamically provided you have supplied the #EnableJpaRepositories in your configuration.
You may also need to put an #EntityScan to make sure all your #Entity's are recognised by Spring
#SpringBootApplication(scanBasePackages= {"base.package"})
#EnableJpaRepositories("base.package")
#EntityScan("base.package")