IllegalArgumentException: No handler can be found for the key 'javax.security.auth.Subject.container' - ejb

I am basically following this tutorial:
https://www.ibm.com/developerworks/java/library/j-javaee8-security-api-4/index.html?ca=drs-
My development environment: TomEE 8.0 M1 Plume
pom.xml
<dependency>
<groupId>org.glassfish.soteria</groupId>
<artifactId>javax.security.enterprise</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
ApplicationConfig:
#CustomFormAuthenticationMechanismDefinition(
loginToContinue = #LoginToContinue(
loginPage = "/login.xhtml",
errorPage = "/login.xhtml?error",
useForwardToLogin = true
)
)
#ApplicationScoped
#Named
public class ApplicationConfig {
}
TestServlet:
#WebServlet("/test")
public class TestServlet extends HttpServlet {
#Inject
SecurityContext securityContext;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
securityContext.isCallerInRole("admin");
}
}
Go to http://localhost:8080/test, I get this exception:
05-Dec-2018 16:38:39.132 SEVERE [http-nio-8080-exec-219] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [servlet.TestServlet] in context with path [] threw exception
java.lang.IllegalArgumentException: No handler can be found for the key 'javax.security.auth.Subject.container'
at javax.security.jacc.PolicyContext.getContext(PolicyContext.java:91)
at org.glassfish.soteria.authorization.JACC$2.run(JACC.java:175)
at java.security.AccessController.doPrivileged(Native Method)
at org.glassfish.soteria.authorization.JACC.getFromContext(JACC.java:173)
at org.glassfish.soteria.authorization.JACC.getSubject(JACC.java:73)
at org.glassfish.soteria.authorization.JACC.isCallerInRole(JACC.java:78)
at org.glassfish.soteria.authorization.spi.impl.ReflectionAndJaccCallerDetailsResolver.isCallerInRole(ReflectionAndJaccCallerDetailsResolver.java:82)
at org.glassfish.soteria.SecurityContextImpl.isCallerInRole(SecurityContextImpl.java:89)
at servlet.TestServlet.doGet(TestServlet.java:20)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.openejb.server.httpd.EEFilter.doFilter(EEFilter.java:65)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:607)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.tomee.catalina.OpenEJBSecurityListener$RequestCapturer.invoke(OpenEJBSecurityListener.java:97)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)
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:770)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
I am from Spring and Spring Security background but new to CDI and EJB.
Could you please tell me how to configure that handler or am I missing something?
Thank you!

The error is caused since TomEE does not fully implement JACC on which the default authorization SPI ("ReflectionAndJaccCallerDetailsResolver") of Soteria depends.
Note that TomEE does in fact support JACC, just not fully.
There's a couple of options here (from easy to more challenging):
The obvious; wait for TomEE 8 final which should make this work one way or the other (using either their own EE Security implementation or otherwise)
Implement the SPI that Soteria uses for authorization and call TomEE/Tomcat native APIs to do the same thing that the default implementation is now using JACC for.
Contribute to TomEE and implement the missing bits in their JACC implementation (or contribute to Tomcat with a web only implementation). There's a JIRA for that already, see TOMEE-1912
I've been planning to provide an example for 2. and make the SPI more obvious in Soteria 1.1, but unfortunately haven't got around to that yet.

Related

AXON: Use MySql for EventStore and MongoDb for Projection - Events recreating records

