JMX MXBean Attributes all UNDEFINED - Spring 3.0.x/Tomcat 6.0 - java

I've been trying to get a sample JMX MXBean working in a Spring-configured webapp, but any basic attributes on the MXBean are coming up as UNDEFINED when I connect with jconsole.
Java interface/classes:
public interface IJmxBean { // marker interface for spring config, see below
}
public interface MgmtMXBean { // lexical convention for MXBeans - mgmt interface
public int getAttribute();
}
public class Mgmt implements IJmxBean, MgmtMXBean { // actual JMX bean
private IServiceBean serviceBean; // service bean injected by Spring
private int attribute = 0;
#Override
public int getAttribute() {
if(serviceBean != null) {
attribute = serviceBean.getRequestedAttribute();
}
return attribute;
}
public void setServiceBean(IServiceBean serviceBean) {
this.serviceBean = serviceBean;
}
}
Spring JMX config:
<beans>
<context:component-scan base-package="...">
<context:include-filter type="assignable" expression="...IJmxBean" />
</context:component-scan>
<context:mbean-export />
</beans>
Here's what I know so far:
The element is correctly instantiating a bean named "mgmt". I've got logging in a zero-argument public constructor that indicates it gets constructed.
is correctly automatically detecting and registering the MgmtMXBean interface with my Tomcat 6.0 container. I can connect to the MBeanServer in Tomcat with jconsole and drill down to the Mgmt MXBean.
When examining the MXBean, "Attribute" is always listed as UNDEFINED, but jconsole can tell the correct type of the attribute. Further, hitting "Refresh" in jconsole does not actually invoke the getter method of "Attribute"- I have logging in the getter method to indicate if it is being invoked (similar to the constructor logging that works) and I see nothing in the logs.
At this point I'm not sure what I'm doing wrong. I've tried a number of things, including constructing an explicit Spring MBeanExporter instance and registering the MXBean by hand, but it either results in the MBean/MXBean not getting registered with Tomcat's MBean server or an Attribute value of UNDEFINED.
For various reasons, I'd prefer not to have to use Spring's #ManagedResource/#ManagedAttribute annotations.
Is there something that I'm missing in the Spring docs or MBean/MXBean specs?

ISSUE RESOLVED: Thanks to prompting by Jon Stevens (above), I went back and re-examined my code and Spring configuration files:
Throwing an exception in the getAttribute() method is a sure way to get "Unavailable" to show up as the attribute's value in JConsole. In my case:
The Spring JMX config file I was using was lacking the default-autowire="" attribute on the root <beans> element;
The code presented above checks to see if serviceBean != null. Apparently I write better code on stackoverflow.com than in my test code, since my test code wasn't checking for that. Nor did I have implements InitializingBean or #PostConstruct to check for serviceBean != null like I normally do on almost all the other beans I use;
The code invoking the service bean was before the logging, so I never saw any log messages about getter methods being entered;
JConsole doesn't report when attribute methods throw exceptions;
The NPE did not show up in the Tomcat logs.
Once I resolved the issue with serviceBean == null, everything worked perfectly. Regardless, +1 to Jon for providing a working demo, since there are literally 50 different ways to configure MBeans/MXBeans within Spring.

I've recently built a sample Spring based webapp that very cleanly enables JMX for latest versions of Spring, Hibernate and Ehcache.
It has examples for both EntityManager based access and DAO access (including transactions!). It also shows how to do annotation based injection in order to negate having to use Spring's xml config for beans. There is even a SpringMVC based example servlet using annotations. Basically, this is a Spring based version of a fairly powerful application server running on top of any servlet engine.
It isn't documented yet, but I'll get to that soon. Take a look at the configuration files and source code and it should be pretty clear.
The motivation behind this is that I got tired of all of the crazy blog posts with 50 different ways to set things up and finally made a single simple source that people can work from. It is up on github so feel free to fork the project and do whatever you want with it.
https://github.com/lookfirst/fallback

Related

Registering Hystrix Concurrency Strategy fails after migrating to spring-boot-2.0

