I am using JMX in Spring application with XML configuration:
<bean id="jmxExporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="bean:name=bean1" value-ref="bean1"/>
<entry key="bean:name=bean2" value-ref="bean2"/>
<entry key="bean:name=bean3" value-ref="bean3"/>
</map>
</property>
<property name="notificationListenerMappings">
<map>
<entry key="*">
<bean class="com.test.listener"/>
</entry>
</map>
</property>
</bean>
<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
<property name="port" value="1099" />
</bean>
<bean id="serverConnector"
class="org.springframework.jmx.support.ConnectorServerFactoryBean">
<property name="objectName" value="connector:name=rmi" />
<property name="serviceUrl"
value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi" />
</bean>
I understand from various documents like instead of this XML configuration we could annotate it with #EnableMBeanExport and with #ManagedResource for the beans.
But i doubt how ConnectorServerFactoryBean gets configured with these annotations. Or is there any annotation available to configure RMI and connectorServerFactoryBean?
Also i need to know how to annotate, notificationListenerMappings configured?
P.S:
I have the code working for publisher and listener under XML configuration. I am planning to move it completely on annotation based as i do not want to disturb XML configuration already in PROD.
Edited
Found the following piece of code: planning to try it:
#Bean
public RmiRegistryFactoryBean registry() {
return new RmiRegistryFactoryBean();
}
#Bean
#DependsOn("registry")
public ConnectorServerFactoryBean connectorServer() throws MalformedObjectNameException {
ConnectorServerFactoryBean connectorServerFactoryBean = new ConnectorServerFactoryBean();
connectorServerFactoryBean.setObjectName("connector:name=rmi");
connectorServerFactoryBean.setServiceUrl("service:jmx:rmi://localhost/jndi/rmi://localhost:1099/connector");
return connectorServerFactoryBean;
}
Edit 2:
I am proceeding on above mentioned approach and I am able to configure MBeans and able to publish notifications. But unfortunately I am stuck up with configuring NotificationListener through Annotation.
I tried adding the following:
#Bean
#DependsOn("registry")
public ConnectorServerFactoryBean connectorServer() throws MalformedObjectNameException {
ConnectorServerFactoryBean connectorServerFactoryBean = new ConnectorServerFactoryBean();
connectorServerFactoryBean.setObjectName("connector:name=rmi");
connectorServerFactoryBean.setServiceUrl("service:jmx:rmi://localhost/jndi/rmi://localhost:1099/connector");
//TestListener is my NotificationListener class
ObjectName objectName = new ObjectName("bean:name=bean1");
connectorServerFactoryBean.getServer().addNotificationListener(objectName,
new TestListener(), null,null);
return connectorServerFactoryBean;
}
I am getting instanceNotFoundException stating bean:name=bean1 is not found. But I have configured like, #ManagedResource(objectName="bean:name=bean1") on my bean1.
Any help please on what i am missing?
#EnableMBeanExport has a server property, which reference the bean name of a server object.
see for example the test of this component, which use this server property : https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/test/java/org/springframework/jmx/export/annotation/EnableMBeanExportConfigurationTests.java
Related
I am refering to Spring AOP by Mkyong http://www.mkyong.com/spring/spring-aop-example-pointcut-advisor/
It worked when tried running from main (i.e. App.java) as given on above link,
I want to integrate it in restful webservice where i have multiple service like CutomerService in mkyong's example.
For example i have controller which calls CustomerService,
#RestController
#RequestMapping(value = "/customer")
public class CustomerController{
#Autowired CustomerService customerService;
#RequestMapping(value = "/getCustomer", method = RequestMethod.GET")
public ResponseEntity<CommonResponse> getService(){
customerService.printName();
}
}
It didn't worked.
i have tried this also:
#Autowired
private ProxyFactoryBean customerServiceProxy;
#RequestMapping(value = "/getCustomer", method = RequestMethod.GET")
public ResponseEntity<CommonResponse> getService(){
CustomerService customerService = (CustomerService) customerServiceProxy
.getTargetSource().getTarget();
customerService.printName();
}
}
this dosent work either.
Any Solution for this?
my bean-config.xml is same as mkyong's example.
It worked ! Just need to change proxy class from "org.springframework.aop.framework.ProxyFactoryBean" to
"org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
Auto proxy creator identifies beans to proxy via a list of names. So we don,t need to specify target bean instead list of beans can be specified and it will intercept automatically.
My config look as below:
<bean id="adviceAround" class="com.tdg.ess.semantic.event.log.AdviceAround" />
<!-- Event logging for Service -->
<bean id="testServicePointCut" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>process</value>
</list>
</property>
</bean>
<bean id="testServiceAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut" ref="testServicePointCut" />
<property name="advice" ref="adviceAround" />
</bean>
<bean
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<!-- Differnt beans which have certain service defined like CustomerService-->
<value>testService1</value>
<value>testService2</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>testServiceAdvisor</value>
</list>
</property>
</bean>
Thanks everyone for looking into.
I am new to spring. Admins of my spring based web app want to configure settings from the web interface, so users can authenticate against LDAP server with their company username and password.
Change in LDAP settings should be possible without restarting the application. This might happen during a 'migration' or whatever reason. I have a couple beans, which need to be refreshed after the admin saves new settings for the LDAP server:
<bean id="ldapServer" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg>
<list>
<value>${ldap.url1}</value>
...
</list>
</constructor-arg>
<constructor-arg value="${ldap.basedn}"</constructor-arg>
<property name="referral" value="${ldap.referral}" />
<property name="baseEnvironmentProperties">...</property>
<property name="userDn" value="${ldap.username}" />
<property name="password" value="${ldap.password}" />
</bean>
I am using Springframework 3.1.2. The problem is, there are constructor arguments, which I want to change and not affect other running jobs. I tried playing with Scoped proxy, but not to much success yet:
<bean id="ldapServer" scope="prototype" ...>
<aop:scoped-proxy/>
I was successful though to get ldapServer to reinstantiate, when using prototype scope by running this piece of code:
#Controller
public class LDAPSettingsController implements ApplicationContextAware {
public ModelAndView handleRequest(...) {
DefaultSpringSecurityContextSource ldap;
ldap = context.getParentBeanFactor().getBean("ldapServer");
System.out.println(ldap.hashCode());
return new ModelAndView(new RedirectView('login.jsp'));
}
...
}
Are scopes and proxies here the way to go, or is the another mechanism in Spring to reflect configuration changes into a running program instance?
UPDATE: Clear up the question.
UPDATE: The root problem with the AOP proxies was following root exception:
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
What worked was adding proxy-target-class="false" attribute to the <aop:scoped-proxy/> tag. I created a new scope, which works better than prototype - It destroys beans on settings update. Now I have this in my beans.xml:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="ldap">
<ref bean="ldapScope" />
</entry>
</map>
</property>
</bean>
<bean id="ldapScope" class="com.myapp.SettingsScope" />
<bean id="ldapServer" scope="ldap" ...>
<aop:scoped-proxy proxy-target-class="false"/>
<constructor-args>
<list><value>${ldap.url1}</value> .. </list>
</constructor-args>
...
</bean>
I also have a controller for LDAP settings into which I inject ldapScope and I call a method which destroys current life-cycle objects and starts a new life-cycle every time, user presses the apply button.
PS: Not sure if I handle the life-cycle "re-start" in the right way - people my way to look for auto-start beans and start them after such event happens (i.e.: Setting -> Apply)
I'm trying to add a simple redirect into a web application built in Restlets, and it's proving non-trivial. The task is a simple one: I want to actually redirect all missing files from a web application to the same static file.
I'm using org.restlet.routing.Redirector with the following values (I'm using Spring injection):
<bean name="router" class="org.restlet.ext.spring.SpringRouter">
<constructor-arg ref="trackerComponentChildContext" />
<property name="attachments">
<map>
<entry key="/api" value-ref="apiRouter" />
<entry key="/statics" value-ref="staticsDirectory" />
<entry key="/" value-ref="staticsRedirector" />
</map>
</property>
</bean>
<bean id="staticsRedirector" class="ca.uhnresearch.pughlab.tracker.restlets.CustomRedirector">
<constructor-arg ref="trackerComponentChildContext" />
<constructor-arg value="{o}/statics/index.html" />
<constructor-arg value="7" />
</bean>
I can play with the file hierarchy relatively simply, but I just want to send anything that doesn't match either /api or /statics to /statics/index.html within the same application.
Restlet is almost getting it, and it does seem now to pick up the reference to the correct file, it just doesn't quite serve it.
I've put a working copy of the whole thing (including Thierry's suggestions below) at: https://github.com/morungos/restlet-spring-static-files. What I'd like to happen is something like the equivalent sequential attempts below:
curl http://localhost:8080/statics/**/* to hit the corresponding /statics/**/*
curl http://localhost:8080 to hit the main /statics/index.html
curl http://localhost:8080/**/* to hit the main /statics/index.html
I made some tests regarding your issue and I can't figure out how to have your message :-(. Perhaps it's because I haven't the whole code.
In fact, I saw a problem at the level of the SpringRouter itself. I would like to attach the redirector with an attachDefault and not an attach("/", ...) / attach("", ...). The method setDefaultAttachment actually does an attach("", ...).
So I made work something with the following updates:
Create a custom SpringRouter
public class CustomSpringRouter extends SpringRouter {
public void setDefaultAttachment(Object route) {
if (route instanceof Redirector) {
this.attachDefault((Restlet) route);
} else {
super.setDefaultAttachment(route);
}
}
}
Create a custom Redirector. I got the context from the component instead of a child context.
public class CustomRedirector extends Redirector {
public CustomRedirector(Component component, String targetPattern, int mode) {
super(component.getContext(), targetPattern, mode);
}
}
I then use the following Spring configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myComponent" class="org.restlet.ext.spring.SpringComponent">
<property name="defaultTarget" ref="router" />
</bean>
<bean name="router" class="test.CustomSpringRouter">
<property name="attachments">
<map>
<entry key="/api" value-ref="apiRouter" />
<entry key="/statics" value-ref="staticsDirectory" />
</map>
</property>
<property name="defaultAttachment" ref="staticsRedirector" />
</bean>
<bean id="staticsRedirector" class="test.CustomRedirector">
<constructor-arg ref="myComponent" />
<constructor-arg value="{o}/statics/index.html" />
<constructor-arg value="7" />
</bean>
<bean name="apiRouter" class="org.restlet.ext.spring.SpringRouter">
(...)
</bean>
(...)
</beans>
Hope it helps you,
Thierry
So I currently am working on a project that uses Spring to inject a schema location for the xsd when calling an xsl, something like:
<bean id="transformer" class="com.mypackage.Transformer">
<property name="xsl" value="sample.xsl" />
<property name="params">
<map>
<entry key="schemaLocation" value-ref="schema" />
</map>
</property>
</bean>
<bean id="schema" class="java.lang.String">
<constructor-arg value="http://www.sample.com/schema/sampleSchema.xsd" />
</bean>
This works fine when you use a url as the schema location, but say for example you want to refer to a schema that is brought in on the classpath as a maven dependency. I've found that using something like 'classpath:sampleSchema.xsd' doesn't work. I would've thought this kind of behaviour was fairly common, is there an accepted workaround to this? Create a custom class that looks up the schema on the classpath and returns its path as a string?
OK so I thought I would share how I fixed this.
Two spring beans:
<bean id="schema" factory-method="getSchemaLocation" factory-bean="schemaFinder" />
<bean id="schemaFinder" class="com.mypackage.SchemaFinder">
<constructor-arg value="NAME_OF_SCHEMA" />
</bean>
And a class:
public class SchemaFinder
{
private String schemaLocation;
public SchemaFinder(String schemaName) throws Exception
{
try
{
URL absoluteSchemaUrl = getClass().getClassLoader().getResource(schemaName);
setSchemaLocation(absoluteSchemaUrl.toString());
}
catch (Exception e)
{
//whatever you want here
}
}
public void setSchemaLocation(String schemaLocation)
{
this.schemaLocation = schemaLocation;
}
public String getSchemaLocation()
{
return this.schemaLocation;
}
}
Quite easy when you think about it...
I'd like to publish JMX notifications using Spring 3, but would like to avoid using the NotificationPublisherAware interface, since the code is also used by an application that doesn't use Spring. The bean is exposed using MBeanExporter bean. The alternatives I found require registering the mbeans, which I currently do using Spring configuration, so this is a bad option.
Is there a way to avoid using the NotificationPublisherAware interface but still publish notifications?
You don't have to use any Spring class in code. Example:
Interface:
import javax.management.MXBean;
#MXBean
public interface SecurityEventsManagerMXBean {
...
#AttributeMetaData(value="UserLoginFailures", defaultValue="0", description="Total user login failures")
public int getUserLoginFailureCount() ;
...
}
Bean:
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
public class SecurityEventsManager extends NotificationBroadcasterSupport implements SecurityEventsManagerMXBean {
...
private void notifyUserLoginFailure(...) {
Notification notification = new Notification(...) ;
sendNotification(notification)
userLoginFailureCount++ ;
}
}
Here #AttributeMetaData is a convenient meta annotation that defines descriptor keys:
import javax.management.DescriptorKey;
#Documented
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface AttributeMetaData {
#DescriptorKey("displayName")
String value();
....
}
Edit March 08. Configuration to export above Mbean:
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"
p:locateExistingServerIfPossible="true" />
<bean id="jmxAttributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
<bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy"
p:attributeSource-ref="jmxAttributeSource" />
<bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler"
p:attributeSource-ref="jmxAttributeSource" />
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="server" ref="mbeanServer"/>
<property name="assembler" ref="assembler"/>
<property name="registrationBehaviorName" value="REGISTRATION_FAIL_ON_EXISTING"/>
<property name="beans">
<map>
<entry>
<key>
<util:constant
static-field="x.y.z.SecurityEventsManager.OBJECT_NAME" />
</key>
<ref bean="securityEventsManager" />
</entry>
</map>
</property>
</bean>
<bean id="securityEventsManager" class="x.y.z.SecurityEventsManager" />
As per Spring docs:
The NotificationPublisher interface and the machinery to get it all working is one of the nicer features of Spring's JMX support. It does however come with the price tag of coupling your classes to both Spring and JMX; as always, the advice here is to be pragmatic... if you need the functionality offered by the NotificationPublisher and you can accept the coupling to both Spring and JMX, then do so.
Ref: http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch24s07.html#jmx-notifications-listeners