I have an existing app that saved collections in MongoDb. As mentioned in documentation and on https://www.youtube.com/watch?v=342tqAORbAM that MongoDB is not right and that I should use plain RDBMS like MySQL /- Axon Server.
I am able to do that but when I restart the server, all the events are replayed and I get collections repeated again.
Here's how my code looks like.
Below, I am using MongoDb for saving Products in ProductDB and MySQL for eventStore.
Application Yaml
spring:
data:
mongodb:
database: productsDB
port: 27017
host: localhost
mvc:
pathmatch:
matching-strategy: ant_path_matcher
datasource:
url: jdbc:mysql://localhost:3306/mysql?autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
username: dinesh
password: abc123
name: mysql
jpa:
show-sql: true
hibernate:
ddl-auto: create
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
##Axon configuration
axon:
serializer:
events: jackson
general: jackson
messages: jackson
In Pom.Xml, I tried excluding axon-server-connector and including as well.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-spring-boot-starter</artifactId>
<version>${axon-spring-boot-starter.version}</version>
<exclusions>
<exclusion>
<groupId>org.axonframework</groupId>
<artifactId>axon-server-connector</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>${commons-beanutils.version}</version>
</dependency>
<dependency>
<groupId>org.axonframework.extensions.mongo</groupId>
<artifactId>axon-mongo</artifactId>
<version>${axon-mongo.version}</version>
</dependency>
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-metrics</artifactId>
<version>${axon-metrics.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.31</version>
</dependency>
Here's my AxonConfig
#Configuration
public class AxonConfig {
#Bean
public EntityManagerProvider getEntityManagerProvider(){
return new ContainerManagedEntityManagerProvider();
}
/* #Bean
public EventStore eventStore(EventStorageEngine storageEngine, GlobalMetricRegistry metricRegistry) {
return EmbeddedEventStore.builder()
.storageEngine(storageEngine)
.messageMonitor(metricRegistry
.registerEventBus("eventStore"))
.build();
}*/
#Bean
public TokenStore tokenStore( EntityManagerProvider entityManagerProvider) {
return JpaTokenStore.builder().entityManagerProvider(entityManagerProvider)
.serializer(JacksonSerializer.defaultSerializer()).build();
}
#Bean
public EventStorageEngine eventStorageEngine(Serializer serializer,
PersistenceExceptionResolver persistenceExceptionResolver,
#Qualifier("eventSerializer") Serializer eventSerializer,
EntityManagerProvider entityManagerProvider,
TransactionManager transactionManager) throws SQLException {
JpaEventStorageEngine eventStorageEngine = JpaEventStorageEngine.builder()
.snapshotSerializer(serializer)
.persistenceExceptionResolver(persistenceExceptionResolver)
.eventSerializer(serializer)
.entityManagerProvider(entityManagerProvider)
.transactionManager(transactionManager)
.build();
return eventStorageEngine;
}
#Bean
public EventUpcasterChain eventUpcasters(){
return new EventUpcasterChain();
}
}
I start my axon server and Application.
Step 1: Http POST Create a new product (WORKS)
Step 2: On Axon Server dashboard , event is created (WORKS)
Step 3: In MongoDb, Product collection is created and entry can be verified (WORKS)
Step 4: Stop the Springboot applicatio and restart.
Step 5: MongoDb has an additional record because event was played again.
What's missing here?
Here's what I already tried:
Create EventStore also in MOngo (Works) but I don't want to use Mongo for eventStore and want to stick to MySql/PostgreSql for Axon server ( All examples on Youtube, documents just show with H2)
Tried adding and also removing the axon-server-connector (DomainEventEntry is not created in either case)
When I enable the code to exclude
<exclusions>
<exclusion>
<groupId>org.axonframework</groupId>
<artifactId>axon-server-connector</artifactId>
</exclusion>
</exclusions>
I get below error
2022-12-03 03:24:47.844 WARN 43476 --- [cessor[event]-0] o.a.e.TrackingEventProcessor : Fetch Segments for Processor 'event' failed: org.hibernate.hql.internal.ast.QuerySyntaxException: DomainEventEntry is not mapped [SELECT MIN(e.globalIndex) - 1 FROM DomainEventEntry e]. Preparing for retry in 1s
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: DomainEventEntry is not mapped [SELECT MIN(e.globalIndex) - 1 FROM DomainEventEntry e]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:138) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:757) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:848) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:114) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:311) ~[spring-orm-5.3.24.jar:5.3.24]
at com.sun.proxy.$Proxy147.createQuery(Unknown Source) ~[na:na]
at org.axonframework.eventsourcing.eventstore.jpa.JpaEventStorageEngine.createTailToken(JpaEventStorageEngine.java:361) ~[axon-eventsourcing-4.6.2.jar:4.6.2]
at org.axonframework.eventsourcing.eventstore.AbstractEventStore.createTailToken(AbstractEventStore.java:171) ~[axon-eventsourcing-4.6.2.jar:4.6.2]
at org.axonframework.eventhandling.TrackingEventProcessor$WorkerLauncher.lambda$run$1(TrackingEventProcessor.java:1218) ~[axon-messaging-4.6.2.jar:4.6.2]
at org.axonframework.common.transaction.TransactionManager.executeInTransaction(TransactionManager.java:47) ~[axon-messaging-4.6.2.jar:4.6.2]
at org.axonframework.eventhandling.TrackingEventProcessor$WorkerLauncher.run(TrackingEventProcessor.java:1216) ~[axon-messaging-4.6.2.jar:4.6.2]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: DomainEventEntry is not mapped [SELECT MIN(e.globalIndex) - 1 FROM DomainEventEntry e]
at org.hibernate.hql.internal.ast.QuerySyntaxException.generateQueryException(QuerySyntaxException.java:79) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:103) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:220) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:636) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:748) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
... 14 common frames omitted
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: DomainEventEntry is not mapped
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:170) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:91) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.ast.tree.FromClause.addFromElement(FromClause.java:77) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:334) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3782) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3671) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:746) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:602) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:339) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:287) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:276) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192) ~[hibernate-core-5.6.14.Final.jar:5.6.14.Final]
... 20 common frames omitted
What else can I try?
I found the issue. Here's short summary how I fixed it.
Addinng Entity Scan fixed the issue
#SpringBootApplication
#EnableSwagger2
**#EntityScan(basePackageClasses = {DomainEventEntry.class, SagaEntry.class, TokenEntry.class})**
public class EventEventApplication {
public static void main(String[] args) {
SpringApplication.run(EventEventApplication.class, args);
}
}
Here's the Axon documentation
https://docs.axoniq.io/reference-guide/axon-framework/spring-boot-integration#jpa-and-persistence-contexts
TLDR : Long explanation
I figured it out what was happening. I think this will help people who are getting same issue.
Summary:
Scenario 1
By default when you use
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-spring-boot-starter</artifactId>
<version>${axon-spring-boot-starter.version}</version>
</dependency>
the axon-server is included and app the wants to use the axon-server to store events. The Axon framework, will pick the first available JPA from you code and use it to store the events.
Ex: If you use "JUST" H2 or MySQL database, the "Your tables" along with Axon-server event tables like Saga/Token Entry etc are saved in the same schema. This is when you don't create any AxonConfiguration and override to create a different Schema.
Senario2:
You have a table called "Product" in schema "ProductDB". On an event handler senario, your data will get saved in ProductDB/Product table. If you have not added any Axon configuration class, AxonAutoConfigure will save the Axon-server table also in "ProductsDB" ex: ProductsDB/Token-entry.
If you want to keep Same DB but different Schemas ex: Products in ProductDB and Axon tables in AXONDB schema then you need to write AxonConfiguration, provide EntityManagerProvider, TokenStore and EventStorageEngine.
Scenario 3
This was my scenario. My entity Product is saved in MONGODB and I wanted to save Axon events in MySQL. Now I added Axon configuration and provide the three amigo beans
#Bean
public EntityManagerProvider getEntityManagerProvider(){
return new ContainerManagedEntityManagerProvider();
}
#Bean
public TokenStore tokenStore(EntityManagerProvider entityManagerProvider) {
return JpaTokenStore.builder().entityManagerProvider(entityManagerProvider)
.serializer(JacksonSerializer.defaultSerializer()).build();
}
#Bean
public EventStorageEngine eventStorageEngine(Serializer serializer,
PersistenceExceptionResolver persistenceExceptionResolver,
#Qualifier("eventSerializer") Serializer eventSerializer,
EntityManagerProvider entityManagerProvider,
TransactionManager transactionManager) throws SQLException {
JpaEventStorageEngine eventStorageEngine = JpaEventStorageEngine.builder()
.snapshotSerializer(serializer)
.persistenceExceptionResolver(persistenceExceptionResolver)
.eventSerializer(serializer)
.entityManagerProvider(entityManagerProvider)
.transactionManager(transactionManager)
.build();
return eventStorageEngine;
}
Now the problem as I stated was that everything was fine, but in MySQL, I was not seeing domain_entry_event table and snapshot_entry_event tables. I assumed it was OK as I was using AXON-SERVER. The problem came when I restarted the application and I saw that Events were getting reapplied which was already executed to save Product entry in DB.
Root Cause: When you use a Jpa then you must also override default configuration to tell axon to stop using Axon-server (exlude axon-server-connector from starter), then you must tell the persistent context to scan table
#EntityScan(basePackageClasses = {DomainEventEntry.class, SagaEntry.class, TokenEntry.class})
Addinng Entity Scan fixed the issue
#SpringBootApplication
#EnableSwagger2
**#EntityScan(basePackageClasses = {DomainEventEntry.class, SagaEntry.class, TokenEntry.class})**
public class EventEventApplication {
public static void main(String[] args) {
SpringApplication.run(EventEventApplication.class, args);
}
}
I figured it out what was happening. I think this will help people who are getting same issue.
Summary:
Scenario 1
By default when you use
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-spring-boot-starter</artifactId>
<version>${axon-spring-boot-starter.version}</version>
the axon-server is included and app the wants to use the axon-server to store events. The Axon framework, will pick the first available JPA from you code and use it to store the events.
Ex: If you use “JUST” H2 or MySQL database, the “Your tables” along with Axon-server event tables like Saga/Token Entry etc are saved in the same schema. This is when you don’t create any AxonConfiguration and override to create a different Schema.
Senario2:
You have a table called “Product” in schema “ProductDB”. On an event handler senario, your data will get saved in ProductDB/Product table. If you have not added any Axon configuration class, AxonAutoConfigure will save the Axon-server table also in “ProductsDB” ex: ProductsDB/Token-entry.
If you want to keep Same DB but different Schemas ex: Products in ProductDB and Axon tables in AXONDB schema then you need to write AxonConfiguration, provide EntityManagerProvider, TokenStore and EventStorageEngine.
Scenario 3
This was my scenario. My entity Product is saved in MONGODB and I wanted to save Axon events in MySQL. Now I added Axon configuration and provide the three amigo beans
#Bean
public EntityManagerProvider getEntityManagerProvider(){
return new ContainerManagedEntityManagerProvider();
}
#Bean
public TokenStore tokenStore(EntityManagerProvider entityManagerProvider) {
return JpaTokenStore.builder().entityManagerProvider(entityManagerProvider)
.serializer(JacksonSerializer.defaultSerializer()).build();
}
#Bean
public EventStorageEngine eventStorageEngine(Serializer serializer,
PersistenceExceptionResolver persistenceExceptionResolver,
#Qualifier("eventSerializer") Serializer eventSerializer,
EntityManagerProvider entityManagerProvider,
TransactionManager transactionManager) throws SQLException {
JpaEventStorageEngine eventStorageEngine = JpaEventStorageEngine.builder()
.snapshotSerializer(serializer)
.persistenceExceptionResolver(persistenceExceptionResolver)
.eventSerializer(serializer)
.entityManagerProvider(entityManagerProvider)
.transactionManager(transactionManager)
.build();
return eventStorageEngine;
}
Now the problem as I stated was that everything was fine, but in MySQL, I was not seeing domain_entry_event table and snapshot_entry_event tables. I assumed it was OK as I was using AXON-SERVER. The problem came when I restarted the application and I saw that Events were getting reapplied which was already executed to save Product entry in DB.
Root Cause: When you use a Jpa then you must also override default configuration to tell axon to stop using Axon-server (exclude axon-server-connector from starter), then you must tell the persistent context to scan table
#EntityScan(basePackageClasses = {DomainEventEntry.class, SagaEntry.class, TokenEntry.class})
Adding Entity Scan fixed the issue
#SpringBootApplication
#EnableSwagger2
**#EntityScan(basePackageClasses = {DomainEventEntry.class, SagaEntry.class, TokenEntry.class})**
public class EventEventApplication {
public static void main(String[] args) {
SpringApplication.run(EventEventApplication.class, args);
}
}

