Spring CLI command not found? - java

I have a superclass which implements CommandMarker. Some children appears as an usable command, but this one does not.
The log says:
10:29:01.128 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'abortCommand'
....
10:29:01.230 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'abortCommand'
I found no errors while creating the bean, but when I try to use the command I get
Command 'abort' not found (for assistance press TAB)
I tagged the corresponding method with #CliCommand(value = "abort", help = "blah")

Seems that a method tagged with #CliCommand must be public to be visible for spring, tagging the class as #Component is not sufficient.

Related

Why aren't the functions getting called in this basic Spring application?

package com.basicspring.basicapp;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class Config {
#Bean
public Dependency dependency(){
System.out.println("In dependency");
return new Dependency();
}
#Bean
public DependencyContainer dependencyContainer(){
System.out.println("In dependencyContainer");
dependency();
dependency();
dependency();
return new DependencyContainer(dependency());
}
}
Output:
Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify: none and -no verify were deprecated in JDK 13 and will likely be removed in a future release.
22:00:36.567 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext#7276c8cd
22:00:36.601 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
22:00:36.759 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
22:00:36.762 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
22:00:36.765 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
22:00:36.766 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
22:00:36.778 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'config'
22:00:36.798 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'dependency'
In dependency
22:00:36.820 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'dependencyContainer'
In dependencyContainer
22:00:36.833 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'spring.liveBeansView.mbeanDomain' in PropertySource 'systemProperties' with value of type String
Process finished with exit code 0
Please look at the statements "In dependency" and "In dependencyContainer" in the output. Even after manually calling the dependency() method twice in dependencyContainer() method, it's not getting executed twice.
Default scope of a spring bean is singleton. Meaning there is only a single instance of a bean that is used throughout the application. If you use the #Configuration, calls to methods annotated with #Bean get routed to check if there is already an instance of the bean. If an instance is present that instance is returned without executing the function. If you remove the #Configuration annotation all the three calls get executed.

sql scripts not working when JobRegistryBeanPostProcessor bean is used

I have a Spring batch application which uses some sql scripts to initialise the database.
When I extend the application by Spring Batch functionality I need to instantiate the JobRegistryBeanPostProcessor bean in order to use JobRegistry.
I use a similar method as in https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/BatchConfiguration.java
However with such addition I have got a problem - sql scripts are not executed anymore.
In the log output I mentioned such new INFO messages with different bean names (XXX) :
] trationDelegate$BeanPostProcessorChecker : Bean XXX is not eligible
for getting processed by all BeanPostProcessors (for example: not
eligible for auto-proxying)
Is there an approach to resolve the problem aforementioned ?
There is a following solution to the problem:
instead of instantiating the JobRegistryBeanPostProcessor bean, directly register the job in the jobRegistry as proposed in https://stackoverflow.com/a/53381283/6931863
Such solution enables initialisation of Database from data.sql as well as stopping jobs using jobOperator.stop.

Custom springboot autoconfiguration not detecting beans

