I am trying to make a class implement an MBean Interface so I can interrogate the properties at runtime. The class I am trying to interrogate is as follows
public class ProfileCache implements ProfileCacheInterfaceMBean{
private Logger logger = Logger.getLogger(ProfileCache.class);
private ConcurrentMap<String, Profile> cache;
public ProfileCache(ConcurrentMap<String, Profile> cache){
this.cache = cache;
}
/**
* Update the cache entry for a given user id
* #param userid the user id to update for
* #param profile the new profile to store
* #return true if the cache update
*/
public boolean updateCache(String userid, Profile profile) {
if (cache == null || cache.size() == 0) {
throw new RuntimeException("Unable to update the cache");
}
if (cache.containsKey(userid)) {
if (profile != null) {
cache.put(userid, profile);
logger.info("Updated the cache for user: "
+ userid + " profile: " + profile);
return true;
}
}
return false;
}
#Override
public ConcurrentMap<String, Profile> getCache() {
if(cache == null){
cache = new ConcurrentHashMap<String, Profile>();
}
return cache;
}
}
The interface looks like this
import com.vimba.profile.Profile;
public interface ProfileCacheInterfaceMBean {
ConcurrentMap<String, Profile> getCache();
}
And i start the MBean like this
cacheImpl = new ProfileCache(factory.createCacheFromDB());
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName profileCache = new ObjectName("org.javalobby.tnt.jmx:type=ProfileCacheInterfaceMBean");
mbs.registerMBean(cacheImpl, profileCache);
However i keep getting the below exception and I am not sure what I need to change
javax.management.NotCompliantMBeanException: MBean class com.vimba.cache.ProfileCache does not implement DynamicMBean, and neither follows the Standard MBean conventions (javax.management.NotCompliantMBeanException: Class com.vimba.cache.ProfileCache is not a JMX compliant Standard MBean) nor the MXBean conventions (javax.management.NotCompliantMBeanException: com.vimba.cache.ProfileCache: Class com.vimba.cache.ProfileCache is not a JMX compliant MXBean)
I think potentially it's because it returns a Map?
Having just encountered this exception and looked at the current answers as well as https://blogs.oracle.com/jmxetc/entry/javax_management_standardmbean_when_and I thought it might help to emphasize and clarify the following already elucidated to:
The NotCompliantMBeanException is caused, among other things, by failing to follow this convention 'ConcreteClassName' implements 'ConcreteClassNameMBean'
I resolved this by updating the original name of my mbean interface from 'OrignalNameMBean' to 'OriginalNameMXBean' allowing the mbean to be registered without following the convention
Another solution would be to follow the convention.
I had the same issue ("does not implement DynamicMBean, and neither follows the Standard MBean conventions") and this article helped me to resolve the problem (see Using StandardMBean section: https://blogs.oracle.com/jmxetc/entry/javax_management_standardmbean_when_and).
I have to explicitly construct a
StandardMBean mbean = new StandardMBean(mBeanImpl, MBeanInterface.class);
then register the mbean:
mbServer.registerMBean(mbean, mBeanName);
It works.
When I register the mBeanImpl with the mbServer, I got the above exception.
The implementing mbean class can declare as many methods as it likes that are not defined in mbeans interface... There is no requirement that the implementing class can/must only implement the interface methods.
In many of the cases this problem is caused because the mbean interface and implementation class are not in the same package!
You can change interface name from SomethingMBean to SomethingMXBean,such as HelloMBean to HelloMXBean,from jdk's source code i saw this:
public static boolean isMXBeanInterface(Class<?> interfaceClass) {
if (!interfaceClass.isInterface())
return false;
if (!Modifier.isPublic(interfaceClass.getModifiers()) &&
!Introspector.ALLOW_NONPUBLIC_MBEAN) {
return false;
}
MXBean a = interfaceClass.getAnnotation(MXBean.class);
if (a != null)
return a.value();
return interfaceClass.getName().endsWith("MXBean");
}
if not endsWith "MXBean",it will return false,then cause throw IllegalArgumentException
jdk version:1.8.0_25
class is "JMX",line 376
Just change interface suffix from 'MBean' to 'MXBean'.
This works for me.
Just change your implementation class name from ProfileCache to ProfileCacheInterface. It should work now. Moreover your implementation class can have any number of its own methods and those methods needs not to be mentioned in the MBean interface.
JMX's standard mbean naming convention is like this
public interface SomeBeanNameMBean{
...
}
public class SomeBeanName implements SomeBeanNameMBean{
...
//implements all the methods of SomeBeanNameMBean
...
//implement other class's own methods if needed
}
I faced the same problem like 'Exception in thread "main" javax.management.NotCompliantMBeanException', in my case I kept MBean interface and implementation classes in differnet package. To resolve the issue, I moved both MBean interface and the implementation class to same package.
In the all the examples I've seen for MBean implementations, I've never seen a class define a method that was not defined in the interface. E.g., ProfileCache has method updateCache, but ProfileCacheInterfaceMBean does not. Try removing the updateCache method from ProfileCache and see if it will work.
Related
I'm trying to implement a database authentication with Eclipse Scout.
For that I created a class DataSourceCredentialVerifier in the client module, which implements the ICredentialVerifierinterface. Then I adapted the init method of the UiServletFilter class to use my verifier.
public class DataSourceCredentialVerifier implements ICredentialVerifier {
private static final Logger LOG = LoggerFactory.getLogger(DataSourceCredentialVerifier.class);
#Override
public int verify(String username, char[] password) throws IOException {
Object queryResult[][] = BEANS.get(IMySqlAuthService.class).load();
return AUTH_OK;
}
I haven't implemented any authentication logic yet. My task now is to establish a clean database connection.
For that I created the following interface in the shared module:
public interface IMySqlAuthService extends IService {
Object[][] load();
}
The implementation is in the server module:
public class MySqlAuthService implements IMySqlAuthService {
#Override
public Object[][] load() {
String sql = "select username, password from users ";
Object[][] queryResult = SQL.select(sql, null, null);
return queryResult;
}
}
First I want to see, if there is at least something in the query, but I get an AssertionException here:
Object queryResult[][] = BEANS.get(IMySqlAuthService.class).load();
org.eclipse.scout.rt.platform.util.Assertions$AssertionException: Assertion error: no instance found for query: interface org.eclipse.scout.app.shared.services.IMySqlAuthService
at org.eclipse.scout.rt.platform.util.Assertions.fail(Assertions.java:580)
at org.eclipse.scout.rt.platform.util.Assertions.assertNotNull(Assertions.java:87)
at org.eclipse.scout.rt.platform.BEANS.get(BEANS.java:41)
I don't get an instance of my MySqlAuthService implementation. I assume that the BeanManager should have created an instance for me. MySqlAuthService should be registered as a Bean, since my IMySqlAuthService interface extends from IService which has the #ApplicationScoped annotation.
Adding the #Bean annotation to MySqlAuthService results in the same exception.
Here some information about the BeanManager and annotations:
https://eclipsescout.github.io/6.0/technical-guide.html#sec-bean.manager
Here is another different approach s.o. tried, but it doesn't feel correct:
https://www.eclipse.org/forums/index.php/t/1079741/
How can I get my example to work with my service?
Here is the working solution with important explanations of Eclipse Scout principles.
The source is summarized information of the Eclipse-Scout-Technical-Guide.
In Scout there is a built in annotation: #TunnelToServer. Interfaces marked with this annotation are called on the server. The server itself ignores this annotation.
To achieve that a bean is registered on client side, this annotation is required. The platform cannot (!) directly create an instance for these beans, a specific producer is registered which creates a proxy that delegates the call to the server.
My first clear mistake was that I hadn't annotated the IMySqlAuthServicewith #TunnelToServer.
After this addition I got rid of the no instance AssertionError.
After that my code ran into the HTTP status-code: 403 access forbidden.
This occured because my code didn't run in the correct Thread. That is the current RunContext. I had to use this lines of code in my verify method of the DataSourceCredentialVerifier:
Subject subject = new Subject();
subject.getPrincipals().add(new SimplePrincipal("system"));
subject.setReadOnly();
RunContext runContext = RunContexts.copyCurrent().withSubject(subject);
Now one can use the runContext's call() or run() method, depending whether the code returns a result. The action is run in the current thread, meaning that the caller is blocked until completion.
Concrete example solution:
Object[][] result = runContext.call(new Callable<Object[][]>() {
#Override
public Object[][] call() throws Exception {
return BEANS.get(IMySqlAuthService.class).load();
}
});
//TODO implement authentication logic.
For more information about the RunContext see here:
https://eclipsescout.github.io/6.0/technical-guide.html#runcontext
I am working on an application developed using Servlet and spring.
Below is the code followed by the description.
package com.mymodule.listener;
import net.sf.ehcache.*;
//imports
public class MyInitializationListener implements ServletContextListener {
/** Singleton instance of CacheManager. */
private static CacheManager singletonManager = null;
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("--ServletContextListener destroyed*--");
}
private static CacheManager getInstance() {
if (singletonManager == null) {
singletonManager = CacheManager.create();
}
return singletonManager;
}
private Cache getCache() {
Cache cache = null;
cache = MyInitializationListener.getInstance().getCache("myCache");
return cache;
}
// Run this before web application is started
public void contextInitialized(ServletContextEvent arg0) {
final Cache cache = getCache();
//logic here
}
Above is my Listener class which gets loaded as soon as the server is started. I have created the ehcache object in the above class. My requirement is as below:
Connect to the database and get the value.
Store the value in cache , so that any further request to that value is retrieved from a cache instead of a database hit.
But the issue is when the above Listener is initialized during server startup, my other XML files where I have configured the data sources are not yet started.So I cannot write any database logic in my Listener class. To solve this issue I have to write the database logic in other class and that class is present in other packages.
package com.mymodule.dao.hibernate;
public class MyDAOImpl extends HibernateDaoSupport implements MyDAO {
public String getDataValue() throws DataLayerException {
//String SQL = "...";
//logic to connect to the database and get the value.
//here I want to get that ehcache object which was created after the server is started in MyInitializerListener class.
}
Please suggest which would be the best possible way and how to get the ehcache object in other classes of the application present in different packages. The value returned from the database table is being used in many parts of the application , and that's the reason I want to store that value in ehcache and call from the cache whenever required.
Create a getter method like this:
public MyObject getMyObject()
{
return myObjectInstance;
}
Then you will be able to get the object from any class that creates an instance of the listener. If you need to get it into a class that doesn't create an instance of the listener, you can still use this, as long as the requesting class has a reference to a class that can reference a class (...) that has access to an instance of the listener.
For example, if You had a class that needs the object and has an instance of the class that instantiated the listener, you could just create a getter method inside both the listener and the class that created it:
In the listener:
public MyObject getMyObject()
{
return myObject;
}
In the class that created the listener:
public MyObject getMyObjectFromListener()
{
return listenerInstance.getMyObject();
}
It's dirty, but it should work.
Since you are using Spring, the correct way is to make the CacheManager or the Cache proper Spring beans.
Once that is achieved you will be able to inject them in the places that require them, whether it is a ServletContextListener or you DAO implementation.
I have the following problem with Guice: a singleton service, is injected with provider of context-sensitive information. Until now, context was related only to servlet requests, so I used a #RequestScoped provider, and I was injecting this provider in service like so:
#RequestScoped
public class ContextProvider<IContext> implements Provider<IContext> {
#Override
public IContext get() { ... } // returns context
}
#Singleton
public class ServiceImpl implements IService {
#Inject
private Provider<IContext> contextProvider;
}
That works fine. Now, I'm working on adding background task processing to the application. Background tasks are not initiated from web-requests, so I can not use ServletScopes.scopeRequest(..). I have written a custom scope (almost exact copy of BatchScoped from Giuce doc) to make each Task run in it's own scope. Now the question is - how to make BatchScoped ContextProvider and configure Guice to use it?
I've made this attempt with binding EDSL:
line 1 : bind(IContext.class).toProvider(ContextProvider.class).in(RequestScoped.class);
line 2 : bind(IContext.class).toProvider(BatchContextProvider.class).in(BatchScoped.class);
but Guice tells me at line 2 that 'A binding to IContext was already configured at line 1'.
The question is: what's the right way of doing such injection with Guice?
A similar question: Getting multiple guice singletons of the same type
In general the problem here is that you want to bind the same class to two different providers (and scopes, but that's actually beside the point). That is only possible if you use unique binding annotations for each one, like so:
bind(IContext.class)
.annotatedWith(MyAnnotation1.class)
.toProvider(ContextProvider.class)
.in(RequestScoped.class);
bind(IContext.class)
.annotatedWith(MyAnnotation2.class)
.toProvider(BatchContextProvider.class)
.in(BatchScoped.class);
And change injection sites to include relevant annotation:
#Inject
#MyAnnotationX
private Provider<IContext> contextProvider;
You need a fake request that starts with your background task and remains for all of it. That is what ServletScopes.scopeRequest does.
public class MyBackgroundTask extends Thread {
#Override
public void run() {
RequestScoper scope = ServletScopes.scopeRequest(Collections.emptyMap());
try ( RequestScoper.CloseableScope ignored = scope.open() ) {
doTask();
}
}
private void doTask() {
}
}
Oh, don't forget to use providers so you delay the retrieval of your dependencies. For example, expading the previous example so the background task uses your IContext.
public class MyBackgroundTask extends Thread {
private Provider<IContext> contextProvider;
#Inject
public MyBackgroundTask(Provider<IContext> contextProvider) {
this.contextProvider = contextProvider;
}
#Override
public void run() {
RequestScoper scope = ServletScopes.scopeRequest(Collections.emptyMap());
try ( RequestScoper.CloseableScope ignored = scope.open() ) {
doTask();
}
}
private void doTask() {
}
}
If you don't use providers the injection, in this example, will be done from the thread that creates the background task which could be inside another scope.
BONUS: You may have noticed the empty map sent as a parameter to the scopeRequest method. Check the Guice javadocs. Those are the instances that you want already present in your fake request scope. Depending on your IContext you may need it.
I have written sample JMX MBean "PoolMBean" based on my uderstanding of MBeans. I have written this to manage and monitor the connection pool. My question here is, is this the way Mbeans are written? Are there any issues in this Mbean code not related to connection pool?
1) What kind of objects can an Mbean method return?
package pool;
import java.util.Date;
public class Connection {
public Date createdAt;
protected int usedCount;
protected boolean isAvailable = true;
public Connection newConnection(){
Connection con= null;
/**
* Code for creating Connection
*/
return con;
}
public void writeDate(){
/**
* Code to write data in the stream
*/
usedCount++;
}
}
package pool;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.LinkedList;
import javax.management.MBeanServer;
import javax.management.ObjectName;
public class ConnectionPool {
public static int maxPoolSize = 20;
public int currentPoolSize = 10;
public LinkedList<Connection> totalPool = new LinkedList<Connection>();
public LinkedList<Connection> availablePool = new LinkedList<Connection>();
public static ConnectionPool cp = new ConnectionPool();
private ConnectionPool(){
}
public synchronized Connection getConnection(){
Connection con = null;
/**
*
*/
availablePool.remove(con);
con.isAvailable = false;
return con;
}
public synchronized void returnConnection(Connection con){
/**
*
*/
availablePool.addFirst(con);
con.isAvailable = true;
}
public static void main(String a[]){
try{
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
Pool mbean = new Pool();
ObjectName name = new ObjectName("test.conMbean:key1=Pool");
server.registerMBean(mbean, name);
System.out.println("Let me see out put");
System.in.read();
}catch (Exception e) {
e.printStackTrace();
}
}
}
package pool;
public interface PoolMBean {
public int getCurrentPoolSize();
public int getMaxPoolSize();
public void setMaxPoolSize(int maxSize);
}
package pool;
public class Pool implements PoolMBean {
#Override
public int getCurrentPoolSize() {
return ConnectionPool.cp.currentPoolSize;
}
#Override
public int getMaxPoolSize() {
return ConnectionPool.maxPoolSize;
}
#Override
public void setMaxPoolSize(int maxSize) {
ConnectionPool.maxPoolSize = maxSize;
}
}
Added this based on "yazan jber" answer provided below.
1) What kind of objects can a Mbean method return? For example if the PoolMBean hasgetStatistics() which returns totalPool LinkedList object. In this case in JConsole the value is displaying Unavailable, but when I tried with HashMap with String objects it worked? So the JConsole can't read everything, What it can read is my question here?
I have gone through the Oracle MXBean annotation API doc, the description here is bit complicated. What I got from this link is there are OpenType,ArrayType, CompositeType, SimpleType and TabularType these deals with only
java.lang.Void,
java.lang.Boolean,
java.lang.Character,
java.lang.Byte,
java.lang.Short,
java.lang.Integer,
java.lang.Long,
java.lang.Float,
java.lang.Double,
java.lang.String,
java.math.BigDecimal,
java.math.BigInteger,
java.util.Date,
javax.management.ObjectName,
CompositeData.class.getName(),
TabularData.class.getName()
these objects. MBean should return any one of this OpenType.
If we want to return any other type that new type should implement CompositeData interface, I didn't get much how this implementation will help Jconsole to read open objects, it is another complicated question?
To Track individual components in my application we should have our own MBeans? If my understanding is right I can use simple java class for this purpose, the extra benefit I'm getting here is the JConsole UI, Isn't it?
Your CompositeData will have a method to return its CompositeType. The type defines the attribute names (keys) of your CompositeData. JConsole, and other JMX clients, may use these keys to access data from the CompositeData.
It is perhaps too late to answer this question - however I wanted to take a shot at this given that I am currently studying JMX.
Questions answered :
Yes, the posted code looks to me to be the correct way to write MBeans within an application.
It is recommended to have custom defined MBeans to manage the resources exposed by an application. What resources warrant management is usually a design-time decision. However, from what I understand; we would want to manage resources that would have impact on the performance and stability of the system and hence would want to administer. A good example would be the Apache Solr related classes which implement the SoltInfoMBean management interface, so that these objects can be managed from the Solr Administration console.
While you can have your own custom implementation to track individual components of the system, the advantage of using MBeans to perform the tracking is not limited to jConsole** UI support alone. With the use of standard JMX interfaces, you provide facilities like Out-of-the-box management capabilities with any management applications that confirms to the JMX spec. Also it would support management over various communication protocols such as RMI, SNMP etc without the management console and the managed applications worry about the nitty-gritties of underlying protocol. This page provides a good set of reasons to use JMX interfaces to add monitoring capabilities to your application.
Hope this helps.
I didn't run the code but it looks fine, you can return any serializable object if the JMX client is Java and has access to the same serializable class, see this link
What is a use case for using a dynamic proxy?
How do they relate to bytecode generation and reflection?
Any recommended reading?
I highly recommend this resource.
First of all, you must understand what the proxy pattern use case. Remember that the main intent of a proxy is to control access to
the target object, rather than to enhance the functionality of the
target object. The access control includes synchronization, authentication, remote access (RPC), lazy instantiation (Hibernate, Mybatis), AOP (transaction).
In contrast with static proxy, the dynamic proxy generates bytecode which requires Java reflection at runtime. With the dynamic approach you don't need to create the proxy class, which can lead to more convenience.
A dynamic proxy class is a class that implements a list of
interfaces specified at runtime such that a method invocation through
one of the interfaces on an instance of the class will be encoded and
dispatched to another object through a uniform interface. It can be
used to create a type-safe proxy object for a list of interfaces
without requiring pre-generation of the proxy class. Dynamic proxy
classes are useful to an application or library that needs to provide
type-safe reflective dispatch of invocations on objects that present
interface APIs.
Dynamic Proxy Classes
I just came up with an interesting use for a dynamic proxy.
We were having some trouble a non-critical service that is coupled with another dependant service and wanted to explore ways of being fault-tolerant when that dependant service becomes unavailable.
So I wrote a LoadSheddingProxy that takes two delegates - one is the remote impl for the 'normal' service (after the JNDI lookup). The other object is a 'dummy' load-shedding impl. There is simple logic surrounding each method invoke that catches timeouts and diverts to the dummy for a certain length of time before retrying. Here's how I use it:
// This is part of your ServiceLocator class
public static MyServiceInterface getMyService() throws Exception
{
MyServiceInterface loadShedder = new MyServiceInterface() {
public Thingy[] getThingys(Stuff[] whatever) throws Exception {
return new Thingy[0];
}
//... etc - basically a dummy version of your service goes here
}
Context ctx = JndiUtil.getJNDIContext(MY_CLUSTER);
try {
MyServiceInterface impl = ((MyServiceHome) PortableRemoteObject.narrow(
ctx.lookup(MyServiceHome.JNDI_NAME),
MyServiceHome.class)).create();
// Here's where the proxy comes in
return (MyService) Proxy.newProxyInstance(
MyServiceHome.class.getClassLoader(),
new Class[] { MyServiceInterface.class },
new LoadSheddingProxy(MyServiceHome.JNDI_NAME, impl, loadShedder, 60000)); // 10 minute retry
} catch (RemoteException e) { // If we can't even look up the service we can fail by shedding load too
logger.warn("Shedding load");
return loadShedder;
} finally {
if (ctx != null) {
ctx.close();
}
}
}
And here's the proxy:
public class LoadSheddingProxy implements InvocationHandler {
static final Logger logger = ApplicationLogger.getLogger(LoadSheddingProxy.class);
Object primaryImpl, loadDumpingImpl;
long retry;
String serviceName;
// map is static because we may have many instances of a proxy around repeatedly looked-up remote objects
static final Map<String, Long> servicesLastTimedOut = new HashMap<String, Long>();
public LoadSheddingProxy(String serviceName, Object primaryImpl, Object loadDumpingImpl, long retry)
{
this.serviceName = serviceName;
this.primaryImpl = primaryImpl;
this.loadDumpingImpl = loadDumpingImpl;
this.retry = retry;
}
public Object invoke(Object obj, Method m, Object[] args) throws Throwable
{
try
{
if (!servicesLastTimedOut.containsKey(serviceName) || timeToRetry()) {
Object ret = m.invoke(primaryImpl, args);
servicesLastTimedOut.remove(serviceName);
return ret;
}
return m.invoke(loadDumpingImpl, args);
}
catch (InvocationTargetException e)
{
Throwable targetException = e.getTargetException();
// DETECT TIMEOUT HERE SOMEHOW - not sure this is the way to do it???
if (targetException instanceof RemoteException) {
servicesLastTimedOut.put(serviceName, Long.valueOf(System.currentTimeMillis()));
}
throw targetException;
}
}
private boolean timeToRetry() {
long lastFailedAt = servicesLastTimedOut.get(serviceName).longValue();
return (System.currentTimeMillis() - lastFailedAt) > retry;
}
}
The class java.lang.reflect.Proxy allows you to implement interfaces dynamically by handling method calls in an InvocationHandler. It is considered part of Java's reflection facility, but has nothing to do with bytecode generation.
Sun has a tutorial about the use of the Proxy class. Google helps, too.
One use case is hibernate - it gives you objects implementing your model classes interface but under getters and setters there resides db related code. I.e. you use them as if they are just simple POJO, but actually there is much going on under cover.
For example - you just call a getter of lazily loaded property, but really the property (probably whole big object structure) gets fetched from the database.
You should check cglib library for more info.