Bean casting error from nested injections - java

I am working with Spring Integration with my project right now, specifically with MessageChannel/PublishSubscribeChannel. What I am trying to achieve is to create a broker module, so that other part of the system can call this module to send message to a specific MessageChannel.
Here is what I am doing now in the broker module:
#Configuration
public class BrokerConfiguration {
#Bean
public MessageChannel brokerChannel1() {
return new PublishSubscribeChannel();
}
}
and:
#Component
public class BrokerA {
#Autowired
#Qualifier("brokerChannel1")
public MessageChannel messageChannel;
public void sendAMessage() {
messageChannel.send(MessageBuilder.withPayload("This is a message!").build());
}
}
I have played around this setup by creating a SpringBootApplication within the broker module and it seems to work perfectly fine. However, when I try to use it in a different module of my system like this:
#Autowired
private BrokerA brokerA;
public void doSomethingHere() {
brokerA.sendAMessage();
}
I get a ClassCastException like this:
java.lang.ClassCastException: org.springframework.integration.channel.PublishSubscribeChannel cannot be cast to org.springframework.messaging.MessageChannel
And when I change messageChannel in BrokerA to the type of PublishSubscribeChannel, it will complain about PublishSubscribeChannel doesn't have a method called send().
This really baffles me. Any suggestions or comments? Thank you!

You have an old version of Spring Integration on the classpath; MessageChannel etc was moved from o.s.integration... to o.s.messaging in Spring 4.0.
You need to use Spring Integration 4.x.

Check your classpath, probably you have duplicated jars.

I ran your code on my environment with last spring boot version without any version specification about spring and it's working just right, the only error is on
MessageBuilder.withPayload("This is a message!") it should be MessageBuilder.withPayload("This is a message!").build()
And I verified using org.springframework.integration.support.MessageBuilder.

Try doing an explicit cast in the return statement of brokerChannel1() in BrokerConfiguration.

Related

Micronaut - What is Springframework #Bean equivalent?

I am very new to Micronauts and I have a fair bit of experience developing spring boot applications. With this background I was stumbled upon creating custom beans like how I used to create with #Bean annotations on Spring applications.
In my case I have a library that provides an Interface and its implementation class. I wanted to use the interface in my code and try to inject the implementation and it failes with below error
Caused by: io.micronaut.context.exceptions.NoSuchBeanException: No bean of type [io.vpv.saml.metadata.service.MetaDataParser] exists for the given qualifier: #Named('MetaDataParserImpl'). Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).
Here is my code
#Singleton
public class ParseMetadataImpl implements ParseMetadata {
private Logger logger = LoggerFactory.getLogger(this.getClass());
#Inject
#Named("MetaDataParserImpl")
private MetaDataParser metaDataParser;
#Override
public IDPMetaData getIDPMetaData(URL url) throws IOException {
logger.info("Parsing {}", url);
logger.info("metaDataParser {}", metaDataParser);
return metaDataParser.parseIDPMetaData(url);
}
}
I am sure there is somehting wrong I am doing and need to understand what to do. I have this working by adding below code and removing annotations around metaDataParser.
#PostConstruct
public void initialize() {
//Want to Avoid This stuff
this.metaDataParser = new MetaDataParserImpl();
}
Using Spring Boot it would be possible to add a #Bean annotation to create some custom beans we can do #Autowired to inject it everywhere on our application. Is there an equivalent on Micronauths that I am missing. I went through the guide on https://docs.micronaut.io/2.0.0.M3/guide/index.html and was not able to get anything to get this working.
Can someone suggest how I can use the #Inject to inject custom beans?
Just incase you want to see this, here is the application on Github.
https://github.com/reflexdemon/saml-metadata-viewer
With the help from Deadpool and a bit of reading I got what I was looking for. The solution was creating #BeanFactory
See Javadoc here: https://docs.micronaut.io/latest/guide/ioc.html#builtInScopes
The #Prototype annotation is a synonym for #Bean because the default scope is prototype.
Thus here is an example that will match the the behavior of Spring framework
Here is the answer for anyone who also is looking for such a thing.
import io.micronaut.context.annotation.Factory;
import io.vpv.saml.metadata.service.MetaDataParser;
import io.vpv.saml.metadata.service.MetaDataParserImpl;
import javax.inject.Singleton;
#Factory
public class BeanFactory {
#Singleton
public MetaDataParser getMetaDataParser() {
return new MetaDataParserImpl();
}
}

