I'm new to Apache Camel. I'm trying to send an exchange from a java method to a route but it gives me "Caused by: org.apache.camel.component.direct.DirectConsumerNotAvailableException: No consumers available on endpoint" error. I want to understand what exactly this error is and when do we get this?
#EndpointInject(uri = "direct:reportRoute")
private ProducerTemplate templatereportRoute;
public void saveDataFromExchange(Map<String, Object> DataMap){
List<Map<String, Object>> paramList = new ArrayList<Map<String, Object>>();
List<Map<String, Object>> rows = templatereportRoute.requestBody("direct:reportReport", DataMap, List.class);
<from uri="direct:reportRoute"/>
<log message=" - ${body}" loggingLevel="INFO"/>
<setProperty propertyName="DataMap">
<simple>${body}</simple>
</setProperty>
The error you encounter means that you are sending to a direct endpoint that does not exist in the Camel Context.
Since you posted an XML fragment that defines the route in question there are two possible problems (as already commented by #claus-ibsen):
The XML you posted is not in use. You are starting a Camel Context but it does not use your XML code. Are you using Spring? Then you can define your Camel routes in Spring XML.
Your setup is fine but your Java code sends the message too early, i.e. before the direct endpoint is up and running. You can put this code in a Test class and run it after the Camel context is started and ready.
Try put in public class from routerBuilder implemention the anotation #Component from Spring context
Ex:
#Component //<<<<---- This
public class RouterClass extends RouteBuilder {
#Override
public void configure() throws Exception {
}
}//class closure
Related
I Just want to learn custom converter and ran into issue. Any help is much appreciated. Camel Version 2.17 and JBoss Fuse 6.3
#Converter
public class MyConvertor{
public MyConvertor(){}
#Converter
public static String convertTo(Exchange exchange) {}
}
In My Spring DSL
<convertBodyTo charset="UTF-8" id="_convertBodyTo1" type="com.x.convertor.MyConvertor"/>
In META-INF/services/org/apache/camel/TypeConverter
com.x.convertor.MyConvertor
Error message :
org.apache.camel.InvalidPayloadException: No body available of type: com.x.convertor.MyConvertor but has value: GenericFile[output.txt] of type: org.apache.camel.component.file.GenericFile on: output.txt. Caused by: No type converter available to convert from type:
at org.apache.camel.processor.Pipeline.process(Pipeline.java:121)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
Caused by: org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: org.apache.camel.component.file.GenericFile to the required type: com.x.convertor.MyConvertor
There are a couple of errors. The type attribute should be your target type (the type you want after conversion).
<convertBodyTo charset="UTF-8" id="_convertBodyTo1" type="java.lang.String"/>
Camel can do this conversion automatically. If you want to write a converter on your own, mind that converter method should have the expected input type as parameter, and not the Exchange (which can be an optional second parameter from Camel 2.16 onwards).
Class should be something like:
#Converter
public class MyConvertor{
public MyConvertor(){}
#Converter
public static String convertTo(GenericFile body, Exchange exchange) {
// The exchange parameter is optional
}
}
See https://camel.apache.org/type-converter.html
If you want to read the content of a CSV file to transform it into a POJO, use Bindy component.
I am sending a Java object to producer endpoint and waiting for the marshalled XML object. I tried changing it to Node object/ File object but it is giving ClassCastException.
So took the xmlObj in an object class type. What should be the correct class to capture the response?
public class ClientEight {
#Produce(uri = "direct:invoice")
ProducerTemplate template;
public static void main(String args[]) throws InterruptedException {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("resources/camel-configTen.xml");
InvoiceXml invoice = new InvoiceXml("fdf3443", 3454, 435345.44 f, "hfhfddfdg"); //any java object we are passing
ClientEight client = (ClientEight) ctx.getBean("client");
Object xmlObj = client.template.requestBody(invoice);
System.out.println(xmlObj);
}
}
Above is a client code which you are using to send the Java object to a producer endpoint and since you are using template.requestBody, you are getting back the object returned.
<camel:camelContext>
<camel:dataFormats>
<!-- path to jaxb annotated class -->
<camel:jaxb id="invoiceJaxb" contextPath="com.java.bean"
prettyPrint="true" />
</camel:dataFormats>
<camel:route>
<camel:from uri="direct:invoice" />
<camel:marshal ref="invoiceJaxb" />
<camel:log message=" ${body}" />
<camel:to uri="file://src/resources?fileName=One.xml"/>
</camel:route>
</camel:camelContext>
the unmarshall processor return a stream, not a single object. In camel, more generally, if you want a specific type, you shouldn't get directly a body as an object, but use the various methods to convert the body into that type.
Try :
Document document = client.template.requestBody(invoice, org.w3c.dom.Document.class);
I am new to camel, i am trying to use camel cxf component to create a soap webservice. I started with a samples from camel in action. I have configured a route using cxf component and added a processor to process the request. I received the request in the bean i used to process the service but i cant able to send the response back to the client. Thanks in advance
This is the route i used :
<route>
<from uri="cxf:bean:orderEndpoint" />
<setExchangePattern pattern="InOut"/>
<to uri="bean:productService" />
</route>
This is the cxf endpoint i have configured,
<cxf:cxfEndpoint id="orderEndpoint"
address="/"
serviceClass="camelws.ws.ProductService"/>
This is the bean i used:
#Service("productService")
public class ProductServiceImpl {
public Product getProducts(){
System.out.println("Inside webservices method....");
Product product = new Product();
product.setName("test product");
product.setPrice("3242");
return product;
}
}
Sysout statement is printed on the console but i am getting a soap response with empty body.
below is my response when i hit http://localhost:9080// from browser:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body/>
</soap:Envelope>
You should implement a Processor, intercept and process your message using something like that :
public class MyProcessor implements Processor {
public void process(Exchange exchange) throws Exception {
...
// Set your response here
exchange.getOut().setBody(product);
}
}
Then reference your processor in your route.
Your response is what you have in your route body after your rote ends, so you must create your massege response object before route ends.
For POJO producing, it is mentioned in Camel docs that InOut is the default.
But, if we are using the sendBody() of ProducerTemplate, is there any need of setting #InOnly also as in the example below.
public class MyBean {
#Produce(uri = "direct:hello")
private ProducerTemplate producerTemplate;
#InOnly
void someInOnlyMethod()
{
...
producerTemplate.sendBody("mystr");
...
}
}
Similarly in the example below, if direct:hello gets a message from the above MyBean object configured without the #InOnly annotation, do we need the setExchangePattern element?
<route>
<from uri="direct:hello"/>
<setExchangePattern pattern="InOnly"/>
<to uri="mock:result"/>
</route>
1)
No when you use the producer template then the MEP is set accordingly to the method you use on the template. eg all send methods is InOnly, and all request methods is InOut. Though some methods has a pattern parameter where you can specify the MEP.
2)
No you often dont have to set/change the MEP. Though in situations where you send a message to a endpoint which supports both InOnly or InOut (and behaves differently) you may want to set the MEP explicit to your needs.
See about these EIPs for details
http://camel.apache.org/event-message.html
http://camel.apache.org/request-reply.html
for example a JMS endpoint can do InOnly (send only to a queue) or InOut (do request/reply over JMS) etc.
I'm trying to set up my first Java application using Spring Data for MongoDB in a multi-module Maven 3 project. Here are the relevant versions:
Java 7
mongodb-win32-x86_64-2.2.0
Spring Data 1.1.1.RELEASE
Spring 3.2.0.RELEASE
I'm getting the following runtime error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'actorFacade': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private es.mi.casetools.praetor.persistence.springdata.repositories.ActorRepository es.mi.casetools.praetor.facade.impl.DefaultActorFacade.actorRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'actorRepository': FactoryBean threw exception on object creation; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property insert found for type void
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:609)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:106)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:57)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:248)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)
... 30 more
Searching in google I found people with the same issue and it seems to be related with custom repositories.
Here is the entity I want to store as a mongo document.
public class Actor {
public enum ActorStereotype {
SYSTEM,
PERSON
}
private String id;
private String code; // unique
private ActorStereotype stereotype;
private String title; // Short title for the actor
private String description;
private String projectId; // project this actor belongs to
// getters & setters
The standard repository interface.
public interface ActorRepository extends MongoRepository<Actor, String>, ActorRepositoryCustom {
}
The custom interface (where I think the error lives).
#NoRepositoryBean
public interface ActorRepositoryCustom {
void updateSingleActor(Actor actor);
void insertActor(Actor actor);
}
The custom interface implementation.
public class ActorRepositoryCustomImpl implements ActorRepositoryCustom {
#Autowired
private MongoTemplate mongoTemplate;
#Override
public void updateSingleActor(Actor actor) {
if(actor.getId() != null)
throw new MissingIdException();
// TODO change to Spring Converter
DBObject dbo = (DBObject)mongoTemplate.getConverter().convertToMongoType(actor);
mongoTemplate.updateFirst(query(where("_id").is(actor.getId())),
Update.fromDBObject(dbo, new String[]{}),
Actor.class);
}
#Override
public void insertActor(Actor actor) {
if(actor.getId() != null)
throw new IdProvidedException();
mongoTemplate.save(actor);
}
}
And finally, the application context.
<context:annotation-config/>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:properties/test.properties</value>
</list>
</property>
</bean>
<!-- mongodb configuration -->
<mongo:repositories base-package="es.mi.casetools.praetor.persistence.springdata.repositories"
mongo-template-ref="mongoTemplate" repository-impl-postfix="Impl">
<repository:exclude-filter type="annotation" expression="org.springframework.data.repository.NoRepositoryBean"/>
</mongo:repositories>
<mongo:mongo id="mongotest" host="${mongo.host}" port="${mongo.port}" write-concern="SAFE">
</mongo:mongo>
<mongo:db-factory dbname="${mongo.dbname}" mongo-ref="mongotest"/>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
</bean>
<bean id="actorFacade" class="es.mi.casetools.praetor.facade.impl.DefaultActorFacade">
</bean>
</beans>
I also have a little Spring test that fails loading the above application context giving the exception I listed near the top.
I tried adding the following but I get the same exception.
<bean id="actorRepositoryCustomImpl" class="es.mi.casetools.praetor.persistence.springdata.repositories.ActorRepositoryCustomImpl"></bean>
Has someone got a clue of what the error may be?
Miguel's comment solved the problem. I had given the wrong name to the implementing class. I've seen similar questions around so I'll try to clarify the solution in the hope that it helps someone else.
I have the following interface definition
public interface ActorRepository extends MongoRepository<Actor, String>, ActorRepositoryCustom
The custom interface definition looks like this:
public interface ActorRepositoryCustom
So my error was naming the implementation of ActorRepositoryCustom with ActorRepositoryCustomImpl, expecting Springdata would pick up the implementation as its postfix is the default one Impl. The thing is, Springdata looks for ActorRepositoryImpl by default, even though what you are implementing is ActorRepositoryCustom. The solution is using the optional attribute repository-impl-postfix and set it to CustomImpl.