I developed a custom Spring Boot autoconfiguration to ease working with a proprietary messaging library.
The main autoconfiguration class is essentially as follows:
#Configuration
#ConditionalOnClass({LibServer.class, LibClient.class})
#EnableConfigurationProperties(LibProperties.class)
public class LibAutoConfiguration {
#Autowired
LibProperties props;
#Bean
#ConditionalOnMissingBean(LibServer.class)
public LibServer lbServ() {
// create and configure a server object
}
#Bean
#ConditionalOnMissingBean(LibClient.class)
public LibClient lbClient() {
//create and configure a client object
}
}
It seems however that the conditional annotation is not detecting beans declared in the main #SpringBootApplication annotated class.
It only detects beans declared in separate #Configuration annotated classes.
That is to say if I place two #Bean annotated methods returning a LibServer and a LibClient object in the main class I end up with two LibServer and two LibClient objects (the autoconfigured ones and the explicitly declared ones) in the context.
Native spring boot autoconfigurations (such as DataSource one) can instead detect beans declared in the main class too (such as a #Bean annotated jdbcTemplate method).
How do I get proper bean detection even for beans declared in the main class?
Edit
A complete multimodule maven project exhibiting the behaviour is at https://github.com/AlexFalappa/spring-boot-testcase
If you set the log level on debug in you application.properties (logging.level.org.springframework=DEBUG), you will notice that Spring will detect both definitions. However you will also see that the order in which this happens may not be what you expected, because it instantiate beans from the library configuration first, and AFTERWARDS from your main class , and thus you get 2 instances (stripped timestamps to make it friendlier):
Bean definitions
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'autoConfigurationReport'
a.ConfigurationClassBeanDefinitionReader : Registering bean definition for #Bean method af.spring.boot.libbo.LibAutoConfiguration.lbServ()
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.boot.autoconfigure.condition.BeanTypeRegistry'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'autoConfigurationReport'
a.ConfigurationClassBeanDefinitionReader : Registering bean definition for #Bean method af.spring.boot.libbo.LibAutoConfiguration.lbClient()
a.ConfigurationClassBeanDefinitionReader : Registering bean definition for #Bean method af.DemoLibboApplication.libServ()
a.ConfigurationClassBeanDefinitionReader : Registering bean definition for #Bean method af.DemoLibboApplication.libClient()
Bean instantiation
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'lbServ'
o.s.b.f.s.DefaultListableBeanFactory : Creating instance of bean 'lbServ'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'libAutoConfiguration'
Autoconfiguring LibServer
o.s.b.f.s.DefaultListableBeanFactory : Eagerly caching bean 'lbServ' to allow for resolving potential circular references
o.s.b.f.s.DefaultListableBeanFactory : Finished creating instance of bean 'lbServ'
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'lbClient'
o.s.b.f.s.DefaultListableBeanFactory : Creating instance of bean 'lbClient'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'libAutoConfiguration'
Autoconfiguring LibClient
o.s.b.f.s.DefaultListableBeanFactory : Eagerly caching bean 'lbClient' to allow for resolving potential circular references
o.s.b.f.s.DefaultListableBeanFactory : Finished creating instance of bean 'lbClient'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'lib.CONFIGURATION_PROPERTIES'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.store'
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'libServ'
o.s.b.f.s.DefaultListableBeanFactory : Creating instance of bean 'libServ'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'demoLibboApplication'
o.s.b.f.s.DefaultListableBeanFactory : Eagerly caching bean 'libServ' to allow for resolving potential circular references
o.s.b.f.s.DefaultListableBeanFactory : Finished creating instance of bean 'libServ'
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'libClient'
o.s.b.f.s.DefaultListableBeanFactory : Creating instance of bean 'libClient'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'demoLibboApplication'
o.s.b.f.s.DefaultListableBeanFactory : Eagerly caching bean 'libClient' to allow for resolving potential circular references
o.s.b.f.s.DefaultListableBeanFactory : Finished creating instance of bean 'libClient'
You can also see in the AUTO-CONFIGURATION REPORT that in your current implementation when the conditionals in the LibAutoConfiguration are evaluated, they match and normally it creates the beans:
Positive matches:
-----------------
...
LibAutoConfiguration#lbClient matched
- #ConditionalOnMissingBean (types: af.libbo.LibClient; SearchStrategy: all) found no beans (OnBeanCondition)
LibAutoConfiguration#lbServ matched
- #ConditionalOnMissingBean (types: af.libbo.LibServer; SearchStrategy: all) found no beans (OnBeanCondition)
...
However, if you add the same condition to your main class, you'll see that it will create the beans according to the definitions in LibAutoConfiguration, and when trying to create those for DemoLibboApplication, it will actually find the previously created beans and skip the instantiation:
Negative matches:
-----------------
...
DemoLibboApplication#libClient did not match
- #ConditionalOnMissingBean (types: af.libbo.LibServer; SearchStrategy: all) found the following [lbServ] (OnBeanCondition)
DemoLibboApplication#libServ did not match
- #ConditionalOnMissingBean (types: af.libbo.LibServer; SearchStrategy: all) found the following [lbServ] (OnBeanCondition)
...
You're not importing your LibAutoConfiguration yourself, do you?
This was the hint: your main class is in a parent package from your auto-configuration class. So you're actually importing the #Configuration yourself through component scan. It turns out that when you process that class (via an explicit import rather than via auto-configuration), no beans have been created yet so it does create them. Your application class is processed later and create those beans as well.
If you move the definition somewhere else, it might work (as you have figured out yourself with LibConfig) but that's not deterministic.
TL;DR make sure that your auto-configuration code is in a separate space and is not the target of component scan. I have moved your DemoLibboApplication to the demo package and it worked as expected.

How to find out how a specific bean is wired in Spring

I have a spring application (A) which uses a transient dependency (B) which in itself is based on Spring as well.
So to summarize, war A & jar B are both spring projects. B is a dependency of A.
One of the attributes of a class in B is decorated in the following way
#Resource(name="thisIsTheTargetRef")
private String hardToFindMe;
I went through the application context files of A & B but I do not find a declaration of a bean with the id 'thisIsTheTargetRef'. But somehow the logs show that the .hardToFindMe. attr gets wired with 'thisIsTheTargetRef' bean. I search through both the A & B projects including all other dependencies to see if this is getting picked up from somewhere else. No dice. I even inspected the Component-scan packages but with no luck. I also did a hard text search for 'thisIsTheTargetRef' in both A & B including the dependency projects. I still don't find it.
Here is a log snippet showing that the bean is still getting wired.
[#|2014-01-27T18:23:16.654+0000|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=10;_ThreadName=Thread-3;|77875 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory {} null - Returning cached instance of singleton bean 'thisIsTheTargetRef'
|#]
[#|2014-01-27T18:23:46.640+0000|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=10;_ThreadName=Thread-3;|18:23:46,639 INFO [XmlWebApplicationContext:1332] Bean 'thisIsTheTargetRef' of type [class org.springframework.jndi.JndiObjectFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|#]
It does appears that I'm missing something here. There might have been a dependency that I have missed looking into and my eyes are just fooling me. But any other obvious places that I should look at?
If not, based on the logs, XmlWebApplicationContext:1332 is referred as the location for the bean. How can I debug to find out where it is getting picked from? Thanks.
You might be lucky by defining a watch/breakpoint on the field you know where it is injected. During the debugging you should get a stop during the autowiring process and you will see which class is wired. This should help identifing it and then check occurences for this class.
I'm not sure if you can directly find out from where this bean is loaded. One hint should be either the annotationprocessor or xmlprocessor.

Why is Spring Container Destroying Beans Immediately After Creating Them?

Immediately after creating all the beans declared in the various context files of my application, Spring notifies (see below) that it is destroying singletons and that context initialization failed.
[INFO] Destroying singletons in
org.springframework.beans.factory.support.DefaultListableBeanFactory
org.springframework.web.context.ContextLoader [ERROR] Context
initialization failed
Does anyone know why the Spring container is destroying all the beans right after creating them?
NOTE: There are no warnings or errors in the log output aside from the above context initialization failure error -- see below.
[DEBUG] Eagerly caching bean 'uploadService' to allow for resolving potential circular references
2011-09-21 15:19:08 org.springframework.beans.factory.annotation.InjectionMetadata
[DEBUG] Processing injected method of bean 'uploadService': AutowiredFieldElement for private
org.apache.commons.fileupload.disk.DiskFileItemFactory com.faciler.ws.services.UploadService.diskFileFactory 2011-09-21 15:19:08
org.springframework.beans.factory.support.DefaultListableBeanFactory
[DEBUG] Creating shared instance of singleton bean
'diskFileItemFactory' 2011-09-21 15:19:08
org.springframework.beans.factory.support.DefaultListableBeanFactory
[DEBUG] Creating instance of bean 'diskFileItemFactory' 2011-09-21
15:19:08
org.springframework.beans.factory.support.DefaultListableBeanFactory
[INFO] Destroying singletons in
org.springframework.beans.factory.support.DefaultListableBeanFactory#b0ede6:
defining beans [org.springframework.beans.
The context initialization failure is causing spring to destroy the beans already successfully created - not the other way round. You will probably need to up the log level to INFO or DEBUG to get to the root cause.
When faced with a situation where you don't know what's causing the issue, remove complexity. In your case, remove most of your beans from the configuration, whether XML or annotation-based. Start adding them back in and see which one breaks the startup cycle. Then you can focus in on why that one bean is causing the failure.
Short answer:
Try increasing JVM memory
here: -XX:PermSize=64m -XX:MaxPermSize=128m -Xms256m -Xmx768m
Detailed answer:
Often Spring desperately destroys beans (hence the communicate) as a way of gaining some memory.
Additionally high Garbage Collector activity slows down spring initialization.
Above I provide settings working for me. Depending on your application complexity you may want to play around with these values.
Disclaimer: It's not always the case. But frequently my spring apps beak down as a result of running them with default JVM memory settings.
Debuging is the best way to find the root cause. If you are using Eclipse for development, run in the debug mode. wait for the control goes to the catch block and in the variables editor you can find the exception object, which should have the stack trace. This way you can find the root cause of the issue.
I have recently faced similar issue. One possible solution to the problem would be to check your main class or wherever you initialize the spring context. Sometimes it happens that exceptions thrown by spring context are caught and never printed or re-thrown. Consider the example below:
AbstractApplicationContext context = null;
try {
context = new ClassPathXmlApplicationContext("beans.xml");
// context.registerShutdownHook();
} catch (Exception e) {
e.printStackTrace();
//print or log error
} finally {
if (context != null) {
context.close();
}
}

Categories