Spring integration ip - udp channel with java code only

I've been looking at the Spring integration ip module, I wanted to create UDP channel for receiving, but I found I can only do it with XML.
I was thinking that I could make something out if I looked inside the implementation code, but it creates bean definition itself, from parameters supplied in xml.
I can't use xml definitions in my code, is there a way to make it work with spring without xml?
alternatively, is there any better way in java to work with udp?
Starting with version 5.0 there is Java DSL on the matter already, so the code for UDP Channel Adapters may look like:
#Bean
public IntegrationFlow inUdpAdapter() {
return IntegrationFlows.from(Udp.inboundAdapter(0))
.channel(udpIn())
.get();
}
#Bean
public QueueChannel udpIn() {
return new QueueChannel();
}
#Bean
public IntegrationFlow outUdpAdapter() {
return f -> f.handle(Udp.outboundAdapter(m -> m.getHeaders().get("udp_dest")));
}
But with existing Spring Integration version you can simply configure UnicastReceivingChannelAdapter bean:
#Bean
public UnicastReceivingChannelAdapter udpInboundAdapter() {
UnicastReceivingChannelAdapter unicastReceivingChannelAdapter = new UnicastReceivingChannelAdapter(1111);
unicastReceivingChannelAdapter.setOutputChannel(udpChannel());
return unicastReceivingChannelAdapter;
}
In the Reference Manual you can find the Tips and Tricks chapter for some info how to write Spring Integration application with raw Java and annotation configuration.
I added JIRA to address Java sample in the Reference Manual.

How to register custom converters in spring boot?

