I use spring shell (not spring boot) in my app and want to disable debug logs.
After I run commands console print some debug logs. For example:
"DEBUG - DefaultListableBeanFactory - Returning cached instance of singleton bean 'myPromptProvider'"
"DEBUG - DefaultListableBeanFactory - Returning cached instance of singleton
bean 'defaultPromptProvider'"
Note that i run my app in windows cmd with java - jar *.jar
Here is my code:
#Component
public class Test implements CommandMarker {
//------------------------------------------------------ create
#CliCommand(value = {"test"})
public void test(
#CliOption(key = {"str"}, mandatory = true) final String str
) {
System.out.println(str);
}
}
and here is output:
spring-shell>test --str aaa
aaa
DEBUG - DefaultListableBeanFactory - Returning cached instance of singleton bean 'defaultPromptProvider'
DEBUG - DefaultListableBeanFactory - Returning cached instance of singleton bean 'myPromptProvider'
I want to eliminate those debug lines.
Related
I have a JAX-RS webservice with a resource for generating testdata. During tests I found out, that the injected EJB is not reinitialized and still contains data from the last request.
I have a jar file server.jar containing my business logic with EJBs. To show my problem I have created a stateless bean:
#Stateless
public class TestService
{
#EJB
SubsequentTestService state2Service;
private String value;
public void testIt()
{
System.out.println("####### VALUE: " + value);
value = "TestValue";
state2Service.testIt();
}
}
I am using the subsequent call to SubsequentTestService to show the odd behaviour also exists for call of another stateless EJB:
#Stateless
public class SubsequentTestService
{
private String value;
public void testIt()
{
System.out.println("####### VALUE2: " + value);
value = "TestValue2";
}
}
Changing the annotation form #EJB to #Inject does not change anything.
In my web.war I have simple JAX-RS beans. The one which is called to show the strange behaviour is defined as follows:
#Path("/test")
public class TestResource
{
#Inject
TestService testService;
#GET
#Path("/state")
public void testState()
{
testService.testIt();
}
}
The JAX-RS application configuration looks as follows:
#ApplicationPath("/api")
public class JaxRsConfiguration extends Application
{
}
The war file contains the beans.xml, but no other configuration file. Everything is packaged into an ear file and is deployed in wildfly 10.0.0.Final. If I call the webservice as GET request via http://localhost:8080/api/test/state I get the expected output:
INFO [stdout] (default task-7) ####### VALUE: null
INFO [stdout] (default task-7) ####### VALUE2: null
But on the second request I get following unexpected output:
INFO [stdout] (default task-8) ####### VALUE: TestValue
INFO [stdout] (default task-8) ####### VALUE2: TestValue2
What is my problem here? Might be anything misconfigured in the wildfly? But I have only changed the logging and the datasource definition.
You have the meaning of #Stateless backwards.
This does not mean like so:
Hey container, here's an arbitrary class, please make it a stateless bean.
This actually means like so:
Hey container, here's a stateless class, you can safely use it as a stateless bean.
You have a stateful class. You should mark it as a #Stateful bean. Otherwise, get rid of all the state (unmanaged instance variables) so you can safely use it as a #Stateless bean.
See also:
Why Stateless session beans?
JSF request scoped bean keeps recreating new Stateful session beans on every request?
When using #EJB, does each managed bean get its own #EJB instance?
Is there anyway I can know in my program, the full path of file loaded through #PropertySource annotation of Spring.
I need it to show in logs so that one can know which property file is being used in the application
This information is logged already by StandardServletEnvironment. You can set log level to DEBUG for org.springframework.web.context.support.StandardServletEnvironment class to show details in your logs.
If you use spring-boot you can simply add following line into your application.properties file.
logging.level.org.springframework.web.context.support.StandardServletEnvironment = DEBUG
Below seems to be working, though I am not sure if the instance is always of type ConfigurableEnvironment
#Component
public class MyListener implements ApplicationListener<ContextRefreshedEvent>{
#Autowired
private Environment env;
private static final Logger log = LoggerFactory.getLogger(MyListener.class);
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if(env instanceof ConfigurableEnvironment){
MutablePropertySources propertySources = ((ConfigurableEnvironment)env).getPropertySources();
for(PropertySource ps : propertySources){
log.info(ps.getName()); //if only file based needed then check if instanceof ResourcePropertySource
}
}
}
}
Edit: don't really need all this. As already answered by Selim, enabling the proper logs does the trick
log4j.logger.org.springframework.core.env.MutablePropertySources=DEBUG
in current ('21) versions of Spring Boot, neither of the two above suggestions for the logging level seem to work. moreover - if the file is actually NOT loaded, because it is NOT found or for whatever other reason, nothing is printed anyway.
at the moment when i have my ROOT logger set to DEBUG (logging.level.root=DEBUG in application.properties), the only thing I see in the log file, when the file is loaded correctly and the #Value annotated property is resolved successfully is:
2021-07-23 11:06:10.299 DEBUG 16776 --- [ restartedMain]
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of
singleton bean 'bahblahService'
2021-07-23 11:06:10.302 DEBUG 16776 --- [ restartedMain]
o.s.c.e.PropertySourcesPropertyResolver : Found key
'blahblah.username' in PropertySource 'class path
resource [custom-local.properties]' with value of type String
A little background:
I am using Spring and Camel together with Java 8.
public static void main(String[] args) throws Exception {
AbstractApplicationContext _context = new ClassPathXmlApplicationContext(
"application-context.xml");
_context.registerShutdownHook();
MessageRoute _messageRoute = (MessageRoute) _context.getBean("messageRoute");
SpringCamelContext _camelContext = _context.getBean(SpringCamelContext.class);
_messageRoute.setContext(_camelContext);
_camelContext.addRoutes(_messageRoute);
Object lock = new Object();
synchronized (lock) {
lock.wait();
}
((ClassPathXmlApplicationContext) _context).close();
}
[main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemProperties]
[main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemEnvironment]
[main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source. Returning [null]
[main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'messageRoute'
[main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.apache.camel.spring.SpringCamelContext#0'
[main] DEBUG o.a.camel.spring.SpringCamelContext - Adding routes from builder: Routes: []
[main] DEBUG o.a.camel.spring.SpringCamelContext - Adding routes from builder: Routes: []
I have tried using DefaultCamelContext as well but the problem is it's just not adding the route class. The MessageRoute class is a simple class extending the RouteBuilder. My observation tells me the line containing: _context.getBean("messageRoute") might have an issue because it's not really passing any route to the RouteBuilder reference.
Never mind I fixed it! Camel wasn't adding an instance of the Route class sitting inside the spring container because in the configure method, one needs an actual path saying from().to().
Pretty funny though that it wasn't throwing any error and even refused the add the ApplicationContext bean to routes.
To add Java routes in XML, just use <routeBuilder ref="myBeanName"/> inside <camelContext>
See the Camel documentation: http://camel.apache.org/spring.html at the section Using Java Code
Is it possible to have beans of imported java based configurations be created with prototype scope?
What I mean is that if I have the following example code:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(
SpringTopLevelConfig.class);
for (int i = 0; i < 2; i++) {
System.out.println(applicationContext.getBean(Student.class));
}
Where
public class Notebook {
static int idCounter = 1;
private final int id;
#Override
public String toString() {
return "Notebook{" +
"id=" + id +
'}';
}
public Notebook() {
id = idCounter++;
}
}
public class Student {
private final Notebook notebook;
#Override
public String toString() {
return "Student{" +
"notebook=" + notebook +
'}';
}
public Student(Notebook notebook) {
this.notebook = notebook;
}
}
And spring Config is :
#Configuration
public class SpringTopLevelConfig {
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Bean
Notebook notebook(){
return new Notebook();
}
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Bean
Student student(){
return new Student(notebook());
}
}
As expected each student gets its own notebook:
Student{notebook=Notebook{id=1}}
Student{notebook=Notebook{id=2}}
However if I try to split up the configuration across multiple classes all of the examples I have found suggest using #Autowire to accomplish this:
#Configuration
#Import(SpringConfigSecondLevel.class)
public class SpringTopLevelConfig {
#Autowired
Notebook notebook;
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Bean
Student student(){
return new Student(notebook);
}
}
#Configuration
public class SpringConfigSecondLevel {
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Bean
Notebook notebook(){
return new Notebook();
}
}
However now the students end up sharing one notebook which is not the behaviour I am trying to achieve.
Student{notebook=Notebook{id=1}}
Student{notebook=Notebook{id=1}}
Is there a spring way to achieve SCOPE_PROTOTYPE behaviour with split configuration classes or will I need to create a NotebookFactory bean to save the students from fighting each other over the same notebook?
The two config file approach did not have the expected result, because you autowire the notebook inside SpringTopLevelConfig class. That notebook instance will be created once, and used from all other student objects, since when you create the student, inside the student constructor you pass that notebook instance instead of the notebook() bean method. You can pass the notebook() bean method inside the student constructor by autowiring the whole config class, so that you can call it:
#Configuration
#Import(SpringConfigSecondLevel.class)
public class SpringTopLevelConfig {
#Autowired SpringConfigSecondLevel springConfigSecondLevel;
#Scope("prototype")
#Bean
Student student(){
return new Student(springConfigSecondLevel.notebook());
}
}
#Configuration
public class SpringConfigSecondLevel {
#Scope("prototype")
#Bean
Notebook notebook(){
return new Notebook();
}
}
Since the Notebook instance is #Autowired it will be created once while creating the springTopLevelConfig singleton bean. This is evident from spring debug level logs
14:59:15.631 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'springTopLevelConfig'
14:59:15.631 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'springTopLevelConfig'
14:59:15.639 [main] DEBUG o.s.b.f.annotation.InjectionMetadata - Registered injected element on class [com.example.spring.prototype_level.SpringTopLevelConfig$$EnhancerBySpringCGLIB$$2fffb2e0]: AutowiredFieldElement for com.example.spring.prototype_level.Notebook com.example.spring.prototype_level.SpringTopLevelConfig.notebook
14:59:15.640 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'springTopLevelConfig' to allow for resolving potential circular references
14:59:15.673 [main] DEBUG o.s.b.f.annotation.InjectionMetadata - Processing injected method of bean 'springTopLevelConfig': AutowiredFieldElement for com.example.spring.prototype_level.Notebook com.example.spring.prototype_level.SpringTopLevelConfig.notebook
14:59:15.682 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'notebook'
14:59:15.682 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:59:15.682 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:59:15.684 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'com.example.spring.prototype_level.SpringConfigSecondLevel' to allow for resolving potential circular references
14:59:15.698 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:59:15.731 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'notebook'
14:59:15.732 [main] DEBUG o.s.b.f.a.AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'springTopLevelConfig' to bean named 'notebook'
14:59:15.733 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'springTopLevelConfig'
14:59:15.733 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor'
14:59:15.733 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor'
14:59:15.733 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:59:15.736 [main] DEBUG o.s.c.a.AnnotationConfigApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor#391663bd]
14:59:15.736 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
14:59:15.739 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemProperties]
14:59:15.739 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemEnvironment]
14:59:15.740 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source. Returning [null]
14:59:15.740 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'student'
14:59:15.740 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'springTopLevelConfig'
14:59:15.752 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'student'
Student{notebook=Notebook{id=1}}
14:59:15.753 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'student'
14:59:15.753 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'springTopLevelConfig'
14:59:15.753 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'student'
Student{notebook=Notebook{id=1}}
An alternative would be to inject the Notebook instance using applicationContext as below
#Configuration
#Import(SpringConfigSecondLevel.class)
public class SpringTopLevelConfig{
#Autowired
private ApplicationContext applicationContext;
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Bean
Student student(){
return new Student(applicationContext.getBean(Notebook.class));
}
}
Now spring will create the Notebook instance every time you create a Student instance. The spring logs too say so
14:55:51.255 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'springTopLevelConfig'
14:55:51.255 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'springTopLevelConfig'
14:55:51.258 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'springTopLevelConfig' to allow for resolving potential circular references
14:55:51.284 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'springTopLevelConfig'
14:55:51.285 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor'
14:55:51.285 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor'
14:55:51.285 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:55:51.285 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:55:51.287 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'com.example.spring.prototype_level.SpringConfigSecondLevel' to allow for resolving potential circular references
14:55:51.292 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:55:51.295 [main] DEBUG o.s.c.a.AnnotationConfigApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor#1396a464]
14:55:51.297 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
14:55:51.300 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemProperties]
14:55:51.301 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemEnvironment]
14:55:51.302 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source. Returning [null]
14:55:51.302 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'student'
14:55:51.305 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'springTopLevelConfig'
14:55:51.342 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'notebook'
14:55:51.342 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:55:51.352 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'notebook'
14:55:51.354 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'student'
Student{notebook=Notebook{id=1}}
14:55:51.355 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'student'
14:55:51.355 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'springTopLevelConfig'
14:55:51.355 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'notebook'
14:55:51.355 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:55:51.355 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'notebook'
14:55:51.355 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'student'
Student{notebook=Notebook{id=2}}
Others have explained why your first attempt did not work. I would only suggest a solution that does not require using an #Autowired field.
#Configuration
#Import(SpringConfigSecondLevel.class)
public class SpringTopLevelConfig {
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Bean
public Student student(Notebook notebook) {
return new Student(notebook);
}
}
If you simply add a method parameter of type Notebook, the Spring container will supply you with a new instance automatically.
I have 2 webapps deployed on Apache TomEE+. In the first webapp I have created a singleton EJB class declared like this:
#Singleton
#Remote
#Startup
#Lock(READ)
public class SolverRegistryBean implements SolverRegistry
{
// ...
From openejb.log I can see, that the singleton is available:
2011-12-05 20:43:22,696 - INFO - Jndi(name=SolverRegistryBeanRemote) --> Ejb(deployment-id=SolverRegistryBean)
2011-12-05 20:43:22,696 - INFO - Jndi(name=global/localhost/SolverCore-1.0/SolverRegistryBean!grid.solver.SolverRegistry) --> Ejb(deployment-id=SolverRegistryBean)
2011-12-05 20:43:22,696 - INFO - Jndi(name=global/localhost/SolverCore-1.0/SolverRegistryBean) --> Ejb(deployment-id=SolverRegistryBean)
2011-12-05 20:43:22,750 - INFO - Started Ejb(deployment-id=SolverRegistryBean, ejb-name=SolverRegistryBean, container=My Singleton Container)
From my other app I want to access that singleton bean, so I do:
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.openejb.client.RemoteInitialContextFactory");
p.put("java.naming.provider.url", "http://127.0.0.1:8080/openejb/ejb");
try {
ctx = new InitialContext(p);
SolverRegistry reg = (SolverRegistry)ctx.lookup(
"openejb:global/global/localhost/SolverCore-1.0/SolverRegistryBean");
but then I get ClassCastException
java.lang.ClassCastException: $Proxy94 cannot be cast to grid.solver.SolverRegistry
I checked that this $Proxy94 class implements interfaces: grid.solver.SolverRegistry, org.apache.openejb.core.ivm.IntraVmProxy and org.apache.openejb.BeanContext$Removable.
Why this doesn't work?
I have resolved my problem by changing the lookup line to:
SolverRegistry reg = (SolverRegistry)ctx.lookup("SolverRegistryBeanRemote");
Still don't know what is openejb:global/global/localhost/SolverCore-1.0/SolverRegistryBean for.