camel proxy complains about wrong type - java

I configured a spring boot based application to use remoting with activemq/jms. The listening part is running fine but I have problems implementing the sending part.
For the sender I went back to "classic" camel and spring because I found more working examples for this but still receive an error:
org.springframework.beans.factory.BeanNotOfRequiredTypeException:
Bean named 'myProxy' must be of type [foo.bar.YouNameIt],
but was actually of type [com.sun.proxy.$Proxy83]
This is the way I try to load the proxy definition:
ApplicationContext context = new ClassPathXmlApplicationContext("config/spring.xml");
YouNameIt youNameIt = context.getBean("myProxy", YouNameIt.class);
And this is the entry in the spring.xml:
<camel:proxy id="myProxy"
serviceInterface="foo.bar.IYouNameIt"
serviceUrl="activemq:queue:site12345" />
What am I doing wrong ?

Access the interface IYouNameIt and not the implementation class YouNameIt:
IYouNameIt youNameIt = context.getBean("myProxy", IYouNameIt.class);
See here for a full Spring remoting example.

Related

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).

Apache Camel Dynamic Consumers

I have created this Camel routes
from("direct:pageExtraction")
.bean(PageManager.class, "setProperties(*, ${headers})")
.filter().method(PageManager.class, "exists").to("seda:pagePostProcessing").end()
.to("seda:pageImposition");
from("seda:pagePostProcessing")
.bean(PageManager.class, "extractThumbnail(*, ${headers})")
.bean(PageManager.class, "extractCMYKSeparation(*, ${headers})")
.bean(PageManager.class, "persist(*, ${headers})")
.bean(PageManager.class, "cleanUp(${headers})")
.to("seda:pageImposition");
from("seda:pageImposition")
.bean(PageManager.class, "extractImposition(*, ${headers})")
.to("seda:printQueue");
At the end, the seda:printQueue has no consumers, sending a message in a route like this apparently works fine. Now I want to introduce a new consumer after the routes have been initialized, I thought it would be possible to create a Spring bean programmatically and let Camel pick up the bean using the #Consume(uri="seda:printQueue") annotation, but as soon as I create the consumer Camel complains
org.apache.camel.RuntimeCamelException: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named '4965d710-b5c7-41cf-97e9-a42bdfcea894' is defined]
Any thoughts?
[UPDATE]
I have traced back the error to the class where this new consumer is created, I'm instantiating the PrintQueue class and then integrating it to the Spring context using an AutowireCapableBeanFactory doing a factory.autowireBean(printQueueInstance) followed by factory.initializeBean(printQueueInstance, id) where id is the 4965d710-b5c7-41cf-97e9-a42bdfcea894 that appears in the exception above, so I think this has to be some kind of context scope problem, may be I am creating this bean in the main or web Spring context and it can't be access by the Camel context, is this possible?
Since this route is invoked synchronously via use of the "direct:" component, it does not appear to require "seda:" for asynchronous invocation of another bean. In this situation, it would appear simplest to invoke a bean with Camel's bean methods for the Java DSL. As an example shown in the Camel bean documentation at:
http://camel.apache.org/bean.html
I would simply do:
// Send message to the bean endpoint
// and invoke given method.
from("direct:start")
// do other stuff in your route
.beanRef("beanName", "methodName");

What means this JMS configuration into a Spring application?

I am studying how Spring framework handle JMS and I have the following doubt related this question founded on my study material.
Consider the following JMS configuration defined into a Spring application:
<jms:listener-container connetionFactory="connectionFactory">
<jms:listener-destination="order.queue" ref="orderListener" method="order" />
</jms:listener-container>
What exactly does this configuration?
Now I know that a JMS connection is tipically obtained from a factory, so I think that it is configuring the factory that give me my JMS connection (is it right?)
But what exactly specify this line?:
<jms:listener-destination="order.queue" ref="orderListener" method="order" />
Tnx
That would be a Message-driven Bean-like in the plain Java EE world. Have a look here. By the way, the attribute is destination="queue.name"; there is no such a thing like <jms:listener-destination="order.queue"...
destination: The destination name for this listener (in other words: the queue where the listener will "listen" to; named as destination in newer versions of Spring)
ref: The bean name of the handler (see next point)
method: The name of the handler method to invoke. If the ref points to a MessageListener or Spring SessionAwareMessageListener, this attribute may be omitted (this is why the latter two must implements the onMessage method, and by convention this will be called)

jetty spring "No resource at X" ResourceAnnotationHandler

I have a java webapp that works just fine, but today I tried to start using spring for dependency injection. The app should run on Jetty Server but i'm stuck on this problem.
When I try to use any servlets that contain a spring dependency, I get this error:
java.lang.IllegalStateException: No resource at valueService
at org.eclipse.jetty.annotations.ResourceAnnotationHandler.handleMethod(ResourceAnnotationHandler.java:345)
at org.eclipse.jetty.annotations.ResourceAnnotationHandler.doHandle(ResourceAnnotationHandler.java:66)
at org.eclipse.jetty.annotations.AnnotationIntrospector$AbstractIntrospectableAnnotationHandler.handle(ResourceAnnotationHandler.java:345)
valueService is the name of the first dependency in the HttpServlet annotated with spring like this:
#Resource(name="valueService")
protected ValueService valueService;
which is defined in my application context as:
<bean id="valueService" class="com.nimbits.server.transaction.value.service.ValueServiceImpl" />
So, jetty is open source, so when I look at the code in jetty server ResourceAnnotationHandler.java:345 it's doing this:
else if (!Util.isEnvEntryType(paramType))
{
//if this is an env-entry type resource and there is no value bound for it, it isn't
//an error, it just means that perhaps the code will use a default value instead
// JavaEE Spec. sec 5.4.1.3
throw new IllegalStateException("No resource at "+(mappedName==null?name:mappedName));
}
so there is my error. Question: any jetty experts know why jetty is processing my spring annotation and throwing this exception. Is there a way to satisfy it? Or stop it?
Thanks, really stuck.
Ben
#Resource(name="valueService")
protected ValueService valueService;
made jetty unhappy
switching to:
#Autowired
protected ValueService valueService;
resolved it

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

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

Categories

Resources