I'm modifying a Maven-based Liferay portlet (6.1.1) that uses Service Layer.
My needs are to add an ActiveMQ listener to the portlet (for communication with external products).
I'm trying to use integrated spring engine (3.0.7) to instance the listener.
So, to start, inside ext-sping.xml (auto managed by Liferay) I defined the following beans:
- a connection factory: org.apache.activemq.ActiveMQConnectionFactory
- a caching connection factory (org.springframework.jms.connection.CachingConnectionFactory) with targetConnectionFactory reference to previous bean.
At deploying time the error I get is:
Cannot convert value of type [org.apache.activemq.ActiveMQConnectionFactory] to
required type [javax.jms.ConnectionFactory] for property
'targetConnectionFactory': no matching editors or conversion strategy found
Obviusly org.apache.activemq.ActiveMQConnectionFactory implements javax.jms.ConnectionFactory, infact if I try to set the value by code, the deploy is done succesfully.
In my pom.xml I try to add a depenency both to activemq-core (just activemq) or activemq-all (contains also javax.jms package), but without success.
How it is possible?
Thank you
Possibly a classloader problem - the classloader loading the CachingConnectionFactory is resolving to a different javax.jms.ConnectionFactory to the one loading the ActiveMQ factory.
Run with -verbose on the command line to see which jar(s) classes are being loaded from.
Related
I am a new user of Spring framework. I am facing some confusion in understanding the difference between core spring framework and spring boot. As far as I understand, Spring boot is a framework which performs the initial setup automatically (like Setting up Maven dependencies and downloading the jar files) and comes with an embedded Tomcat server which makes it ready to deploy in just one click., Whereas, Spring MVC requires manual setup. All the tutorials that I watched for core spring show bean configuration using bean factory which configures the beans using a .XML file. In Spring boot, this bean configuration file is absent. My question is, what is the use of this bean configuration file? I did not find any legitimate use of this file in making a REST service with spring. I didn't see any use of the Application Context, Bean Factory in creating web application. Can someone point out how can bean factory be used in Spring web apps? Is there any fundamental difference between core spring and spring boot other than the additional components?
The Spring application context is essentially the "pool" of beans (service objects, which include controllers, converters, data-access objects, and so on) and related information that define an application; I recommend the reference introduction. In theory, you can get complicated with the context setup and have hierarchical organization and such, but in most real-world cases you just have a single plain context.
Inside this context you need to install all of the beans that provide the logic for your application. There are several possible ways to do this, but the two main ways are by providing XML files with have directives like bean (define an individual bean) or component-scan (automatically search for classes with certain annotations, including #Controller) and by using Java classes annotated with #Configuration, which can use annotations and #Bean methods.
The XML style is generally older, and newer applications mostly use Java configuration, but both provide entries that are collected into the context, and you can use both simultaneously. However, in any application, you have to provide some way of getting the registration started, and you will typically have one "root" XML file or configuration class that then imports other XML files and/or configuration classes. In a legacy web.xml-based application, you specify this in your servlet configuration file.
Spring Boot is, as you said, essentially a collection of ready-to-go configuration classes along with a mechanism for automatically detecting configurations and activating them. Even this requires a configuration root, though! This is the #EnableAutoConfiguration instruction, frequently used through its composite #SpringBootApplication. The application context and configuration mechanisms work normally once Boot finds them and pulls them in. Spring knows where to get started because you give it an explicit instruction to build a context starting with that entry point, usually with SpringApplication.run(MyApplication.class, args).
The embedded-server configuration just happens to be a particular set of configuration that is really useful and comes with one of the Boot starter packages. There's nothing there that you couldn't do in a non-Boot application.
As the title mentioned, I have a A component required a bean of type [SomeBean] error and I would like to know which component requires [SomeBean]. Is there a way to get more information on which bean requires the missing one?
Also, why do I get this error message? I am pretty sure that sometime missing beans generate a clearer message stating what beans require the missing ones.
Why I am asking:
I am trying to make a spring application that is similar to another (working) one, and use many similar beans. But I have trouble following the bean dependencies. So I removed one bean of the working application and run it in order to know where and how this component is used.
=> So, in general, I am looking for good ways to track bean dependencies in complex contexts.
Some time my IDE (intellij ultimate 2019) gives me some information, but here it doesn't. Maybe because the dependencies span a few packages, many being outside the application code, and use AutoConfiguration. Don't know...
If I use the spring diagram, it generates something that is not really readable (too meany beans). And the diagram is more a list of found beans structured by where there are provided, not the bean dependency diagram: my application list the beans it provides, and the autoConfig list the beans it provides. But It doesn't tell what bean of the autoConf is using which bean that my app provides. Or maybe I just don't understand how it works.
The default log configuration echoes messages to the console as they are written. By default, ERROR-level, WARN-level, and INFO-level messages are logged. You can also enable a “debug” mode by starting your application with a --debug flag.
So, indeed, you should enable that debug mode to see a more detailed log information about your error, which seems to be a missing required bean dependency.
See some more detailed info about in Spring Loggin
We are using Kafka with Spring Cloud Stream and we need to connect to a Confluent Schema Registry in our Spring Boot component see https://github.com/donalthurley/KafkaConsumeScsAndConfluent.
We have added the following configuration to create the required ConfluentSchemaRegistryClient bean see https://github.com/donalthurley/KafkaConsumeScsAndConfluent/blob/master/src/main/java/com/example/kafka/KafkaConfig.java which should override the default schema registry from Spring Cloud Stream.
However we have been seeing the following failure intermittently after some deployments.
org.springframework.messaging.MessageDeliveryException: failed to send Message to channel
The underlying cause shows this stack trace
Caused by: java.lang.NullPointerException
at org.springframework.cloud.stream.schema.client.DefaultSchemaRegistryClient.register(DefaultSchemaRegistryClient.java:71)
at org.springframework.cloud.stream.schema.avro.AvroSchemaRegistryClientMessageConverter.resolveSchemaForWriting(AvroSchemaRegistryClientMessageConverter.java:238)
at org.springframework.cloud.stream.schema.avro.AbstractAvroMessageConverter.convertToInternal(AbstractAvroMessageConverter.java:179)
at org.springframework.messaging.converter.AbstractMessageConverter.toMessage(AbstractMessageConverter.java:201)
at org.springframework.messaging.converter.AbstractMessageConverter.toMessage(AbstractMessageConverter.java:191)
at org.springframework.messaging.converter.CompositeMessageConverter.toMessage(CompositeMessageConverter.java:83)
at org.springframework.cloud.stream.binding.MessageConverterConfigurer$OutboundContentTypeConvertingInterceptor.doPreSend(MessageConverterConfigurer.java:322)
at org.springframework.cloud.stream.binding.MessageConverterConfigurer$AbstractContentTypeInterceptor.preSend(MessageConverterConfigurer.java:351)
at org.springframework.integration.channel.AbstractMessageChannel$ChannelInterceptorList.preSend(AbstractMessageChannel.java:611)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:453)
The fact that the DefaultSchemaRegistryClient is being invoked by the AvroSchemaRegistryClientMessageConverter would indicate to us that there is a problem with the wiring of our ConfluentSchemaRegistryClient bean.
Is there something else required in our configuration to ensure the ConfluentSchemaRegistryClient bean is wired correctly?
It worked for me. This is what I did :
used the configuration class exactly like you did
used the #EnableSchemaRegistryClient annotation in the project
added the avro serializer to the classpath : io.confluent:kafka-avro-serializer
set the properties as follows:
spring.cloud.stream.kafka.bindings.channel.consumer.configuration.schema.registry.url=address of your registry
spring.cloud.stream.kafka.bindings.channel.consumer.configuration.specific.avro.reader=true
where channel corresponds to the channel name in your app.
I think the last property is very important to tell Spring to use Avro serializer instead of the default serializer.
I am using Spring Cloud Stream Elmhurst.RELEASE, so properties' names might slightly differ if you use another version.
I have now moved the #EnableSchemaRegistryClient annotation to the project application class see https://github.com/donalthurley/KafkaConsumeScsAndConfluent/commit/b4cf5427d7ab0a4fed619fe54b042890f5ccb594 and redeployed and this has fixed the issue I had when it was deployed on our environment.
I had been annotating my producer and consumer classes with the #EnableSchemaRegistryClient annotation.
In all my local testing this had been working against my local docker confluent schema registry.
However on deploying to our environments it was working most of the time but failed occasionally after some deploys.
I hadn't succeeded in replicating this locally.
I noticed also in testing locally that I get the same null pointer exception stack trace if I remove the configuration for the Confluent Schema Registry.
So the problem I think I was seeing is that the AvroSchemaRegistryClientMessageConverter bean was not wired with the confluent schema registry bean when the #EnableSchemaRegistryClient annotation was not present in the project application class.
I don't understand why exactly that would be necessary but I think it may have solved the issue.
I'm trying to create a portlet with liferay 6.2 and using spring. If I create a bean without using constructor-arg or factory-method then everything works fine. But if I use either of these then I get exceptions when the portlet is deployed.
an example:
the exception I'm getting is:
01:28:21,884 ERROR [ContextLoader:323] Context initialization failed
java.lang.IncompatibleClassChangeError: class org.springframework.core.LocalVariableTableParameterNameDiscoverer$ParameterNameDiscoveringVisitor has interface org.springframework.asm.ClassVisitor as super class
I realize that this can be caused by having 2 versions of ams, but im using the spring jars that come with liferay.
You give an option yourself - duplicate classes. But without knowing how you build and what you're doing, there's hardly anything to do apart from asking you to make extra extra extra sure that you don't have duplicate resources on the classpath:
Check your deployed web application (once it's deployed to your application server) and its WEB-INF/lib folder for such duplicates. They might come in only during the buildprocess, e.g. they might not be in your IDE's workspace. Or Liferay might inject them (due to declared dependencies) during deployment.
You'll have to figure out how (and in which phase) those resources get there, then eliminate that option (e.g. through proper maven scope, e.g. "provided")
I'm developing a Spring application which shall be used by any kind of other application, no matter if that is a Spring project, a web application or even a simple single-class console application. The application who uses my project will just have to add the JAR file with my application.
So my project has a static factory class that gets and returns a bean from its Spring context which acts as an access object to access all public available functions of my project.
That part is already working.
But I need the developer of the application that uses my JAR to be able to overwrite certain configurations in my project without editing the config files in the JAR itself. At the moment those settings should be overwritable:
- the data source and hibernate bean configuration
- the jasypt (encryption) bean configuration
- the log4j settings
How do I make those settings overwriteable with configs from outside the jar?
Greetings
touchdown
Maybe a good solution would be a configuration that the user could override, for this take a look into:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java
Specially to #Configuration and #Bean
Maybe you could have a configuration class implemented and the user can override it. After extending the class and overwrite some methods that provides some beans the user shall inform it to your factory that will do nothing else than
new AnnotationConfigApplicationContext(userConfigurationClass);
If you want to replace the complete configuration, than the easyest way would be to have a parametrized factory that takes an alternative configuration file as its argument.
If you need it a bit more fine grain (lets say up to 10 parts), than you can split your application xml in several smaller once, and use again a configurable factory that allows to exchange the smaller xml files.
So I got a solution that is working for me.
I put an general import for override context-XMLs at the bottom of my main application context:
<import resource="classpath*:project/package/config/override/or-*.xml" />
So all the user has to do is to create the package "project/package/config/override" in his classpath (e.g. resource folder) and place matching XML files in it with new bean definitions.