Spring JDBC session causes duplicate entry exception

In my Spring Boot project, there are REST and MVC controllers. Where the MVC part should have session. This part goes fine, but when you come from a MVC page with session and start using Swagger from the browser to the API I start to see these messages on the REST API endpoints:
org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [INSERT INTO SPRING_SESSION_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) VALUES (?, ?, ?)Duplicate entry '7a69e3fe-dd7f-4a1d-85bb-2dcd617225dd-SPRING_SECURITY_SAVED_REQUE' for key 'PRIMARY'; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '7a69e3fe-dd7f-4a1d-85bb-2dcd617225dd-SPRING_SECURITY_SAVED_REQUE' for key 'PRIMARY'
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:242)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1402)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:620)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:850)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:905)
at org.springframework.session.jdbc.JdbcOperationsSessionRepository.insertSessionAttributes(JdbcOperationsSessionRepository.java:515)
at org.springframework.session.jdbc.JdbcOperationsSessionRepository.access$300(JdbcOperationsSessionRepository.java:131)
at org.springframework.session.jdbc.JdbcOperationsSessionRepository$2.doInTransactionWithoutResult(JdbcOperationsSessionRepository.java:413)
at org.springframework.transaction.support.TransactionCallbackWithoutResult.doInTransaction(TransactionCallbackWithoutResult.java:36)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
at org.springframework.session.jdbc.JdbcOperationsSessionRepository.save(JdbcOperationsSessionRepository.java:393)
at org.springframework.session.jdbc.JdbcOperationsSessionRepository.save(JdbcOperationsSessionRepository.java:131)
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.saveSession(SessionRepositoryFilter.java:377)
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:233)
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:197)
at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:150)
at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:81)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:472)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:395)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:316)
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:395)
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:254)
at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:349)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:175)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '7a69e3fe-dd7f-4a1d-85bb-2dcd617225dd-SPRING_SECURITY_SAVED_REQUE' for key 'PRIMARY'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.Util.getInstance(Util.java:408)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3976)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3912)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2530)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2683)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2486)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2079)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2013)
at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5104)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1998)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
at org.springframework.jdbc.core.JdbcTemplate.lambda$update$0(JdbcTemplate.java:855)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:605)
... 36 common frames omitted
My security configuration looks like this:
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.cors().and()
.authorizeRequests()
.antMatchers(
"/",
"/index.html",
"/oauth2-redirect.html",
"/favicon-*.png",
"/swagger-*",
"/swagger.json"
).permitAll()
.anyRequest().authenticated();
}
}
Appereantly there is a bug in delta session handling: https://github.com/spring-projects/spring-session/pull/1070
This should be fixed in version Spring Session 2.0.4.RELEASE, I worked on version Spring Session 2.0.3.RELEASE and have now downgraded to Spring Session 1.3.2.RELEASE which resolved my issues (which is in spring boot 1.5.13.RELEASE).
Will try again when version 2.0.4.RELEASE is out.
UPDATE: I tested the SNAPSHOT version, suggested here
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
<version>2.0.4.BUILD-SNAPSHOT</version>
</dependency>
This is resolving my issue.
Need to use sql query that will ignore duplicate. Spring already have the correct one, you just need to enable it:
#Configuration
class DatabaseConfig {
#Bean
public MySqlJdbcIndexedSessionRepositoryCustomizer sessionRepositoryCustomizer() {
return new MySqlJdbcIndexedSessionRepositoryCustomizer();
// or PostgreSqlJdbcIndexedSessionRepositoryCustomizer
}
}