Trying to register hystrix concurrency strategy fails after migrating to Spring-boot-2.0 with spring actuator enabled with java.lang.IllegalStateException stating that "Another strategy was already registered" . This is although I have not used registerConcurrencyStrategy anywhere else in my code.
I'd like to register concurrency strategy to carry-forward Log MDC context so that I'm able to log both within and outside the Hystrix wrapped method equally well, which includes thread-locals. And this used to work perfectly in spring-boot-1.5
After having migrated to spring-boot 2.0 (from 1.5), the HystrixPlugins.getInstance().registerConcurrencyStrategy(this); fails with IllegalStateException
As per https://github.com/Netflix/Hystrix/issues/1057, this issue can come if either (a) Any other code flow would have registered its own or default ConcurrencyStrategy before this is invoked (b) any call would have come via Hystrix before this is invoked
Since the above invocation is within the constructor of a class which is annotated with #Component, this should get invoked ideally before any method call happens (except initialization of other beans, including their constructors).
We even tried moving this code inside the SpringBoot Application Class's main method before invoking the SpringApplication.run(MyApplication.class, args); but that also didn't work
#Component
public class ContextCopyHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
private static final String EVENT = "HystrixConcurrencyStrategy";
private static final String ACTION = "ContextCopy";
public ContextCopyHystrixConcurrencyStrategy(Logger logger, LoggerUtil defaultLoggerUtil) {
try {
HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
} catch (IllegalStateException e) {
defaultLoggerUtil.logEvents(logger, Level.WARN, e.getMessage(), EVENT, ACTION, "", "Race condition! Could not register strategy. HystrixConcurrencyStrategy is already initialized.");
}
Expected: My registering should have happened before any other code and registering should have been successful
Actual: My registering fails with IllegalStateException
How do I make sure that my registering happens well before any other registering (which is not present in my code, but may be inside some of the libraries that I may be transitively using)
By default, Spring boot 2 accuator registers Hystrix Metric Binder beans which reset already set HystrixConcurrencyStrategy and sets HystrixConcurrencyStrategyDefault.
So, disabling that bean by
management.metrics.binders.hystrix.enabled=false
would help not resetting your custom HystrixConcurrencyStrategy
We took a close look at my maven .m2 directory classes and looked for registerConcurrencyStrategy inside all the classes in all the jars. And we found that
io.micrometer.core.instrument.binder.hystrix
was internally registering the HystrixConcurrencyStrategy with the default one.
And upon further research we found that setting the following property in application.properties:
management.metrics.binders.hystrix.enabled=false disabled the Hystrix Metrics Binder (I'm actually not sure what it does though!) and then things worked
I was using spring-boot-starter-parent v2.5.3 with Spring Cloud version 2020.0.3.
I had to manually include version for spring-cloud-starter-netflix-hystrix. I was getting "Another strategy was already registered" exception when starting my microservice. I included the
management.metrics.binders.hystrix.enabled=false
in the application.properties file and this issue got resolved.

Registering DirectChannelMetrics as a JMX Bean programmatically

I have a Spring integration application with several FileTailingMessageProducers and DirectMessageChannels created programmatically -- i.e. not through XML configuration, but within a ApplicationListener<ContextRefreshedEvent>. Now I would like to monitor the message channels using JMX. I guess I will have to add them using my integrationMBeanExporter.
This is what I tried:
DirectChannelMetrics directChannelMetrics = new DirectChannelMetrics(tailedLines, "tailedLines");
integrationMBeanExporter.getServer().registerMBean(directChannelMetrics, new ObjectName("d:foo=foo"));
Yet I am getting the following Exception:
javax.management.NotCompliantMBeanException: MBean class org.springframework.integration.monitor.DirectChannelMetrics does not implement DynamicMBean, and neither follows the Standard MBean conventions
It is surprising to me, that the DirectChannelMetrics does not fulfill JMX requirements, since when I look into my application with jvisualvm I can see other beans of this type registered without problems.
Any ideas?
From one side MBeanExporter does this on the matter:
return new StandardMBean(bean, ((Class<Object>) ifc));
Before registering bean as an MBean.
From other side I think your logic smells a bit. It looks abnormal to create MessageChannels at runtime. Especially those which are for the JMX export.
I can agree about dynamic FileTailingMessageProducers, but seems for me we can avoid dynamic channels with refactored logic for the predefined channels.
You could leverage Spring's MBeanExport.registerManagedResource(directChannelMetrics, new ObjectName("d:foo=foo")). Spring will generate a management interface for the instance of DirectChannelMetric class. But DirectChannelMetric class needs either to implement the Mbean/MXBean interface or to match current MBeanInfoAssembler expectations(be marked with the #ManagedResource annotation in the case of MetadataMBeanInfoAssembler or implements one of specified interfaces in the case of InterfaceBasedMBeanInfoAssembler etc).

EJB2 xdoclet #ejb.ejb-ref in session bean pointing to itself

I'm working now on migration from EJB 2.0 to 3.0.
Old session beans used xdoclets to configure some stuff.
I can understand almost all of them, but there is one thing that is bothering me.
Why do someone use #ejb.ejb-ref in way like in code below.
/**
* #ejb:bean name="SomeBean"
* local-jndi-name="com/my/jndi/SomeBean"
* view-type="local" type="Stateless"
*
* #ejb.ejb-ref ejb-name="SomeBean"
* view-type="local"
*
* ..some more stuff here
*/
public class SomeBean implements SessionBean {
// class body here
}
There is few more #tags in this xdoclet including some for configuring weblogic (#weblogic).
Is there some reason we may want to add reference to bean itself?
Second question, is this config still needed in ejb3?
I have this feeling that I read somewhere that this #weblogic tags may sometimes need to use this kind of reference but I just cannot find it one more time. Is it true?
#EDIT
After talk with one of the authors of such classes, i find out that such self-reference may be used when one of bean methods calls second method (which may have to require new transaction) by using reference to instance of class it's owns.
After upgrade it can be replaced by something like this below.
#Stateless
public class SomeBean implements IBeanLocal {
#EJB
IBeanLocal someBean;
// class body here
}
My confusion was mainly caused by some unnecessary uses of this kind of self-reference.
As pointed by Steve C, probably someone wasn't sure how to use this xdoclet feature.
First of all, the "local" view types imply that you're looking at EJB 2.1 code (not 2.0).
I agree that the #ejb.ejb-ref tag is curious. It would only be useful if it was using JNDI somewhere to look up another instance of the same type of session bean. And even then it's redundant because the ejb home objects are available in the bean's EJBContext object.
It's quite possible the original authors did not know what the ejb-ref was for. There was a lot of that going around at the time.
If there was an ejb-ref to another type of bean, then you would typically see a corresponding #weblogic.ejb-local-reference-description or #weblogic.ejb-reference-description which is used to generate the JNDI mapping information in the weblogic.xml file, linked by the ejb-name.
In any event, you would replace any of these lookup references with instance variables marked up with #EJB.
The complete xdoclet documentation (and source) is still available at (http://xdoclet.sourceforge.net/xdoclet/index.html), FWIW.

Can I replace a Spring bean definition at runtime?

Consider the following scenario. I have a Spring application context with a bean whose properties should be configurable, think DataSource or MailSender. The mutable application configuration is managed by a separate bean, let's call it configuration.
An administrator can now change the configuration values, like email address or database URL, and I would like to re-initialize the configured bean at runtime.
Assume that I can't just simply modify the property of the configurable bean above (e.g. created by FactoryBean or constructor injection) but have to recreate the bean itself.
Any thoughts on how to achieve this? I'd be glad to receive advice on how to organize the whole configuration thing as well. Nothing is fixed. :-)
EDIT
To clarify things a bit: I am not asking how to update the configuration or how to inject static configuration values. I'll try an example:
<beans>
<util:map id="configuration">
<!-- initial configuration -->
</util:map>
<bean id="constructorInjectedBean" class="Foo">
<constructor-arg value="#{configuration['foobar']}" />
</bean>
<bean id="configurationService" class="ConfigurationService">
<property name="configuration" ref="configuration" />
</bean>
</beans>
So there's a bean constructorInjectedBean that uses constructor injection. Imagine the construction of the bean is very expensive so using a prototype scope or a factory proxy is not an option, think DataSource.
What I want to do is that every time the configuration is being updated (via configurationService the bean constructorInjectedBean is being recreated and re-injected into the application context and dependent beans.
We can safely assume that constructorInjectedBean is using an interface so proxy magic is indeed an option.
I hope to have made the question a little bit clearer.
Here is how I have done it in the past: running services which depend on configuration which can be changed on the fly implement a lifecycle interface: IRefreshable:
public interface IRefreshable {
// Refresh the service having it apply its new values.
public void refresh(String filter);
// The service must decide if it wants a cache refresh based on the refresh message filter.
public boolean requiresRefresh(String filter);
}
Controllers (or services) which can modify a piece of configuration broadcast to a JMS topic that the configuration has changed (supplying the name of the configuration object). A message driven bean then invokes the IRefreshable interface contract on all beans which implement IRefreshable.
The nice thing with spring is that you can automatically detect any service in your application context that needs to be refreshed, removing the need to explicitly configure them:
public class MyCacheSynchService implements InitializingBean, ApplicationContextAware {
public void afterPropertiesSet() throws Exception {
Map<String, ?> refreshableServices = m_appCtx.getBeansOfType(IRefreshable.class);
for (Map.Entry<String, ?> entry : refreshableServices.entrySet() ) {
Object beanRef = entry.getValue();
if (beanRef instanceof IRefreshable) {
m_refreshableServices.add((IRefreshable)beanRef);
}
}
}
}
This approach works particularly well in a clustered application where one of many app servers might change the configuration, which all then need to be aware of. If you want to use JMX as the mechanism for triggering the changes, your JMX bean can then broadcast to the JMS topic when any of its attributes are changed.
I can think of a 'holder bean' approach (essentially a decorator), where the holder bean delegates to holdee, and it's the holder bean which is injected as a dependency into other beans. Nobody else has a reference to holdee but the holder. Now, when the holder bean's config is changed, it recreates the holdee with this new config and starts delegating to it.
You should have a look at JMX. Spring also provides support for this.
Spring 2.0.x
Spring 2.5.x
Spring 3.0.x
Further updated answer to cover scripted bean
Another approach supported by spring 2.5.x+ is that of the scripted bean. You can use a variety of languages for your script - BeanShell is probably the most intuitive given that it has the same syntax as Java, but it does require some external dependencies. However, the examples are in Groovy.
Section 24.3.1.2 of the Spring Documentation covers how to configure this, but here are some salient excerpts illustrating the approach which I've edited to make them more applicable to your situation:
<beans>
<!-- This bean is now 'refreshable' due to the presence of the 'refresh-check-delay' attribute -->
<lang:groovy id="messenger"
refresh-check-delay="5000" <!-- switches refreshing on with 5 seconds between checks -->
script-source="classpath:Messenger.groovy">
<lang:property name="message" value="defaultMessage" />
</lang:groovy>
<bean id="service" class="org.example.DefaultService">
<property name="messenger" ref="messenger" />
</bean>
</beans>
With the Groovy script looking like this:
package org.example
class GroovyMessenger implements Messenger {
private String message = "anotherProperty";
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message
}
}
As the system administrator wants to make changes then they (or you) can edit the contents of the script appropriately. The script is not part of the deployed application and can reference a known file location (or one that is configured through a standard PropertyPlaceholderConfigurer during startup).
Although the example uses a Groovy class, you could have the class execute code that reads a simple properties file. In that manner, you never edit the script directly, just touch it to change the timestamp. That action then triggers the reload, which in turn triggers the refresh of properties from the (updated) properties file, which finally updates the values within the Spring context and off you go.
The documentation does point out that this technique doesn't work for constructor-injection, but maybe you can work around that.
Updated answer to cover dynamic property changes
Quoting from this article, which provides full source code, one approach is:
* a factory bean that detects file system changes
* an observer pattern for Properties, so that file system changes can be propagated
* a property placeholder configurer that remembers where which placeholders were used, and updates singleton beans’ properties
* a timer that triggers the regular check for changed files
The observer pattern is implemented by
the interfaces and classes
ReloadableProperties,
ReloadablePropertiesListener,
PropertiesReloadedEvent, and
ReloadablePropertiesBase. None of them
are especially exciting, just normal
listener handling. The class
DelegatingProperties serves to
transparently exchange the current
properties when properties are
updated. We only update the whole
property map at once, so that the
application can avoid inconsistent
intermediate states (more on this
later).
Now the
ReloadablePropertiesFactoryBean can be
written to create a
ReloadableProperties instance (instead
of a Properties instance, as the
PropertiesFactoryBean does). When
prompted to do so, the RPFB checks
file modification times, and if
necessary, updates its
ReloadableProperties. This triggers
the observer pattern machinery.
In our case, the only listener is the
ReloadingPropertyPlaceholderConfigurer.
It behaves just like a standard spring
PropertyPlaceholderConfigurer, except
that it tracks all usages of
placeholders. Now when properties are
reloaded, all usages of each modified
property are found, and the properties
of those singleton beans are assigned
again.
Original answer below covering static property changes:
Sounds like you just want to inject external properties into your Spring context. The PropertyPlaceholderConfigurer is designed for this purpose:
<!-- Property configuration (if required) -->
<bean id="serverProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- Identical properties in later files overwrite earlier ones in this list -->
<value>file:/some/admin/location/application.properties</value>
</list>
</property>
</bean>
you then reference the external properties with Ant syntax placeholders (that can be nested if you want from Spring 2.5.5 onwards)
<bean id="example" class="org.example.DataSource">
<property name="password" value="${password}"/>
</bean>
You then ensure that the application.properties file is only accessible to the admin user and the user running the application.
Example application.properties:
password=Aardvark
Or you could use the approach from this similar question and hence also my solution:
The approach is to have beans that are configured via property files and the solution is to either
refresh the entire applicationContext (automatically using a scheduled task or manually using JMX) when properties have changed or
use a dedicated property provider object to access all properties. This property provider will keep checking the properties files for modification. For beans where prototype-based property lookup is impossible, register a custom event that your property provider will fire when it finds an updated property file. Your beans with complicated lifecycles will need to listen for that event and refresh themselves.
You can create a custom scope called "reconfigurable" into the ApplicationContext. It creates and caches instances of all beans in this scope. On a configuration change it clears the cache and re-creates the beans on first access with the new configuration. For this to work you need to wrap all instances of reconfigurable beans into an AOP scoped proxy, and access the configuration values with Spring-EL: put a map called config into the ApplicationContext and access the configuration like #{ config['key'] }.
This is not something I tried, I am trying to provide pointers.
Assuming your application context is a subclass of AbstractRefreshableApplicationContext(example XmlWebApplicationContext, ClassPathXmlApplicationContext). AbstractRefreshableApplicationContext.getBeanFactory() will give you instance of ConfigurableListableBeanFactory. Check if it is instance of BeanDefinitionRegistry. If so you can call 'registerBeanDefinition' method. This approach will be tightly coupled with Spring implementation,
Check the code of AbstractRefreshableApplicationContext and DefaultListableBeanFactory(this is the implementation you get when you call 'AbstractRefreshableApplicationContext getBeanFactory()')
Option 1 :
Inject the configurable bean into the DataSource or MailSender. Always get the configurable values from the configuration bean from within these beans.
Inside the configurable bean run a thread to read the externally configurable properties (file etc..) periodically. This way the configurable bean will refresh itself after the admin had changed the properties and so the DataSource will get the updated values automatically.
You need not actually implement the "thread" - read : http://commons.apache.org/configuration/userguide/howto_filebased.html#Automatic_Reloading
Option 2 (bad, i think, but maybe not - depends on use case) :
Always create new beans for beans of type DataSource / MailSender - using prototype scope. In the init of the bean, read the properties afresh.
Option 3 :
I think, #mR_fr0g suggestion on using JMX might not be a bad idea. What you could do is :
expose your configuration bean as a MBean (read http://static.springsource.org/spring/docs/2.5.x/reference/jmx.html)
Ask your admin to change the configuration properties on the MBean (or provide an interface in the bean to trigger property updates from their source)
This MBean (a new piece of java code that you will need to write), MUST keep references of Beans (the ones that you want to change / inject the changed properties into). This should be simple (via setter injection or runtime fetch of bean names / classes)
When the property on the MBean is changed (or triggered), it must call the appropriate setters on the respective beans. That way, your legacy code does not change, you can still manage runtime property changes.
HTH!
You may want to have a look at the Spring Inspector a plug-gable component that provides programmatic access to any Spring based application at run-time. You can use Javascript to change configurations or manage the application behaviour at run-time.
Here is the nice idea of writing your own PlaceholderConfigurer that tracks the usage of properties and changes them whenever a configuration change occurs. This has two disadvantages, though:
It does not work with constructor injection of property values.
You can get race conditions if the reconfigured bean receives a
changed configuration while it is processing some stuff.
My solution was to copy the original object. Fist i created an interface
/**
* Allows updating data to some object.
* Its an alternative to {#link Cloneable} when you cannot
* replace the original pointer. Ex.: Beans
* #param <T> Type of Object
*/
public interface Updateable<T>
{
/**
* Import data from another object
* #param originalObject Object with the original data
*/
public void copyObject(T originalObject);
}
For easing the implementation of the function fist create a constructor with all fields, so the IDE could help me a bit. Then you can make a copy constructor that uses the same function Updateable#copyObject(T originalObject). You can also profit of the code of the constructor created by the IDE to create the function to implement:
public class SettingsDTO implements Cloneable, Updateable<SettingsDTO>
{
private static final Logger LOG = LoggerFactory.getLogger(SettingsDTO.class);
#Size(min = 3, max = 30)
private String id;
#Size(min = 3, max = 30)
#NotNull
private String name;
#Size(min = 3, max = 100)
#NotNull
private String description;
#Max(100)
#Min(5)
#NotNull
private Integer pageSize;
#NotNull
private String dateFormat;
public SettingsDTO()
{
}
public SettingsDTO(String id, String name, String description, Integer pageSize, String dateFormat)
{
this.id = id;
this.name = name;
this.description = description;
this.pageSize = pageSize;
this.dateFormat = dateFormat;
}
public SettingsDTO(SettingsDTO original)
{
copyObject(original);
}
#Override
public void copyObject(SettingsDTO originalObject)
{
this.id = originalObject.id;
this.name = originalObject.name;
this.description = originalObject.description;
this.pageSize = originalObject.pageSize;
this.dateFormat = originalObject.dateFormat;
}
}
I used it in a Controller for updating the current settings for the app:
if (bindingResult.hasErrors())
{
model.addAttribute("settingsData", newSettingsData);
model.addAttribute(Templates.MSG_ERROR, "The entered data has errors");
}
else
{
synchronized (settingsData)
{
currentSettingData.copyObject(newSettingsData);
redirectAttributes.addFlashAttribute(Templates.MSG_SUCCESS, "The system configuration has been updated successfully");
return String.format("redirect:/%s", getDao().getPath());
}
}
So the currentSettingsData which has the configuration of the application gonna have the updated values, located in newSettingsData. These method allows updating any bean without high complexity.

Spring AOP does not works in Tomcat and tcserver

I have an aspect which works fine when I run it from a unit test or through a stand alone application. However when I run it as a part of web application and host it on Tomcat the Aspects are not applied.
My aspect looks like
public class MyAspect {
#Around("within(com.service..*)")
public Object doLogging(ProceedingJoinPoint pjp) throws Throwable {
//do something
Object obj = pjp.proceed();
//do something else
return obj;
}
}
I am able to solve this. The reason was that the aspect were getting processed by web application context and not by global application context so I have to restructure couple of things. I have detailed the steps here
#seanizer Spring does support within. It's true that it is only applied to methods and in within it will apply to methods of all the package and sub package of com.service. For details check the reference documentation here
Update: I'll leave this in, because it's still partially valid, even if it didn't help in your case. I'll edit a few places though, edits are marked like this or this.
If you're using Spring AOP, it can't work. Spring AOP only fully supports the execution pointcut. The within pointcut only works when it applies to method executions, for the full functionality of within you will need AspectJ (Spring AOP only uses some AspectJ pointcuts, but not the AspectJ weaver). Either through static compilation (usually through Maven or Ant) or through Load-Time-Weaving.
Also, your class is missing an #Aspect annotation.
How about move
<context:component-scan base-package="com.*" />
<mvc:annotation-driven/>
<aop:aspectj-autoproxy />
to servlet-mvc.xml?

Categories

Resources