Spring-boot 2.7.0 with jax-ws 1.9 WSServletContextListener Unable to start embedded Tomcat - spring-boot

What do I do wrong with JAX-WS and SPRING-BOOT?
I use jaxws-spring v1.9, spring-boot-starter-parent v2.7.0.
I don`t have web.xml.
I have #WebService() #SOAPBinding()
My problem is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
but file is in /src/main/resource/WEB-INF/sun-jaxws.xml
2022-08-04 16:47:58.026 ERROR 20076 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:165) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577) ~[spring-context-5.3.20.jar:5.3.20]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar:2.7.0]
at com.thecloud.telecom.TelecomApplication.main(TelecomApplication.java:14) ~[classes/:na]
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:142) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:104) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:479) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:211) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:184) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162) ~[spring-boot-2.7.0.jar:2.7.0]
... 8 common frames omitted
Caused by: java.lang.IllegalStateException: StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[] failed to start
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.rethrowDeferredStartupExceptions(TomcatWebServer.java:187) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:126) ~[spring-boot-2.7.0.jar:2.7.0]
... 13 common frames omitted
Disconnected from the target VM, address: '127.0.0.1:52298', transport: 'socket'
Process finished with exit code 1
It happens when I try to use
JaxWsListener
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import com.sun.xml.ws.transport.http.servlet.WSServletContextListener;
#WebListener
public class JaxWsListener implements ServletContextAttributeListener, ServletContextListener {
private final WSServletContextListener listener;
public JaxWsListener() {
this.listener = new WSServletContextListener();
}
#Override
public void attributeAdded(ServletContextAttributeEvent event) {
listener.attributeAdded(event);
}
#Override
public void attributeRemoved(ServletContextAttributeEvent event) {
listener.attributeRemoved(event);
}
#Override
public void attributeReplaced(ServletContextAttributeEvent event) {
listener.attributeReplaced(event);
}
#Override
public void contextInitialized(ServletContextEvent sce) {
listener.contextInitialized(sce);
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
listener.contextDestroyed(sce);
}
}
without this Listener spring-boot (tomcat) started well.
for JAX-WS as well I use this class :
JaxWsServlet
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.xml.ws.transport.http.servlet.WSServlet;
import lombok.extern.log4j.Log4j2;
#Log4j2
#WebServlet(name = "JaxWsServlet", urlPatterns = JaxWsServlet.URL_PATTERN, loadOnStartup = 1)
public class JaxWsServlet extends WSServlet {
public static final String URL_PATTERN = "/jaxws";
public JaxWsServlet() {
LOG.debug("CREATE {}", this.getClass().getSimpleName());
}
#Override
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
LOG.debug("JAX-WS Init");
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException {
super.doPost(request, response);
LOG.debug("JAX-WS DoPost");
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
super.doGet(request, response);
LOG.debug("JAX-WS DoGet");
}
}
as well I have /WEB-INF/soap-jaxws.xml
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
version="2.0">
<endpoint name="SoapService"
implementation="com.ws.endpoint.SoapService"
url-pattern="/ws/call1" />
<endpoint name="SoapService2"
implementation="com.ws.endpoint.SoapService2"
url-pattern="/ws/call2" />
</endpoints>
this file parsed in the WSServletContextListener - it is hard coded there.

I solved this issue by putting /WEB-INF/sun-jaxws.xml into **/srv/main/resources/META-INF/resources/**WEB-INF/sun-jaxrs.xml
this helped me
It is enough to have in your spring-boot application:
/WEB-INF/sun-jaxws.xml - BCS it is HARDCODED in the jax-ws
#WebService
#WebListener
spring-boot-starter-parent:2.7.0
org.jvnet.jax-ws-commons.spring:jaxws-spring:1.9 - with exclusions
#Service
#WebService(
name = "SoapService",
endpointInterface = "com.ws.service.SoapService")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class SoapService
implements ISoapService { ....
and #WebListener (look at it above)
#WebListener
public class JaxWsListener implements ServletContextAttributeListener, ServletContextListener {
private final WSServletContextListener listener;
........
You do not need #WebServlet
pom.xml:
<dependency>
<groupId>org.jvnet.jax-ws-commons.spring</groupId>
<artifactId>jaxws-spring</artifactId>
<version>1.9</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
</exclusion>
<!-- ? -->
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.xml.stream.buffer</groupId>
<artifactId>streambuffer</artifactId>
</exclusion>
<exclusion>
<groupId>org.jvnet.staxex</groupId>
<artifactId>stax-ex</artifactId>
</exclusion>
</exclusions>
</dependency>

Related

Method Annotated with #EventHandler is not getting triggered in Axon Based Spring Boot Microservice

The event is getting stored in the event store but not getting persisted in the Entity table.
My Controller method
#PostMapping("/saveProduct")
public ResponseEntity<Void> productCreator(#RequestBody CreateProductModel createProductModel){
CreateProductCommand createProductCommand = CreateProductCommand.builder().
productId(UUID.randomUUID().toString()).
title(createProductModel.getTitle()).
description(createProductModel.getDescription()).
price(createProductModel.getPrice()).
discountPercentage(createProductModel.getDiscountPercentage()).
available(createProductModel.isAvailable()).build();
try {
commandGateway.sendAndWait(createProductCommand);
}catch(Exception e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(HttpStatus.OK);
}
Aggregate Class
#Aggregate
public class ProductAggregate {
#AggregateIdentifier
private String productId;
private String title;
private String description;
private int price;
private short discountPercentage;
private boolean available;
public ProductAggregate() {
//leave it blank always
}
#CommandHandler
public ProductAggregate(CreateProductCommand createProductCommand) {
ProductCreatedEvent productCreatedEvent = new ProductCreatedEvent();
BeanUtils.copyProperties(createProductCommand, productCreatedEvent);
AggregateLifecycle.apply(productCreatedEvent);
}
#EventSourcingHandler
public void on(ProductCreatedEvent productCreatedEvent) {
this.productId = productCreatedEvent.getProductId();
this.title = productCreatedEvent.getTitle();
this.description = productCreatedEvent.getDescription();
this.price = productCreatedEvent.getPrice();
this.discountPercentage = productCreatedEvent.getDiscountPercentage();
this.available = productCreatedEvent.isAvailable();
}
}
But this below class's method public void on(ProductCreatedEvent productCreatedEvent) is not getting called because of which the events are getting stored in event store but not getting persisted. Can someone help why this is happening?
#Service
public class ProductEventsHandler {
private final ProductRepo productRepo;
public ProductEventsHandler(ProductRepo productRepo) {
this.productRepo = productRepo;
}
#EventHandler
public void on(ProductCreatedEvent productCreatedEvent) {
//1. Create object of entity
Product product = new Product();
//2. Copy from productCreatedEvent(event) to entity
BeanUtils.copyProperties(productCreatedEvent, product);
//3. repository.save(entity);
productRepo.save(product);
}
}
Also, I am getting an exception while running the application as below :
2021-11-07 00:19:20.677 INFO 6668 --- [ main] com.netflix.discovery.DiscoveryClient : Initializing Eureka in region us-east-1
2021-11-07 00:19:20.719 INFO 6668 --- [ main] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration
2021-11-07 00:19:20.782 WARN 6668 --- [s.CQRS.query]-0] o.a.e.TrackingEventProcessor : Error occurred. Starting retry mode.
com.thoughtworks.xstream.security.ForbiddenClassException: com.solinvictus.Products.CQRS.events.ProductCreatedEvent
at com.thoughtworks.xstream.security.NoTypePermission.allows(NoTypePermission.java:26) ~[xstream-1.4.18.jar:1.4.18]
at com.thoughtworks.xstream.mapper.SecurityMapper.realClass(SecurityMapper.java:74) ~[xstream-1.4.18.jar:1.4.18]
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.18.jar:1.4.18]
at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:47) ~[xstream-1.4.18.jar:1.4.18]
at org.axonframework.serialization.AbstractXStreamSerializer.classForType(AbstractXStreamSerializer.java:159) ~[axon-messaging-4.2.jar:4.2]
at org.axonframework.serialization.LazyDeserializingObject.<init>(LazyDeserializingObject.java:83) ~[axon-messaging-4.2.jar:4.2]
at org.axonframework.eventhandling.EventUtils.lambda$upcastAndDeserializeTrackedEvents$1(EventUtils.java:99) ~[axon-messaging-4.2.jar:4.2]
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_202]
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_202]
at org.axonframework.eventsourcing.eventstore.BatchingEventStorageEngine$EventStreamSpliterator.tryAdvance(BatchingEventStorageEngine.java:242) ~[axon-eventsourcing-4.2.jar:4.2]
at java.util.stream.StreamSpliterators$WrappingSpliterator.lambda$initPartialTraversalState$0(StreamSpliterators.java:294) ~[na:1.8.0_202]
at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.fillBuffer(StreamSpliterators.java:206) ~[na:1.8.0_202]
at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.doAdvance(StreamSpliterators.java:161) ~[na:1.8.0_202]
at java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(StreamSpliterators.java:300) ~[na:1.8.0_202]
at java.util.Spliterators$1Adapter.hasNext(Spliterators.java:681) ~[na:1.8.0_202]
at org.axonframework.eventsourcing.eventstore.EmbeddedEventStore$EventConsumer.peekPrivateStream(EmbeddedEventStore.java:397) ~[axon-eventsourcing-4.2.jar:4.2]
at org.axonframework.eventsourcing.eventstore.EmbeddedEventStore$EventConsumer.peek(EmbeddedEventStore.java:356) ~[axon-eventsourcing-4.2.jar:4.2]
at org.axonframework.eventsourcing.eventstore.EmbeddedEventStore$EventConsumer.hasNextAvailable(EmbeddedEventStore.java:333) ~[axon-eventsourcing-4.2.jar:4.2]
at org.axonframework.common.stream.BlockingStream.hasNextAvailable(BlockingStream.java:40) ~[axon-messaging-4.2.jar:4.2]
at org.axonframework.eventhandling.TrackingEventProcessor.checkSegmentCaughtUp(TrackingEventProcessor.java:464) ~[axon-messaging-4.2.jar:4.2]
at org.axonframework.eventhandling.TrackingEventProcessor.processBatch(TrackingEventProcessor.java:351) ~[axon-messaging-4.2.jar:4.2]
at org.axonframework.eventhandling.TrackingEventProcessor.processingLoop(TrackingEventProcessor.java:275) ~[axon-messaging-4.2.jar:4.2]
at org.axonframework.eventhandling.TrackingEventProcessor$TrackingSegmentWorker.run(TrackingEventProcessor.java:1071) [axon-messaging-4.2.jar:4.2]
at org.axonframework.eventhandling.TrackingEventProcessor$WorkerLauncher.run(TrackingEventProcessor.java:1183) [axon-messaging-4.2.jar:4.2]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_202]
You've encountered a failure in Axon's upcaster because of a ForbiddenClassException thrown by XStream.
2021-11-07 00:19:20.782 WARN 6668 --- [s.CQRS.query]-0] o.a.e.TrackingEventProcessor : Error occurred. Starting retry mode.
com.thoughtworks.xstream.security.ForbiddenClassException: com.solinvictus.Products.CQRS.events.ProductCreatedEvent
To solve this you should allow XStream for your event classes to be serialized as stated in this answer
There were two issues that I found in my code :
The issue was with XStream so I excluded the Xstream dependency from the axon framework and added the XStream dependency myself ().
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-spring-boot-starter</artifactId>
<version>4.2</version>
<exclusions>
<exclusion>
<groupId>org.axonframework</groupId>
<artifactId>axon-server-connector</artifactId>
</exclusion>
<exclusion>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.17</version>
</dependency>
The silly one:
I had annotated the "id" field of the entity class with #GeneratedValue and since I was populating the value using UUID that was causing the error. It was causing the error. I didn't notice this issue until I did the 1st fix(mentioned above)

Use ElasticSearch client in non web application with Spring

I'm creating a non web application with Spring that will read data from Kafka and write it in ElasticSearch, i included the following dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
And the following configuration class:
#Configuration
public class ElasticSearchConfig extends AbstractElasticsearchConfiguration{
#Bean
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo("localhost:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
}
When i execute the following code:
#Override
public void run(String... args) throws Exception {
IndexRequest request = new IndexRequest("test-transactions");
request.id("2");
request.source("{\"name\":\"Sammie\"," + "\"lastname\":\"Goldner\"," + "\"username\":\"hugh.vonrueden\","
+ "\"amount\":9622235.2009}", XContentType.JSON);
client.index(request, RequestOptions.DEFAULT);
}
I get the following exception:
Caused by: java.lang.ClassNotFoundException: org.springframework.http.HttpHeaders
at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_251]
at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[na:1.8.0_251]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355) ~[na:1.8.0_251]
at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[na:1.8.0_251]
... 46 common frames omitted
If i include the following dependency the code works fine:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
But it brings a lot of other functionalities that i don't want in my code, is there any other way to configure spring-boot-starter-data-elasticsearch in a non web application?
Thanks.

Ignore MongoDB socket connection on Spring Test

I am using mongo in my spring project, but I cant connect to mongo server. Anyone knows a way to ignore this bean when executing tests, because sometimes I dont have the mongo server up and I dont want that this build fail.
I really like to know if I can ignore it using SpringRunner.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { Application.class })
public class ApplicationTests {
#Test
public void contextLoads() {
}
}
Stacktrace:
Caused by: org.springframework.dao.DataAccessResourceFailureException:
Timed out after 30000 ms while waiting for a server that matches WritableServerSelector.
Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketException: localhost}, caused by {java.net.UnknownHostException: localhost}}]; nested exception is com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting for a server that matches WritableServerSelector. Client view of cluster state is {type=UNKNOWN, servers=[{address=localhost:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketException: localhost}, caused by {java.net.UnknownHostException: localhost}}]
Spring components:
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Dalston.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
PS I stopped the mongodb at localhost intentionally.
You can disable Spring Boot's auto configuration of MongoDB by adding the following annotation to your ApplicationTests class:
#EnableAutoConfiguration(exclude={MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
This will prevent Spring Boot from creating the MongoClient (assuming there are no other classes in your test context annotated with #EnableAutoConfiguration or #SpringBootApplication).
I solved using embedded mongodb.
Dependency (https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo):
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>
I added specific configuration on application-test.yml (execute using spring.profile.active=test)
spring:
data:
mongodb:
database: dbtest
host: localhost
port: 27028
And the ApplicationTests.java
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { Application.class })
public class ApplicationTests {
private static final String LOCALHOST = "127.0.0.1";
private static final String DB_NAME = "dbtest";
private static final int MONGO_TEST_PORT = 27028;
private static MongodProcess mongoProcess;
private static Mongo mongo;
#BeforeClass
public static void initializeDB() throws IOException {
MongodStarter starter = MongodStarter.getDefaultInstance();
IMongodConfig mongodConfig = new MongodConfigBuilder()
.version(Version.Main.V3_3)
.net(new Net(LOCALHOST, MONGO_TEST_PORT, Network.localhostIsIPv6()))
.build();
MongodExecutable mongodExecutable = null;
try {
mongodExecutable = starter.prepare(mongodConfig);
mongoProcess = mongodExecutable.start();
mongo = new MongoClient(LOCALHOST, MONGO_TEST_PORT);
mongo.getDB(DB_NAME);
} finally {
if (mongodExecutable != null)
mongodExecutable.stop();
}
}
#Test
public void contextLoads() {}
#AfterClass
public static void shutdownDB() throws InterruptedException {
if (mongo != null) mongo.close();
if (mongoProcess != null) mongoProcess.stop();
}
}

Spring IntegrationFlow Http.inboundGateway ambiguous parameter type

I'm trying to convert the following spring integration sample to a Java Config version. https://github.com/dsyer/http-amqp-tunnel
We need a slightly modified version of this project to work in a production environment. My problem is that I keep getting the following exception when starting the application.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'httpInboundGateway' defined in org.springframework.platform.proxy.TunnelApplication: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.integration.dsl.IntegrationFlow]: Factory method 'httpInboundGateway' threw exception; nested exception is java.lang.IllegalArgumentException: Found ambiguous parameter type [class [Ljava.lang.String;] for method match: [public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.multipartResolver(org.springframework.web.multipart.MultipartResolver), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.replyMapper(org.springframework.integration.mapping.OutboundMessageMapper), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.autoStartup(boolean), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.mappedResponseHeaders(java.lang.String[]), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.phase(int), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.crossOrigin(org.springframework.integration.dsl.support.Consumer), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.errorChannel(java.lang.String), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.headerMapper(org.springframework.integration.mapping.HeaderMapper), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.requestMapper(org.springframework.integration.mapping.InboundMessageMapper), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.messageConverters(org.springframework.http.converter.HttpMessageConverter[]), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.requestTimeout(long), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.payloadExpression(org.springframework.expression.Expression), public java.lang.Class org.springframework.integration.dsl.core.IntegrationComponentSpec.getObjectType(), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.requestPayloadType(java.lang.Class), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.payloadFunction(org.springframework.integration.dsl.support.Function), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.errorChannel(org.springframework.messaging.MessageChannel)]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
at org.springframework.platform.proxy.TestServerApplication.main(TestServerApplication.java:11) [classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.integration.dsl.IntegrationFlow]: Factory method 'httpInboundGateway' threw exception; nested exception is java.lang.IllegalArgumentException: Found ambiguous parameter type [class [Ljava.lang.String;] for method match: [public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.multipartResolver(org.springframework.web.multipart.MultipartResolver), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.replyMapper(org.springframework.integration.mapping.OutboundMessageMapper), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.autoStartup(boolean), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.mappedResponseHeaders(java.lang.String[]), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.phase(int), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.crossOrigin(org.springframework.integration.dsl.support.Consumer), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.errorChannel(java.lang.String), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.headerMapper(org.springframework.integration.mapping.HeaderMapper), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.requestMapper(org.springframework.integration.mapping.InboundMessageMapper), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.messageConverters(org.springframework.http.converter.HttpMessageConverter[]), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.requestTimeout(long), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.payloadExpression(org.springframework.expression.Expression), public java.lang.Class org.springframework.integration.dsl.core.IntegrationComponentSpec.getObjectType(), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.requestPayloadType(java.lang.Class), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.payloadFunction(org.springframework.integration.dsl.support.Function), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.errorChannel(org.springframework.messaging.MessageChannel)]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
... 18 common frames omitted
Caused by: java.lang.IllegalArgumentException: Found ambiguous parameter type [class [Ljava.lang.String;] for method match: [public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.multipartResolver(org.springframework.web.multipart.MultipartResolver), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.replyMapper(org.springframework.integration.mapping.OutboundMessageMapper), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.autoStartup(boolean), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.mappedResponseHeaders(java.lang.String[]), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.phase(int), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.crossOrigin(org.springframework.integration.dsl.support.Consumer), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.errorChannel(java.lang.String), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.headerMapper(org.springframework.integration.mapping.HeaderMapper), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.requestMapper(org.springframework.integration.mapping.InboundMessageMapper), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.messageConverters(org.springframework.http.converter.HttpMessageConverter[]), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.requestTimeout(long), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.payloadExpression(org.springframework.expression.Expression), public java.lang.Class org.springframework.integration.dsl.core.IntegrationComponentSpec.getObjectType(), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.requestPayloadType(java.lang.Class), public org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec org.springframework.integration.dsl.http.BaseHttpInboundEndpointSpec.payloadFunction(org.springframework.integration.dsl.support.Function), public org.springframework.integration.dsl.core.MessagingGatewaySpec org.springframework.integration.dsl.core.MessagingGatewaySpec.errorChannel(org.springframework.messaging.MessageChannel)]
at org.springframework.util.Assert.isNull(Assert.java:92) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.integration.util.MessagingMethodInvokerHelper.findHandlerMethodsForTarget(MessagingMethodInvokerHelper.java:497) ~[spring-integration-core-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.integration.util.MessagingMethodInvokerHelper.<init>(MessagingMethodInvokerHelper.java:226) ~[spring-integration-core-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.integration.util.MessagingMethodInvokerHelper.<init>(MessagingMethodInvokerHelper.java:149) ~[spring-integration-core-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.integration.util.MessagingMethodInvokerHelper.<init>(MessagingMethodInvokerHelper.java:144) ~[spring-integration-core-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.integration.handler.MethodInvokingMessageProcessor.<init>(MethodInvokingMessageProcessor.java:60) ~[spring-integration-core-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.integration.handler.ServiceActivatingHandler.<init>(ServiceActivatingHandler.java:37) ~[spring-integration-core-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.integration.dsl.IntegrationFlowDefinition.handle(IntegrationFlowDefinition.java:985) ~[spring-integration-java-dsl-1.2.1.RELEASE.jar:na]
at org.springframework.integration.dsl.IntegrationFlowDefinition.handle(IntegrationFlowDefinition.java:964) ~[spring-integration-java-dsl-1.2.1.RELEASE.jar:na]
at org.springframework.integration.dsl.IntegrationFlowDefinition.handle(IntegrationFlowDefinition.java:950) ~[spring-integration-java-dsl-1.2.1.RELEASE.jar:na]
at org.springframework.platform.proxy.TunnelApplication.httpInboundGateway(TunnelApplication.java:93) ~[classes/:na]
at org.springframework.platform.proxy.TunnelApplication$$EnhancerBySpringCGLIB$$4e2cc6e6.CGLIB$httpInboundGateway$3(<generated>) ~[classes/:na]
at org.springframework.platform.proxy.TunnelApplication$$EnhancerBySpringCGLIB$$4e2cc6e6$$FastClassBySpringCGLIB$$e8c73d4b.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.platform.proxy.TunnelApplication$$EnhancerBySpringCGLIB$$4e2cc6e6.httpInboundGateway(<generated>) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_66]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_66]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_66]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
... 19 common frames omitted
Here's my modified version of TunnelApplication. The original can be found in the project link above.
package org.springframework.platform.proxy;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.*;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.dsl.*;
import org.springframework.integration.dsl.amqp.Amqp;
import org.springframework.integration.dsl.http.Http;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.support.HttpRequestHandlerServlet;
#Configuration
#ComponentScan
#EnableAutoConfiguration
#EnableIntegration
public class TunnelApplication
{
public static void main(String[] args)
{
SpringApplication.run(TunnelApplication.class, args);
}
#Value("${urlExpression}")
private String urlExpression;
#Value("${outboundQueue}")
private String outboundQueue;
#Value("${inboundQueue}")
private String inboundQueue;
#Autowired
private ConnectionFactory rabbitConnectionFactory;
#Bean
public Queue requestQueue()
{
return new Queue(outboundQueue, true, false, true);
}
#Bean
public Queue targetQueue()
{
return new Queue(inboundQueue, true, false, true);
}
#Bean
public ServletRegistrationBean httpInboundGatewayServletRegistration()
{
ServletRegistrationBean bean = new ServletRegistrationBean(httpInboundGatewayServlet(), "/tunnel/*");
bean.setName("httpInboundGateway");
return bean;
}
#Bean
public HttpRequestHandlerServlet httpInboundGatewayServlet()
{
return new HttpRequestHandlerServlet();
}
#Bean
public RestTemplate safeRestTemplate()
{
return new RestTemplate();
}
#Bean
public Jackson2JsonMessageConverter jsonMessageConverter()
{
return new Jackson2JsonMessageConverter();
}
#Bean
public AmqpTemplate amqpTemplate()
{
RabbitTemplate result = new RabbitTemplate(rabbitConnectionFactory);
result.setMessageConverter(jsonMessageConverter());
return result;
}
#Bean
public IntegrationFlow httpInboundGateway()
{
return IntegrationFlows.from("outbound")
.handle(Http.inboundGateway("/tunnel"))
.get();
}
#Bean
public IntegrationFlow amqpOutbound(AmqpTemplate amqpTemplate)
{
return IntegrationFlows.from("outbound")
.handle(
Amqp.outboundAdapter(amqpTemplate)
.mappedRequestHeaders("http_*")
.routingKeyExpression("headers['routingKey']")
)
.get();
}
#Bean
public IntegrationFlow amqpInboundGateway(ConnectionFactory connectionFactory)
{
return IntegrationFlows.from("inbound").handle
(
Amqp.inboundGateway(connectionFactory, inboundQueue)
.mappedRequestHeaders("http_*")
.messageConverter(jsonMessageConverter())
)
.get();
}
#Bean
public IntegrationFlow httpOutboundGateway()
{
return IntegrationFlows.from("inbound").handle(Http.outboundGateway(urlExpression)).get();
}
}
When I run TunnelApplication I get the above error. My maven pom file has been modified as follows. The main difference being that I'm using spring boot 1.5.1 and the original project uses 1.1.4.BUILD-SNAPSHOT.
<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>
<parent>
<groupId>com.redi</groupId>
<artifactId>redi-parent</artifactId>
<version>5.0.0</version>
</parent>
<artifactId>http-amqp-tunnel</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>HTTP AMQP Tunnel</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</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-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-http</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jmx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>org.springframework.platform.proxy.TunnelApplication</start-class>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I'd really appreciate some guidance. This is my first spring integration project and I feel like I'm close.
Thanks in advance for your help.
Revised Configuration
package org.springframework.platform.proxy;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.*;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.dsl.*;
import org.springframework.integration.dsl.amqp.Amqp;
import org.springframework.integration.dsl.http.Http;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.support.HttpRequestHandlerServlet;
#Configuration
#ComponentScan
#EnableAutoConfiguration
#EnableIntegration
public class TunnelApplication
{
public static void main(String[] args)
{
SpringApplication.run(TunnelApplication.class, args);
}
#Value("${urlExpression}")
private String urlExpression;
#Value("${outboundQueue}")
private String outboundQueue;
#Value("${inboundQueue}")
private String inboundQueue;
#Autowired
private ConnectionFactory rabbitConnectionFactory;
#Bean
public Queue requestQueue()
{
return new Queue(outboundQueue, true, false, true);
}
#Bean
public Queue targetQueue()
{
return new Queue(inboundQueue, true, false, true);
}
#Bean
public ServletRegistrationBean httpInboundGatewayServletRegistration()
{
ServletRegistrationBean bean = new ServletRegistrationBean(httpInboundGatewayServlet(), "/tunnel/*");
bean.setName("httpInboundGateway");
return bean;
}
#Bean
public HttpRequestHandlerServlet httpInboundGatewayServlet()
{
return new HttpRequestHandlerServlet();
}
#Bean
public RestTemplate safeRestTemplate()
{
return new RestTemplate();
}
#Bean
public Jackson2JsonMessageConverter jsonMessageConverter()
{
return new Jackson2JsonMessageConverter();
}
#Bean
public AmqpTemplate amqpTemplate()
{
RabbitTemplate result = new RabbitTemplate(rabbitConnectionFactory);
result.setMessageConverter(jsonMessageConverter());
return result;
}
#Bean
public IntegrationFlow httpInboundGateway()
{
return IntegrationFlows.from(Http.inboundGateway("/tunnel")).channel("outbound")
.get();
}
#Bean
public IntegrationFlow amqpOutbound(AmqpTemplate amqpTemplate)
{
return IntegrationFlows.from("outbound")
.handle(
Amqp.outboundAdapter(amqpTemplate)
.mappedRequestHeaders("http_*")
.routingKeyExpression("headers['routingKey']")
)
.get();
}
#Bean
public IntegrationFlow amqpInboundGateway(ConnectionFactory connectionFactory)
{
return IntegrationFlows.from
(
Amqp.inboundGateway(connectionFactory, inboundQueue)
.mappedRequestHeaders("http_*")
.messageConverter(jsonMessageConverter())
)
.channel("inbound")
.get();
}
#Bean
public IntegrationFlow httpOutboundGateway()
{
return IntegrationFlows.from("inbound").handle(Http.outboundGateway(urlExpression)).get();
}
The error I am now getting when I navigate to http://localhost:9000/tunnel is the following:
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'httpInboundGateway' is expected to be of type 'org.springframework.web.HttpRequestHandler' but was actually of type 'org.springframework.integration.dsl.StandardIntegrationFlow'
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:378) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1087) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.web.context.support.HttpRequestHandlerServlet.init(HttpRequestHandlerServlet.java:57) ~[spring-web-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at javax.servlet.GenericServlet.init(GenericServlet.java:158) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1183) ~[tomcat-embed-core-8.5.11.jar:8.5.11]
at
}
.handle(Http.inboundGateway("/tunnel"))
You can't invoke an inbound gateway from a .handle() method.
Inbound endpoints are not consumers.
It looks like it should be .from(Http.in...).
You have the same issue with the amqp inbound endpoint.

Jetty scavenging sessions error with view-scoped beans

I am trying to port a Tomcat app to JettyRunner 9.2 I want to move my app to Heroku, so I need to start it with either an embedded server, or JettyRunner. I thought JettyRunner would be easiest, as I could keep a WAR format, and make it easy to port away if necessary.
Any help would be much appreciated. If I can't get it to work soon, I may try embedded Tomcat, or look at hosting which doesn't require me to change my container.
If a different method of using Jetty - maybe embedded Jetty would be easier, please let me know and point me to some details.
So, to the app behaviour. The app seems to be ported fine and starts ok, but I'm getting an error on login. Here is the exception
2014-12-26 05:18:21.189:WARN:oejs.session:org.eclipse.jetty.server.session.HashSessionManager#69f63d95Timer: Problem scavenging sessions
java.lang.NullPointerException
at com.sun.faces.application.view.ViewScopeContextManager.destroyBeans(Unknown Source)
at com.sun.faces.application.view.ViewScopeContextManager.sessionDestroyed(Unknown Source)
at com.sun.faces.application.view.ViewScopeManager.sessionDestroyed(Unknown Source)
at com.sun.faces.application.WebappLifecycleListener.sessionDestroyed(Unknown Source)
at com.sun.faces.config.ConfigureListener.sessionDestroyed(Unknown Source)
at org.eclipse.jetty.server.session.AbstractSessionManager.removeSession(AbstractSessionManager.java:772)
at org.eclipse.jetty.server.session.AbstractSession.timeout(AbstractSession.java:302)
at org.eclipse.jetty.server.session.HashSessionManager.scavenge(HashSessionManager.java:358)
at org.eclipse.jetty.server.session.HashSessionManager$Scavenger.run(HashSessionManager.java:84)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
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)
Here are my jetty and jsf dependencies:
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.2.6.v20141205</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.2.6.v20141205</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.2.9</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
Here is my maven jetty plugin section of my pom:
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${org.eclipse.jetty.version}</version>
<configuration>
<webApp>
<overrideDescriptor>src/main/webapp/WEB-INF/jetty-web-override.xml</overrideDescriptor>
</webApp>
<contextXml>src/main/webapp/WEB-INF/jetty-context.xml</contextXml>
</configuration>
</plugin>
Listeners in my web.xml
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
jetty-web-override.xml
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
<resource-env-ref>
<resource-env-ref-name>BeanManager</resource-env-ref-name>
<resource-env-ref-type>
javax.enterprise.inject.spi.BeanManager
</resource-env-ref-type>
</resource-env-ref>
jetty-env.xml
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure id="webAppCtx" class="org.eclipse.jetty.webapp.WebAppContext">
<New id="BeanManager" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg>
<Ref id="webAppCtx"/>
</Arg>
<Arg>BeanManager</Arg>
<Arg>
<New class="javax.naming.Reference">
<Arg>javax.enterprise.inject.spi.BeanManager</Arg>
<Arg>org.jboss.weld.resources.ManagerObjectFactory</Arg>
<Arg/>
</New>
</Arg>
</New>
</Configure>
and finally, jetty.context:
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
"http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="serverClasses">
<Array type="java.lang.String">
<Item>-org.eclipse.jetty.servlet.ServletContextHandler.Decorator</Item>
</Array>
</Set>
</Configure>
This issue is caused by a bug in the JSF implementation to do with ViewScoped beans, which is described here The described bug is in JSF 2.29 and 2.28. The fix is in 2.30, which is not yet released.
I tried going back versions in the 2.2 heirarchy. 2.27 and before this bug disappeared, but other bugs occur in ViewScoped beans.
It looks like View Scoped beans are basically broken in jsf 2.2 (as far as I looked), so as a temporary measure, I have changed all my View Scoped beans to Request Scoped. This avoids the error.
I just made the following workaround.
I'm using Jetty 9.2, CDI 1.2 (Weld) and Mojarra 2.28.
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import javax.enterprise.inject.spi.CDI;
import javax.faces.FacesException;
import javax.faces.context.ExternalContext;
import javax.faces.context.ExternalContextFactory;
import javax.faces.context.ExternalContextWrapper;
import com.sun.faces.util.Util;
public class CDIViewScopeFixExternalContextFactory extends ExternalContextFactory{
private final ExternalContextFactory wrapped;
public CDIViewScopeFixExternalContextFactory(ExternalContextFactory wrapped){
this.wrapped = wrapped;
}
#Override
public ExternalContext getExternalContext(Object context, Object request,
Object response) throws FacesException {
ExternalContext externalContext = getWrapped().getExternalContext(context, request, response);
CDIViewScopeWorkaround wrapper = new CDIViewScopeWorkaround(externalContext);
return wrapper;
}
#Override
public ExternalContextFactory getWrapped() {
return this.wrapped;
}
private static class CDIViewScopeWorkaround extends ExternalContextWrapper{
private static String CDI_KEY;
static {
try {
Field f = Util.class.getDeclaredField("CDI_AVAILABLE_PER_APP_KEY");
f.setAccessible(true);
CDI_KEY = (String) f.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private final ExternalContext wrapped;
public CDIViewScopeWorkaround(ExternalContext wrapped){
this.wrapped = wrapped;
}
#Override
public ExternalContext getWrapped() {
return wrapped;
}
#Override
public Map<String, Object> getApplicationMap() {
MapFix mapFix = new MapFix(super.getApplicationMap());
return mapFix;
}
}
private static class MapFix extends MapWrapper<String,Object>{
public MapFix(Map<String, Object> delegate) {
super(delegate);
}
#Override
public Object get(Object key) {
if(CDIViewScopeWorkaround.CDI_KEY.equals(key)){
return CDI.current().getBeanManager();
}
return super.get(key);
}
}
private static class MapWrapper<K,V> implements Map<K,V>{
private Map<K,V> delegate;
public int size() {
return delegate.size();
}
public boolean isEmpty() {
return delegate.isEmpty();
}
public boolean containsKey(Object key) {
return delegate.containsKey(key);
}
public boolean containsValue(Object value) {
return delegate.containsValue(value);
}
public V get(Object key) {
return delegate.get(key);
}
public V put(K key, V value) {
return delegate.put(key, value);
}
public V remove(Object key) {
return delegate.remove(key);
}
public void putAll(Map<? extends K, ? extends V> m) {
delegate.putAll(m);
}
public void clear() {
delegate.clear();
}
public Set<K> keySet() {
return delegate.keySet();
}
public Collection<V> values() {
return delegate.values();
}
public Set<java.util.Map.Entry<K, V>> entrySet() {
return delegate.entrySet();
}
public boolean equals(Object o) {
return delegate.equals(o);
}
public int hashCode() {
return delegate.hashCode();
}
public MapWrapper(Map<K,V> delegate){
this.delegate = delegate;
}
}
}
faces-config.xml
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.ord/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
<application>
…
</application>
<factory>
<external-context-factory>your.package.CDIViewScopeFixExternalContextFactory</external-context-factory>
</factory>
</faces-config>
I have the same issue with a 7.0.55 tomcat on a linux system.
For me, JAVASERVERFACES-3450 is not the problem, because this ticket refers to null instances of view scoped beans which are already destroyed.
Our exception in ViewScopeContextManager.destroyBeans(Unknown Source) occurs because of a null instance of beanManager.
With a Tomcat 7.0.55 on a windows system, everything works... :(

Resources