I writing application using spring-boot-starter-jdbc (v1.3.0).
The problem that I met: Instance of BeanPropertyRowMapper fails as it cannot convert from java.sql.Timestamp to java.time.LocalDateTime.
In order to copy this problem, I implemented
org.springframework.core.convert.converter.Converter for these types.
public class TimeStampToLocalDateTimeConverter implements Converter<Timestamp, LocalDateTime> {
#Override
public LocalDateTime convert(Timestamp s) {
return s.toLocalDateTime();
}
}
My question is: How do I make available TimeStampToLocalDateTimeConverter for BeanPropertyRowMapper.
More general question, how do I register my converters, in order to make them available system wide?
The following code bring us to NullPointerException on initialization stage:
private Set<Converter> getConverters() {
Set<Converter> converters = new HashSet<Converter>();
converters.add(new TimeStampToLocalDateTimeConverter());
converters.add(new LocalDateTimeToTimestampConverter());
return converters;
}
#Bean(name="conversionService")
public ConversionService getConversionService() {
ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean();
bean.setConverters(getConverters());
bean.afterPropertiesSet();
return bean.getObject();
}
Thank you.
All custom conversion service has to be registered with the FormatterRegistry. Try creating a new configuration and register the conversion service by implementing the WebMvcConfigurer
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new TimeStampToLocalDateTimeConverter());
}
}
Hope this works.
I'll copy my answer from https://stackoverflow.com/a/72781591/140707 since I think the two questions are similar (so the answer applies to both).
Existing answers didn't work for me:
Customizing via WebMvcConfigurerAdapter.addFormatters (or simply annotating the converter with #Component) only works in the WebMvc context and I want my custom converter to be available everywhere, including #Value injections on any bean.
Defining a ConversionService bean (via ConversionServiceFactoryBean #Bean or #Component) causes Spring Boot to replace the default ApplicationConversionService on the SpringApplication bean factory with the custom bean you've defined, which will probably be based on DefaultConversionService (in AbstractApplicationContext.finishBeanFactoryInitialization). The problem is that Spring Boot adds some handy converters such as StringToDurationConverter to the standard set in DefaultConversionService, so by replacing it you lose those conversions. This may not be an issue for you if you don't use them, but it means that solution won't work for everyone.
I created the following #Configuration class which did the trick for me. It basically adds custom converters to the ConversionService instance used by Environment (which is then passed on to BeanFactory). This maintains as much backwards compatibility as possible while still adding your custom converter into the conversion services in use.
#Configuration
public class ConversionServiceConfiguration {
#Autowired
private ConfigurableEnvironment environment;
#PostConstruct
public void addCustomConverters() {
ConfigurableConversionService conversionService = environment.getConversionService();
conversionService.addConverter(new MyCustomConverter());
}
}
Obviously you can autowire a list of custom converters into this configuration class and loop over them to add them to the conversion service instead of the hard-coded way of doing it above, if you want the process to be more automatic.
To make sure this configuration class gets run before any beans are instantiated that might require the converter to have been added to the ConversionService, add it as a primary source in your spring application's run() call:
#SpringBootApplication
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(new Class<?>[] { MySpringBootApplication.class, ConversionServiceConfiguration.class }, args);
}
}
If you don't do this, it might work, or not, depending on the order in which your classes end up in the Spring Boot JAR, which determines the order in which they are scanned. (I found this out the hard way: it worked when compiling locally with an Oracle JDK, but not on our CI server which was using a Azul Zulu JDK.)
Note that for this to work in #WebMvcTests, I had to also combine this configuration class along with my Spring Boot application class into a #ContextConfiguration:
#WebMvcTest(controllers = MyController.class)
#ContextConfiguration(classes = { MySpringBootApplication.class, ConversionServiceConfiguration.class })
#TestPropertySource(properties = { /* ... properties to inject into beans, possibly using your custom converter ... */ })
class MyControllerTest {
// ...
}
I suggest to use #Autowired and the related dependency injection mechanism of spring to use a single ConversionService instance throughout your application. The ConversionService will be instantiated within the configuration.
All Converters to be available application wide receive an annotation (e.g. #AutoRegistered). On application start a #Component FormatterRegistrar (Type name itself is a bit misleading, yes it is "...Registrar" as it does the registering. And #Component as it is fully spring managed and requires dependency injection) will receive #AutoRegistered List of all annotated Converters.
See this thread for concrete implementation details. We use this mechanism within our project and it works out like a charm.
org.springframework.web.servlet.config.annotation.WebMvcConfigurer or any on its implementation is one stop place for any kind of customization in spring boot project. It prvoides various methods, for your Converter requirement.
Just create a new Converter by extending org.springframework.core.convert.converter.Converter<S, T>. Then register it with Spring by your class overriding method org.springframework.web.servlet.config.annotation.WebMvcConfigurer.addFormatters(FormatterRegistry)
Note there are Other types of Converter also which basically starts from ConditionalConverter.
Trying adding
#Converter(autoApply = true)
Its needs to be placed over the convertor class. This works for me in case of Convertor needed for Localdate for interacting to DB.
#Converter(autoApply = true)
public class LocalDateAttributeConverter implements AttributeConverter<LocalDate, Date> {
#Override
public Date convertToDatabaseColumn(LocalDate locDate) {
return (locDate == null ? null : Date.valueOf(locDate));
}
#Override
public LocalDate convertToEntityAttribute(Date sqlDate) {
return (sqlDate == null ? null : sqlDate.toLocalDate());
}
}
This is now applied automatically while interacting with DB.

Is it possible to write a Guice-like module in Spring Framework with Java configuration?

I was wondering if there was a sort of compromise that allowed you to emulate/leverage the Google Guice style EDSL way of writing modules which binds interfaces to implementations in Spring.
For example, say I had a Google Guice Module that looked like this:
public class BillingModule extends AbstractModule {
protected void configure() {
bind(BillingService.class).to(RealBillingService.class);
}
}
This binds the BillingService interface to the RealBillingService implementation.
One way that I think I can do utilizing Spring's Java configuration class is something that looks like this
#Configuration
public class BillingConfiguration {
#Bean
public BillingService getRealBillingService() {
return new RealBillingService();
}
}
I was wondering if there was a better way to do this or if this broke down with increasingly complex usage.
I really like Google Guice and how it does Dependency Injection but that's kind of all it does. Spring does a lot more (yes, its dependency injection mechanism is still not 'as-nice' as Guice) but undeniably has some great projects that we would like to utilize like Spring Data, Spring Data REST, etc. which eliminate the need for writing a ton of boilerplate code.
The way to do this is to use #Profile to include different implementations of the same interface.
A simple example would be DataSource. This can however easily be extended to any other interfaces with multiple implementations.
As an example:
#Configuration
public class LocalDataConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
}
}
and then for use in production:
#Configuration
#Profile("production")
public class JndiDataConfig {
#Bean
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
Then all you need to do is declare which profiles are active when you start your application context and #Inject/#Autowire DataSource where you need it.
I've used both Guice and Spring a fair bit. As far as I know, the spring usage you show in the question is the only way to achieve the same as the binding in Guice with Spring. If you need to inject dependencies you can always include those as arguments to the #Bean method and have spring inject them for you.
It's definitely not as clean but it works the same way. One key thing to watch out for is that the default scope in spring is Singleton rather than a new instance every time (spring calls this scope prototype)

intellij incorrectly saying no beans of type found for autowired repository

I have created a simple unit test but IntelliJ is incorrectly highlighting it red. marking it as an error
No beans?
As you can see below it passes the test? So it must be Autowired?
I had this same issue when creating a Spring Boot application using their #SpringBootApplication annotation. This annotation represents #Configuration, #EnableAutoConfiguration and #ComponentScan according to the spring reference.
As expected, the new annotation worked properly and my application ran smoothly but, Intellij kept complaining about unfulfilled #Autowire dependencies. As soon as I changed back to using #Configuration, #EnableAutoConfiguration and #ComponentScan separately, the errors ceased. It seems Intellij 14.0.3 (and most likely, earlier versions too) is not yet configured to recognise the #SpringBootApplication annotation.
For now, if the errors disturb you that much, then revert back to those three separate annotations. Otherwise, ignore Intellij...your dependency resolution is correctly configured, since your test passes.
Always remember...
Man is always greater than machine.
Add Spring annotation #Repository over the repository class.
I know it should work without this annotation. But if you add this, IntelliJ will not show error.
#Repository
public interface YourRepository ...
...
If you use Spring Data with extending Repository class it will be conflict packages. Then you must indicate packages directly.
import org.springframework.data.repository.Repository;
...
#org.springframework.stereotype.Repository
public interface YourRepository extends Repository<YourClass, Long> {
...
}
And next you can autowired your repository without errors.
#Autowired
YourRepository yourRepository;
It probably is not a good solution (I guess you are trying to register repository twice). But work for me and don't show errors.
Maybe in the new version of IntelliJ can be fixed: https://youtrack.jetbrains.com/issue/IDEA-137023
My version of IntelliJ IDEA Ultimate (2016.3.4 Build 163) seems to support this. The trick is that you need to have enabled the Spring Data plugin.
Sometimes you are required to indicate where #ComponentScan should scan for components. You can do so by passing the packages as parameter of this annotation, e.g:
#ComponentScan(basePackages={"path.to.my.components","path.to.my.othercomponents"})
However, as already mentioned, #SpringBootApplication annotation replaces #ComponentScan, hence in such cases you must do the same:
#SpringBootApplication(scanBasePackages={"path.to.my.components","path.to.my.othercomponents"})
At least in my case, Intellij stopped complaining.
I always solve this problem doing de following..
Settings>Inspections>Spring Core>Code than you shift from error to warning the severity option
I am using spring-boot 2.0, and intellij 2018.1.1 ultimate edition and I faced the same issue.
I solved by placing #EnableAutoConfiguration in the main application class
#SpringBootApplication
#EnableAutoConfiguration
class App{
/**/
}
Check if you missed #Service annotation in your service class, that was the case for me.
Configure application context and all will be ok.
Have you checked that you have used #Service annotation on top of your service implementation?
It worked for me.
import org.springframework.stereotype.Service;
#Service
public class UserServiceImpl implements UserServices {}
Putting #Component or #configuration in your bean config file seems to work, ie something like:
#Configuration
public class MyApplicationContext {
#Bean
public DirectoryScanner scanner() {
return new WatchServiceDirectoryScanner("/tmp/myDir");
}
}
#Component
public class MyApplicationContext {
#Bean
public DirectoryScanner scanner() {
return new WatchServiceDirectoryScanner("/tmp/myDir");
}
}
Use #EnableAutoConfiguration annotation with #Component at class level. It will resolve this problem.
For example:
#Component
#EnableAutoConfiguration
public class ItemDataInitializer {
#Autowired
private ItemReactiveRepository itemReactiveRepository;
#Autowired
private MongoOperations mongoOperations;
}
simple you have to do 2 steps
add hibernate-core dependency
change #Autowired to #Resource.
==>> change #Autowired to #Resource
If you don't want to make any change to you code just to make your IDE happy. I have solved it by adding all components to the Spring facet.
Create a group with name "Service, Processors and Routers" or any name you like;
Remove and recreate "Spring Application Context" use the group you created previously as a parent.
As long as your tests are passing you are good, hit alt + enter by taking the cursor over the error and inside the submenu of the first item you will find Disable Inspection select that
For me the solution was to place #EnableAutoConfiguration in the Application class under the #SpringBootApplication its going to underline it because its redundant. Delete it and voila all you warnings regarding missing beans are vanished! Silly Spring...
And one last piece of important information - add the ComponentScan so that the app knows about the things it needs to wire. This is not relevant in the case of this question. However if no #autowiring is being performed at all then this is likely your solution.
#Configuration
#ComponentScan(basePackages = {
"some_package",
})
public class someService {
I am using this annotation to hide this error when it appears in IntelliJ v.14:
#SuppressWarnings("SpringJavaAutowiringInspection")
I had similar issue in Spring Boot application. The application utilizes Feign (HTTP client synthetizing requests from annotated interfaces). Having interface SomeClient annotated with #FeignClient, Feign generates runtime proxy class implementing this interface. When some Spring component tries to autowire bean of type SomeClient, Idea complains no bean of type SomeClient found since no real class actually exists in project and Idea is not taught to understand #FeignClient annotation in any way.
Solution: annotate interface SomeClient with #Component. (In our case, we don't use #FeignClient annotation on SomeClient directly, we rather use metaannotation #OurProjectFeignClient which is annotated #FeignClient and adding #Component annotation to it works as well.)
in my Case, the Directory I was trying to #Autowired was not at the same level,
after setting it up at the same structure level, the error disappeared
hope it can helps some one!
As most synchronisation errors between IntelliJ (IDE) and development environments.
Specially if you have automated tests or build that pass green all the way through.
Invalidate Cache and Restart solved my problem.
What you need to do is add
#ComponentScan("package/include/your/annotation/component") in AppConfiguration.java.
Since I think your AppConfiguraion.java's package is deeper than your annotation component (#Service, #Component...)'s package,
such as "package/include/your/annotation/component/deeper/config".
I had a similar problem in my application.
When I added annotations incorrect highliting dissapeared.
#ContextConfiguration(classes = {...})
IntelliJ IDEA Ultimate
Add your main class to IntelliJ Spring Application Context, for example Application.java
File -> Project Structure..
left side:
Project Setting -> Modules
right side: find in your package structure
Spring and add + Application.java
just add below two annotations to your POJO.
#ComponentScan
#Configuration
public class YourClass {
//TODO
}
#Autowired(required = false)
will shut intellij up
My solution to this issue in my spring boot application was to open the spring application context and adding the class for the missing autowired bean manually!
(access via Project Structure menu or spring tool window... edit "Spring Application Context")
So instead of SpringApplicationContext just containing my ExampleApplication spring configuration it also contains the missing Bean:
SpringApplicationContext:
ExampleApplication.java
MissingBeanClass.java
et voilĂ : The error message disappeared!
This seems to still be a bug in the latest IntelliJ and has to do with a possible caching issue?
If you add the #Repository annotation as mk321 mentioned above, save, then remove the annotation and save again, this fixes the problem.
Sometimes - in my case that is - the reason is a wrong import. I accidentally imported
import org.jvnet.hk2.annotations.Service
instead of
import org.springframework.stereotype.Service
by blindly accepting the first choice in Idea's suggested imports. Took me a few minutes the first time it happend :-)
All you need to do to make this work is the following code:
#ComponentScan
public class PriceWatchTest{
#Autowired
private PriceWatchJpaRepository priceWatchJpaRepository;
...
...
}
I just had to use #EnableAutoConfiguration to address it, however this error had no functional impact.

Categories