Facing issue while adding Springdoc-openapi in Spring Framework based project (Not Spring Boot) - spring

We have Spring framework (version 5.3.22) based application, not a spring boot.
We have added springdoc-openapi (1.6.11) dependency along with below openapi configuration.
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"org.springdoc"})
#Import({org.springdoc.core.SpringDocConfiguration.class,
org.springdoc.webmvc.core.SpringDocWebMvcConfiguration.class,
org.springdoc.webmvc.ui.SwaggerConfig.class,
org.springdoc.core.SwaggerUiConfigProperties.class,
org.springdoc.core.SwaggerUiOAuthProperties.class,
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.class})
public class OpenApiConfig implements WebMvcConfigurer { }
In our application, we have multiple projects having mixed of Java configurations and XML based configurations.
Both types of classes (java config like #controller/#service and XML definitions like <bean id="".... >) are having dependencies injected through #Autowired.
The classes having beans created through component scanning (#controller/#service) are working well, all the injected dependecies are resolved as expected.
But the classes having XML definitions are having issues, where dependencies injected through setter and bean ref are working fine, but the dependencies injected through #Autowired are found as null at runtime. Looks like #Autowired annotation itself is not getting resolved while creating bean of such classes. We have also verified that our XML context file has <context:annotation-config /> defined and so #Autowired should get resolved here.
Without this springdoc-openpi dependency and these OpenApiConfig, we are not facing this issue.
Does anyone have more insights here ?

Related

Spring boot Jpa is not working with Spring batch and spring integration

I am working with spring batch. I needed to add some jpa repositories. So previously i was using JDBCTemplate which was working fine.
But when I started working with JPA, the spring boot application could not find the repos. Which were there.
#Autowired
ClassLevelConfigRepo clcr;
I checked these things as the best practices.
Added #EnableJpaRepositories in springBoot application class.
Added #Repostiories to the repository interfaces.
extended the interfaces with JpaRepository<Account, String>
Added #Entity to the entity classes and defined the #Table and # Column annotations properly.
But I am still getting below error.
Field clcr in com.cloudtask.batchconfig.util.LhmUtility required a bean of type 'com.cloudtask.batchconfig.repo.ClassLevelConfigRepo' that could not be found.
I tried checking all the dependencies in pom.xml it was as per recommended. And I have all the tables defined properly in data base.
I was expecting the application to return the Autowired clcr object propely.
Edit 1 : spring boot application annotations
#SpringBootApplication
#ComponentScan({"com.cloudtask"})
#EnableAsync
#IntegrationComponentScan({"com.cloudtask"})
#EnableIntegrationManagement(defaultLoggingEnabled = "true")
#EnableJpaRepositories
#EntityScan
public class imclassApplication ```
When you work with Spring Data Jpa with those basic points you should also keep track of below points.
you have added spring-boot-starter-data-jpa in your pom.xml
you have added the entity and repo package below one level of the application package.
If you the package is at same level you should specify the exact package details in the annotation. in your case it should be like :
#EnableJpaRepositories("com.cloudtask.batchconfig.repo")
#EntityScan(basePackages = {"com.cloudtask.batchconfig.entity"})
Happy programming!

Spring framework #Configurable vs #Configuration

I seems have problem understanding these 2 annotation. I have try to read the javadocs but still cannot figure out. Can anyone help to explain with simple code about these 2 ?
Thank so much in advance.
You use #Configuration as a replacement to the XML based configuration for configuring spring beans. So instead of an xml file we write a class and annotate that with #Configuration and define the beans in it using #Bean annotation on the methods.
And finally you use AnnotationConfigApplicationContext to register this #Configuration class and thus spring manages the beans defined. Small example you can find at Spring Configuration Documentaion.
Quoting from the above link
It is just another way of configuration Indicates that a class declares
one or more #Bean methods and may be processed by the Spring container
to generate bean definitions and service requests for those beans at
runtime.
And #Configurable is an annotation that injects dependencies into objects that are not managed by Spring using aspectj libraries. i.e., you still use old way of instantiation with plain new operator to create objects but the spring will take care of injecting the dependencies into that object automatically for you.
#Configuration is the heart of the Java-based configuration mechanism and provides an alternative to XML-based configuration.
#Configuration classes are just like regular #Components classes, except that methods annotated with #Bean are used to factory beans.

Purpose of using #Configuration annotation

I have created a spring mvc based application but I didn't use this #Configuration annotation. What is the purpose of using #Configuration annotation? By using this, what are we communicating to springMVC container?
Assuming your application is using xml configuration rather than AnnotationConfig so it is not loaded to ApplicationContext at all.
#Configuration is used when ApplicationContext has been initialized and bean registration.
#Configuration annotation is a core Spring annotation, and not Spring MVC. It is a core entry point to configuring Spring-based application using Java config instead of XML config.
Please, use Spring Documentation more often because it is a place where you will find answers to most of your questions. Like this one:
Indicates that a class declares one or more Bean #Bean methods and may
be processed by the Spring container to generate bean definitions and
service requests for those beans at runtime

Spring Boot Scanning Classes from jars issue

In my sample spring boot application, i have added a dependency of a custom jar. My sample application has a support for web and jpa.
The jar which i've created contains a Spring MVC controller. Below is the sample code
#Controller
public class StartStopDefaultMessageListenerContainerController {
#Autowired(required=false)
private Map<String, DefaultMessageListenerContainer> messageListeners;
I haven't manually created a bean instance of this controller anywhere in my code.
Problem - When i start my spring boot application by running the main class, i get an error in console that prob while autowiring DefaultMessageListenerContainer.
My question here is, even though this class StartStopDefaultMessageListenerContainerController is just present in the classpath, it's bean shouldn't be created and autowiring should not happen. But spring boot is scanning the class automatically and then it tries to autowire the fields.
Is this the normal behavior of spring and is there anyway i can avoid this?
If the StartStopDefaultMessageListenerContainerController class is part of component scanning by spring container, Yes spring tries to instantiate and resolve all dependencies.
Here your problem is #Autowired on collection. Spring docs says,
Beans that are themselves defined as a collection or map type cannot be injected through #Autowired, because type matching is not properly applicable to them. Use #Resource for such beans, referring to the specific collection or map bean by unique name.
And also Refer inject-empty-map-via-spring

Spring - #Configurable classes in external JAR

I want to use spring dependency injection for my domain classes, that are possibly not created within spring context. That's why I have annotated these classes with #Configurable annotation and I try to setup load time weaving. My spring configuration is :
#SpringBootApplication
#EnableSpringConfigured
#EnableAspectJAutoProxy
#EnableCaching(mode = AdviceMode.ASPECTJ)
#EnableLoadTimeWeaving
public class WebApplication extends WebMvcConfigurerAdapter
This works fine but only if my #Configurable classes are in same JAR as my main Spring Boot application. However I want to have my #Configurable domain classes in JAR that is added as dependency for main application.
I tried this but it looks like load time weaving is not working for external JARs. Do you have any suggestions how to solve this issue?
EDIT
I have added -verbose:class to my JVM options and I have found out that classes from external JARs are loaded by class loader before LoadTimeWeaving is configured and initialized. And classes not in external JAR are loaded as they are needed i.e. after LoadTimeWeaving init.
So basically my question is :
Is it possible to initialize LTW before external JARs loading? Or is it possible to reload (or make AspectJ enhancement) classes after LTW is configured?
EDIT 2
I found out the reason why my classes from external jar are loadded before LTW init. It's because these classes are also annotated with #Entity annotation. Therefore they are loaded during hibernate initialization which occure before LTW init.
So the final question is: :D
How to assume that LTW is initialized before hibernate (and possibly other) initializations?
Ok I have a solution. :) As I sad issue was the order of spring bean initialization. So I simple had to ensure that load time weaver was initialized before hibernate. Simply injecting LoadTimeWeaver into my configuration class was the workaround:
#Autowired
private LoadTimeWeaver loadTimeWeaver;
EDIT
Another solution is to add aspectjweaver.jar as javaagent in addition to spring-instrument.

Resources