ClassCastException: ServletRequestHandledEvent cannot be cast to WebServerInitializedEvent

I am having Spring-Boot w Vaadin project where I had to define some Spring-MVC REST controllers. While using Vaadin UI all is working fine. But when I invoke any of the REST controllers functionality wise all seems working but I can see in logs there is an exception thrown.
1102038 2017-08-09 09:36:12.223 [ajp-nio-8009-exec-5] DEBUG o.s.c.e.SimpleApplicationEventMulticaster - Non-matching event type for listener: org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer$$Lambda$102/980450043#270a6b1b
java.lang.ClassCastException: org.springframework.web.context.support.ServletRequestHandledEvent cannot be cast to org.springframework.boot.web.context.WebServerInitializedEvent
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:399)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:353)
at org.springframework.web.servlet.FrameworkServlet.publishRequestHandledEvent(FrameworkServlet.java:1078)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1009)
at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:892)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:651)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
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.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.jasig.cas.client.session.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:97)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilterAbstractAuthenticationProcessingFilter.java:200)
Thanks to the source code availability I started debugging and found that if I override org.springframework.context.event.GenericApplicationListenerAdapter.supportsEventType(ResolvableType eventType) like bellow everything is going back to normal.
#Override
#SuppressWarnings("unchecked")
public boolean supportsEventType(ResolvableType eventType) {
if (this.delegate instanceof SmartApplicationListener) {
Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve();
return (eventClass != null &&
((SmartApplicationListener) this.delegate).supportsEventType(eventClass));
} else
return (this.declaredEventType == null ||
(this.declaredEventType.isAssignableFrom(eventType) &&
!this.declaredEventType.getType().toString().equals("E")));
}
(I have added !this.declaredEventType.getType().toString().equals("E") to the last return statement)
Question:
Should I stick with this hack or just might miss something in a configuration?
Thanks in advance.
You haven't missed anything in your configuration. The ClassCastException is due to a bug in Spring Framework 5.0 RC3. It's been fixed in the latest snapshots. You could stick with your hack for now, or you could switch to using Spring Framework snapshots (that are available from https://repo.spring.io/snapshot) by overriding spring.version in your pom.xml or build.gradle.

Spring Session store user credential only

I am currently Spring MVC 4 with Spring Data Neo4j/MongoDB/JPA. Everything works find until I need to use Spring Session Data Redis to share sessions between servers. The problem is that Spring Session intercept all the HttpSession and store them in Redis. Thus the following exception is seen:
org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [org.neo4j.ogm.session.Neo4jSession]
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:92)
at org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:168)
at org.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:129)
at org.springframework.data.redis.core.DefaultBoundHashOperations.putAll(DefaultBoundHashOperations.java:86)
at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.saveDelta(RedisOperationsSessionRepository.java:778)
at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.access$000(RedisOperationsSessionRepository.java:670)
at org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:388)
at org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:245)
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:244)
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:214)
at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:167)
at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1502)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1458)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [org.neo4j.ogm.session.Neo4jSession]
at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:68)
at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:35)
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:90)
... 31 more
Caused by: java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [org.neo4j.ogm.session.Neo4jSession]
at org.springframework.core.serializer.DefaultSerializer.serialize(DefaultSerializer.java:43)
at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:63)
... 33 more
from which I think the Neo4jSession is not serializable. Thus, how can I configure Spring Session to only store client session in Redis and locally for sessions of Spring Data.
some codes:
web.xml
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
Config.class
#EnableRedisHttpSession
public class Config {
#Bean
public static ConfigureRedisAction configureRedisAction() {
return ConfigureRedisAction.NO_OP;
}
#Bean
public JedisConnectionFactory connectionFactory() {
JedisConnectionFactory connection = new JedisConnectionFactory();
connection.setHostName("myhost.aliyuncs.com");
connection.setPassword("xxxx");
connection.setPort(6379);
return connection;
}
}
Many thanks.
Problem temporarily solved. I change scope of the Neo4jSession to request, so that it doesn't store with the session.

