Statement of problem:
I am refactoring my application from Spring 5.x to Spring 6.0.0 .
Due to changes in the java API's imposed by Oracle, some dependencies have been forced to be changed.
There appears to be a dependency conflict where the org.springframework.jms.listener.MessageListenerContainer requires a jakarta.jms.ConnectionFactory, but the org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory extends the older javax.jms.ConnectionFactory .
I suspect that there is a POM dependency that I am missing, but I have been unable to resolve it.
POM excerpt:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-xml</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-flow</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jms</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jdbc</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-file</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client</artifactId>
<version>2.27.1</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-spring-integration</artifactId>
<version>2.27.1</version>
</dependency>
Code Snip:
// ActiveMQConnectionFactory implements javax.jms.ConnectionFactory
#Order(0)
public ActiveMQConnectionFactory connectionFactory() throws JMSException {
if (connectionFactory == null) {
connectionFactory = new ActiveMQConnectionFactory();
PropertyValue pv = configPropertiesService.fetchPropertyValue(PropertyValueConstants.ACTIVEMQ_BROKER_URL,
PropertyValueConstants.ACTIVEMQ_BROKER_URL_DEFAULT);
PropertyValue pvu = configPropertiesService.fetchPropertyValue(PropertyValueConstants.ACTIVEMQ_BROKER_UNAME,
PropertyValueConstants.ACTIVEMQ_BROKER_USERNAME_DEFAULT);
PropertyValue pvp = configPropertiesService.fetchPropertyValue(PropertyValueConstants.ACTIVEMQ_BROKER_PASS,
PropertyValueConstants.ACTIVEMQ_BROKER_PASS_DEFAULT);
connectionFactory.setBrokerURL(pv.getValue());
connectionFactory.setPassword(pvp.getValue());
}
return connectionFactory;
}
#Bean(name = "MessageDrivenAdapter")
public MessageListenerContainer getContainer() {
DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
container.setConnectionFactory(connectionFactory()); // requires jakarta.jms.ConnectionFactory
container.setDestinationName("requestsQueue");
container.setMessageListener(messageListener());
container.setAutoStartup(false);
container.setTaskExecutor(stepTaskExecutor);
container.setConcurrentConsumers(5);
return container;
}
ActiveMQ developers provide two flavours of their library (seems to be the most sober approach for that messy javax -> jakarta transition):
ActiveMQ Artemis JMS Client - compatible with Java EE API (javax. namespace)
ActiveMQ Artemis Jakarta Messaging Client - compatible with JakartaEE 9 API (jakarta. namespace)
You need the second one.
Related
Background: Getting NoSuchMethodError - while doing mongo connection.
This is spring application. If i remove mongo template code then with mongo client it is working fine but with mongo template it is failing.
Dependencies I have added in my pom
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-core</artifactId>
<version>4.6.1</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.6.1</version>
</dependency>
Code Snipet
final ConnectionString connectionString = new ConnectionString(
"mongodb://ssdsd:wewdsds:2323");
final MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(connectionString)
.applyToSslSettings(builder -> {
builder.enabled(true);
builder.invalidHostNameAllowed(true);
}).build();
MongoClient client = MongoClients.create(settings);
SimpleMongoClientDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, "db");
MongoTemplate template = new MongoTemplate(factory);
Exception i am getting
Root Exception stack trace:
java.lang.NoSuchMethodError:
org.springframework.util.Assert.noNullElements(Ljava/util/Collection;Ljava/lang/String;)V
at org.springframework.data.mongodb.core.convert.MongoCustomConversions$MongoConverterConfigurationAdapter.registerConverters(MongoCustomConversions.java:287)
at org.springframework.data.mongodb.core.convert.MongoCustomConversions$MongoConverterConfigurationAdapter.from(MongoCustomConversions.java:185)
at org.springframework.data.mongodb.core.convert.MongoCustomConversions.<init>(MongoCustomConversions.java:95)
at org.springframework.data.mongodb.core.MongoTemplate.getDefaultMongoConverter(MongoTemplate.java:3015)
at org.springframework.data.mongodb.core.MongoTemplate.<init>(MongoTemplate.java:225)
at org.springframework.data.mongodb.core.MongoTemplate.<init>(MongoTemplate.java:210)
Updated for classpath dependancies:
spring-boot-2.1.6.RELEASE.jar
spring-boot-autoconfigure-2.1.6.RELEASE.jar
spring-cloud-cloudfoundry-connector-1.2.3.RELEASE.jar
spring-cloud-core-1.2.3.RELEASE.jar
spring-cloud-spring-service-connector-1.2.3.RELEASE.jar
spring-context-5.3.24.jar
spring-context-support-2.5.6.jar
spring-data-commons-2.7.6.jar
spring-data-mongodb-3.4.6.jar
spring-expression-5.3.24.jar
spring-jms-2.5.6.jar
spring-tx-5.3.24.jar
spring-web-5.3.22.jar
Please help to resolve this issue
I am using spring boot latest version 3.0.1 with camel and required to do IBM MQ connection to read messages. STS showing below error.
ERROR The method setTargetConnectionFactory(ConnectionFactory) from the type SingleConnectionFactory refers to the missing type ConnectionFactory
Code:
public CachingConnectionFactory createCrewcachingConnectionFactory() {
CachingConnectionFactory factory = new CachingConnectionFactory();
factory.setSessionCacheSize(10);
factory.setTargetConnectionFactory(connectionFactory1());
return factory;
}
public ConnectionFactory connectionFactory1() {
MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();
connectionFactory.setHostName("MQ Host name");
connectionFactory.setPort("MQ port");
connectionFactory.setChannel("MQ Channel");
connectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
return connectionFactory;
}
POM Dependencies:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath></relativePath>
</parent>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot</artifactId>
<version>3.19.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>3.19.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jms</artifactId>
<version>3.19.0</version>
</dependency>
You will need the JMS API. Something like:
<!-- https://mvnrepository.com/artifact/javax.jms/javax.jms-api -->
<dependency>
<groupId>javax.jms</groupId>
<artifactId>javax.jms-api</artifactId>
<version>2.0.1</version>
</dependency>
pom.xml dependencies
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>jersey-apache-connector</artifactId>
</dependency>
Using Jersey 2.33 version and javax.ws.rs-api version 2.1.1 jars and from below sample code, I'm trying to invoke
new JerseyClientBuilder()
.withConfig(clientConfig)
.executorService(executorService)
and getting below error
Caused by: java.lang.NoSuchMethodError:
org.glassfish.jersey.client.JerseyClientBuilder.executorService(Ljava/util/concurrent/ExecutorService;)Ljavax/ws/rs/client/ClientBuilder;
#ApplicationScoped
public class SimpleHttpClient {
#Resource
private ManagedExecutorService executorService;
#Override
public ClientBuilder newHttpClientBuilder(ClientSettings settings) {
ClientConfig configuration = new ClientConfig();
configuration.property(ClientProperties.CONNECT_TIMEOUT, TimeUnit.MILLISECONDS);
configuration.property(ClientProperties.READ_TIMEOUT, TimeUnit.MILLISECONDS);
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(settings.getConnectionPoolSize());
connectionManager.setDefaultMaxPerRoute(50);
configuration.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);
configuration.connectorProvider(new ApacheConnectorProvider());
return new JerseyClientBuilder().withConfig(configuration).executorService(executorService);
}
}
I'm using spring boot 2 to create a project and use websocket using reactive web dependency. My application is worked correctly until I add datarest dependency. after I add datarest dependency application give
' failed: Error during WebSocket handshake: Unexpected response code: 404
is any way to resolve this conflict?.
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.integration/spring-integration-file -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-file</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
WebSocketConfiguration
#Configuration
public class WebSocketConfiguration {
#Bean
public IntegrationFlow fileFlow(PublishSubscribeChannel channel, #Value("file://${HOME}/Desktop/in") File file) {
FileInboundChannelAdapterSpec in = Files.inboundAdapter(file).autoCreateDirectory(true);
return IntegrationFlows.from(
in,
p -> p.poller(pollerFactory -> {
return pollerFactory.fixedRate(1000);
})
).channel(channel).get();
}
#Bean
#Primary
public PublishSubscribeChannel incomingFilesChannel() {
return new PublishSubscribeChannel();
}
#Bean
public WebSocketHandlerAdapter webSocketHandlerAdapter() {
return new WebSocketHandlerAdapter();
}
#Bean
public WebSocketHandler webSocketHandler(PublishSubscribeChannel channel) {
return session -> {
Map<String, MessageHandler> connections = new ConcurrentHashMap<>();
Flux<WebSocketMessage> publisher = Flux.create((Consumer<FluxSink<WebSocketMessage>>) fluxSink -> {
connections.put(session.getId(), new ForwardingMessageHandler(session, fluxSink));
channel.subscribe(connections.get(session.getId()));
}).doFinally(signalType -> {
channel.unsubscribe(connections.get(session.getId()));
connections.remove(session.getId());
});
return session.send(publisher);
};
}
#Bean
public HandlerMapping handlerMapping(WebSocketHandler webSocketHandler) {
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
handlerMapping.setOrder(10);
handlerMapping.setUrlMap(Collections.singletonMap("/ws/files", webSocketHandler));
return handlerMapping;
}
}
spring-boot-starter-data-rest brings spring-boot-starter-web as a transitive dependency (so basically Spring MVC). This makes Spring Boot configure your application as a Spring MVC web application.
Spring Data REST does not currently support Spring WebFlux (see this issue for more information on that).
Your only choice is to remove the Spring Data REST dependency, as you can't have both Spring MVC and Spring WebFlux in the same Spring Boot application.
Just taking Spring-Boot for a spin and decided to mix in Camel because I need some arcane Headers work in the rest client I am working on. Setting up the application was fine until I added the camel-http component to my POM, then I get this on init:
Exception in thread "main" org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
I've havent got the first idea of where to start to look for the problem. I gather Spring Boot will look up the classpath and try to wire stuff up, so is there a way for the to block the Camel packages from being acted on or something of the sort?
Complete log of the start up in this Gist
Here's my main aplication code:
#ComponentScan
#EnableAutoConfiguration
public class Application {
private static ApplicationContext ctx;
public static void main(String[] args) throws Exception {
ctx = SpringApplication.run(Application.class, args);
//Right outta Spring 4 docs
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
//---
// FIXME: ugly hack to allow some POC woek while wait for proper Camel/Spring4 unit tests fix.
Application app = new Application();
app.executeTests();
}
/**
* Dev QOL - unit tests are broken for now, see:
* https://issues.apache.org/jira/browse/CAMEL-7074
* <p/>
* Waiting for fix (Too lay to checkout and build my own Camel)
*/
private void executeTests() throws Exception {
testAuth();
}
#Bean
DefaultCamelContext camelCtx() throws Exception {
DefaultCamelContext camel = new DefaultCamelContext();
camel.addRoutes(cryptsyRouteBuilder());
camel.start();
return camel;
}
#Bean
public CryptsyRouteBuilder cryptsyRouteBuilder() throws Exception{
CryptsyRouteBuilder bean = new CryptsyRouteBuilder();
bean.setCryptsy(cryptsy());
return bean;
}
#Bean
public Cryptsy cryptsy() throws IOException {
return new Cryptsy();
}
protected void testAuth() throws Exception {
ProducerTemplate producer = camelCtx().createProducerTemplate();
producer.requestBody("direct:start", "Why, hullo there", String.class);
}
}
And my POM dependencies:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>0.5.0.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-actuator</artifactId>-->
<!--</dependency>-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- Camel -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-javaconfig</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-quartz</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test-spring</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-http</artifactId>
<version>${camel.version}</version>
</dependency>
<!-- Assorted -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
</dependencies>
<properties>
<start-class>xxx.xxxx.Application</start-class>
<camel.version>2.12.2</camel.version>
</properties>
The exception is telling you that Spring Boot thinks you want to build a web server, but can't find the right dependencies on the classpath. The most obvious reason for that in your case would be that the HTTP dependencies you added included Servlet APIs. I see no reason why you need that for a client app, but only you would know whether you need it or not. Maybe you can exclude it?
If you do need the Servlet dependencies and just want to explicitly tell Boot that you aren't creating a web application you can set the property spring.main.web_environment=false, or use the SpringApplication (or SpringApplicationBuilder) API directly to set the same flag. See docs here for background information.