undertow + Spring WebApplicationInitializer - Double initialization

I am migrating an old web app. It was written with old web.xml-style, now we want to programmatically build the servlet.
This is a Spring MVC app, deployed as a WAR module in an EAR under Wildfly 10.0.0.Final.
I wrote my implementation of Spring's WebApplicationInitializer (still using Spring XML config at the moment, to preceed step by step - next step will be to migrate to JavaConfig). Though I'm stuck here because the servlet is initialized twice, and the second time the initilization fails due to a filter's name conflict - NullPointerException after filter creation.
This is my initilizer:
public class MyWebApplicationInitializer implements WebApplicationInitializer {
private static final Logger log = LoggerFactory.getLogger(MyWebApplicationInitializer.class);
/**
* #see org.springframework.web.WebApplicationInitializer#onStartup(javax.servlet.ServletContext)
*/
#Override
public void onStartup(ServletContext container) throws ServletException {
log.debug("******* Initializing Web App *******");
XmlWebApplicationContext rootContext = new XmlWebApplicationContext();
rootContext.setConfigLocation("classpath:META-INF/spring/application-context.xml");
XmlWebApplicationContext webContext = new XmlWebApplicationContext();
webContext.setConfigLocation("classpath:META-INF/spring/mvc-context.xml");
container.addListener(new ContextLoaderListener(rootContext));
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(webContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
container.addFilter("log4jEnhancementFilter", Log4jEnhancementFilter.class);
log.info("******* Web App correctly initialized *******");
}
}
A bit of log below:
[ServerService Thread Pool -- 74]:[INFO] # 2016-04-19 07:19:27,725: io.undertow.servlet.spec.ServletContextImpl.log:313: Spring WebApplicationInitializers detected on classpath: [com.xyz.web.servlet.MyWebApplicationInitializer#6356dd91]
[ServerService Thread Pool -- 74]:[DEBUG] # 2016-04-19 07:19:27,725: com.xyz.web.servlet.MyWebApplicationInitializer.onStartup:44: ******* Initializing Web App *******
...
[ServerService Thread Pool -- 74]:[INFO] # 2016-04-19 07:19:27,796: com.xyz.web.servlet.MyWebApplicationInitializer.onStartup:59: ******* Web App correctly initialized *******
...
[ServerService Thread Pool -- 74]:[INFO] # 2016-04-19 07:19:27,797: io.undertow.servlet.spec.ServletContextImpl.log:313: Spring WebApplicationInitializers detected on classpath: [com.xyz.web.servlet.MyWebApplicationInitializer#427d3c64]
[ServerService Thread Pool -- 74]:[DEBUG] # 2016-04-19 07:19:27,797: com.xyz.web.servlet.MyWebApplicationInitializer.onStartup:44: ******* Initializing Web App *******
07:19:27,800 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 74) MSC000001: Failed to start service jboss.undertow.deployment.default-server.default-host./www: org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./www: java.lang.RuntimeException: java.lang.NullPointerException
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:85)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at org.jboss.threads.JBossThread.run(JBossThread.java:320)
Caused by: java.lang.RuntimeException: java.lang.NullPointerException
at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:231)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:100)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:82)
... 6 more
Caused by: java.lang.NullPointerException
at com.xyz.web.servlet.MyWebApplicationInitializer.onStartup(MyWebApplicationInitializer.java:54)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:175)
at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:184)
... 8 more
As you can see there is a double servlet's initilization; the first succeeds, the second fails due to the NPE.
What am I doing wrong and how can I fix it?

Resources