I started today with Mule. I spent about 8 hours now, but can't get very far. I can't seem to execute the method of the Spring StoredProcedure if I execute it using the http:inbound-endpoint. It works using vm:inbound-endpoint. I assumed the transformer would get executed if Mule saw it accepted a String or a FundStatementParam object, but it doesn't get executed.
It seems mule is looking for a method that accepts org.apache.commons.httpclient.ContentLengthInputStream on za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc. I don't really want to add methods to my current project and I don't want to include Mule classes to my main project that contains the business logic
I am not sure if I am required to create a wrapper classes over the business logic classes
*mulefundstatements2-functional-test-config.xml*
<spring:beans>
<spring:import resource="classpath*:spring/datasourceLocalContext.xml"/>
<spring:bean name="retrieveFundStatementProc" class="za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc">
<spring:property name="sql" value="di_fund_statement.DI_FD_ICE_WEB_COVUS" />
<spring:property name="dataSource" ref="dataSource" />
<spring:property name="muleInit" value="" />
</spring:bean>
</spring:beans>
<flow name="main">
<composite-source>
<http:inbound-endpoint host="localhost" port="3883" path="retrieveFundStatementProc" exchange-pattern="request-response">
</http:inbound-endpoint>
<vm:inbound-endpoint path="retrieveFundStatementProc" exchange-pattern="request-response"/>
</composite-source>
<!-- TODO add your service component here. This can also be a Spring bean using <spring-object bean="name"/> -->
<pooled-component>
<spring-object bean="retrieveFundStatementProc"/>
</pooled-component>
<vm:outbound-endpoint path="out"/>
</flow>
*Spring bean*
@Repository
public class RetrieveFundStatementProc extends StoredProcedure
{
public String execute(FundStatementParam fundStatementParam) throws Exception
{
....
}
public String execute(String contNo, String entityNo, Date fromDate, Date toDate, String reportType) throws Exception
{
.....
}
*Transformer*
@ContainsTransformerMethods
public class FundStatementProcTransformer
{
@Transformer
public FundStatementParam transform(String param)
{
return new FundStatementParam();
}
}
*Test case*
I tried passing in the FundStatementParam object and also a String to see if I can get the Transformer to execute
public void testMuleFundStatements2() throws Exception
{
MuleClient client = new MuleClient(muleContext);
Date from = new GregorianCalendar(2010, 6, 1).getTime();
Date to = new GregorianCalendar(2010, 11, 1).getTime();
FundStatementParam fundStatementParam = new FundStatementParam();
fundStatementParam.setContNo("8550000053");
fundStatementParam.setEntityNo("1031276775");
fundStatementParam.setFromDate(from);
fundStatementParam.setToDate(to);
fundStatementParam.setReportType("D");
MuleMessage result = client.send("http://localhost:3883/retrieveFundStatementProc?method=execute", "fundStatementParam", null);
*Error*
================================================================================
= Testing: testMuleFundStatements2 =
================================================================================
[11-29 16:21:48] ERROR DefaultServiceExceptionStrategy [connector.http.0.receiver.2]:
********************************************************************************
Message : Failed to find entry point for component, the following resolvers tried but failed: [
AnnotatedEntryPointResolver: Component: za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc@5b28c9 doesn't have any annotated methods, skipping.
MethodHeaderPropertyEntryPointResolver: Could not find entry point on: "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc" with arguments: "{class org.apache.commons.httpclient.ContentLengthInputStream}"
CallableEntryPointResolver: Object "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc@5b28c9" does not implement required interface "interface org.mule.api.lifecycle.Callable"
ReflectionEntryPointResolver: Could not find entry point on: "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc" with arguments: "{class org.apache.commons.httpclient.ContentLengthInputStream}"
]
Code : MULE_ERROR-321
--------------------------------------------------------------------------------
Exception stack is:
1. Failed to find entry point for component, the following resolvers tried but failed: [
AnnotatedEntryPointResolver: Component: za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc@5b28c9 doesn't have any annotated methods, skipping.
MethodHeaderPropertyEntryPointResolver: Could not find entry point on: "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc" with arguments: "{class org.apache.commons.httpclient.ContentLengthInputStream}"
CallableEntryPointResolver: Object "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc@5b28c9" does not implement required interface "interface org.mule.api.lifecycle.Callable"
ReflectionEntryPointResolver: Could not find entry point on: "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc" with arguments: "{class org.apache.commons.httpclient.ContentLengthInputStream}"
] (org.mule.model.resolvers.EntryPointNotFoundException)
org.mule.model.resolvers.DefaultEntryPointResolverSet:58 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/model/resolvers/EntryPointNotFoundException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
org.mule.model.resolvers.EntryPointNotFoundException: Failed to find entry point for component, the following resolvers tried but failed: [
AnnotatedEntryPointResolver: Component: za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc@5b28c9 doesn't have any annotated methods, skipping.
MethodHeaderPropertyEntryPointResolver: Could not find entry point on: "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc" with arguments: "{class org.apache.commons.httpclient.ContentLengthInputStream}"
CallableEntryPointResolver: Object "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc@5b28c9" does not implement required interface "interface org.mule.api.lifecycle.Callable"
ReflectionEntryPointResolver: Could not find entry point on: "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc" with arguments: "{class org.apache.commons.httpclient.ContentLengthInputStream}"
]
at org.mule.model.resolvers.DefaultEntryPointResolverSet.invoke(DefaultEntryPointResolverSet.java:58)
at org.mule.component.DefaultComponentLifecycleAdapter.invoke(DefaultComponentLifecycleAdapter.java:350)
at org.mule.component.AbstractJavaComponent.invokeComponentInstance(AbstractJavaComponent.java:90)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
[11-29 16:21:48] ERROR DefaultServiceExceptionStrategy [connector.http.0.receiver.2]: The Default Service Exception Strategy has been invoked but there is no current service on the context. Please report this to d...@mule.codehaus.org
Testsuite: za.co.discoveryinvest.fundstatements.mulefundstatements2.MuleFundStatements2TestCase
Tests run: 1, Failures: 1, Errors: 0, Time elapsed: 2.457 sec
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
*Changed transformer by adding a couple different method signatures*
@ContainsTransformerMethods
public class FundStatementProcTransformer
{
@Transformer
public FundStatementParam transform(InputStream param)
{
System.out.println("1");
return new FundStatementParam();
}
@Transformer
public FundStatementParam transform(FundStatementParam fundStatementParam)
{
System.out.println("2");
return new FundStatementParam();
}
@Transformer
public FundStatementParam transform(String param)
{
System.out.println("3");
return new FundStatementParam();
}
@Transformer
public FundStatementParam transform(org.apache.commons.httpclient.ContentLengthInputStream param)
{
System.out.println("4");
return new FundStatementParam();
}
}
*Changed config file*
<http:inbound-endpoint host="localhost" port="3883" path="retrieveFundStatementProc" exchange-pattern="request-response">
<response>
<object-to-string-transformer/>
</response>
</http:inbound-endpoint>
*Tried calling with my param object* *and with string*
MuleMessage result = client.send("http://localhost:3883/retrieveFundStatementProc?method=execute", fundStatementParam, null);
result = client.send("http://localhost:3883/retrieveFundStatementProc?method=execute", "fundStatementParam", null);
*Still same error*
Root Exception stack trace:
org.mule.model.resolvers.EntryPointNotFoundException: Failed to find entry point for component, the following resolvers tried but failed: [
AnnotatedEntryPointResolver: Component: za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc@9b59a2 doesn't have any annotated methods, skipping.
MethodHeaderPropertyEntryPointResolver: Could not find entry point on: "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc" with arguments: "{class org.apache.commons.httpclient.ContentLengthInputStream}"
CallableEntryPointResolver: Object "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc@9b59a2" does not implement required interface "interface org.mule.api.lifecycle.Callable"
ReflectionEntryPointResolver: Could not find entry point on: "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc" with arguments: "{class org.apache.commons.httpclient.ContentLengthInputStream}"
]
When I debug the transformer doesn't get executed so Mule can't seem to find the transformer. It is in the same directory as my test case. I also tried to add it in the sources directory of my project and that also didn't work.
When I debug the transformer doesn't get executed so Mule can't seem to find the transformer. It is in the same directory as my test case. I also tried to add it in the sources directory of my project and that also didn't work.
================================================================================
= Testing: testMuleFundStatements2 =
================================================================================
[11-30 08:13:21] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:13:21] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:13:21] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:13:22] WARN Configuration [main]: The notification listener subscription "ListenerSubscriptionPair [listener=FundStatementProcTransformer{this=8f3eac, name='FundStatementProcTransformer', ignoreBadInput=false, returnClass=SimpleDataType{type=java.lang.Object, mimeType='*/*'}, sourceTypes=[]}, subscription=NULL]" has already been registered
[11-30 08:13:22] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:13:22] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:13:22] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:13:22] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
<custom-transformer name="FundStatementProcTransformer" class="za.co.discoveryinvest.fundstatements.mulefundstatements2.FundStatementProcTransformer"/>
<flow name="main">
<composite-source>
<http:inbound-endpoint host="localhost" port="3883" path="retrieveFundStatementProc" exchange-pattern="request-response">
<response>
<transformer ref="FundStatementProcTransformer"/>
</response>
</http:inbound-endpoint>
<vm:inbound-endpoint path="retrieveFundStatementProc" exchange-pattern="request-response"/>
</composite-source>
<!-- TODO add your service component here. This can also be a Spring bean using <spring-object bean="name"/> -->
<pooled-component>
<spring-object bean="retrieveFundStatementProc"/>
</pooled-component>
<vm:outbound-endpoint path="out"/>
</flow>
When I debug this error actually comes up before the transform. I most likely need to change the config file to execute the transformer before the method is invoked
[11-30 08:15:13] ERROR DefaultServiceExceptionStrategy [connector.http.0.receiver.2]:
********************************************************************************
Message : Failed to find entry point for component, the following resolvers tried but failed: [
AnnotatedEntryPointResolver: Component: za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc@12eda6f doesn't have any annotated methods, skipping.
MethodHeaderPropertyEntryPointResolver: Could not find entry point on: "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc" with arguments: "{class org.apache.commons.httpclient.ContentLengthInputStream}"
CallableEntryPointResolver: Object "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc@12eda6f" does not implement required interface "interface org.mule.api.lifecycle.Callable"
ReflectionEntryPointResolver: Could not find entry point on: "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc" with arguments: "{class org.apache.commons.httpclient.ContentLengthInputStream}"
]
Code : MULE_ERROR-321
<flow name="main">
<composite-source>
<http:inbound-endpoint transformer-refs="FundStatementProcTransformer" host="localhost" port="3883" path="retrieveFundStatementProc" exchange-pattern="request-response">
</http:inbound-endpoint>
Do you have an example of how to get data out of the object that is sent to the doTransform method?
protected FundStatementParam doTransform(Object src, String enc) throws TransformerException
{
System.out.println("5");
return new FundStatementParam();
}
Also what can I do about all these warnings?
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN Configuration [main]: The notification listener subscription "ListenerSubscriptionPair [listener=FundStatementProcTransformer{this=24c22b, name='FundStatementProcTransformer', ignoreBadInput=false, returnClass=SimpleDataType{type=java.lang.Object, mimeType='*/*'}, sourceTypes=[]}, subscription=NULL]" has already been registered
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
[11-30 08:21:20] WARN TransientRegistry [main]: TransientRegistry already contains an object named 'FundStatementProcTransformer.transform'. The previous object will be overwritten.
First let me ask, is this call correct?
MuleMessage result = client.send("http://localhost:3883/retrieveFundStatementProc?method=execute", fundStatementParam, null, 0);
I am passing in the param object. Should I actually rather pass in XML? I thought any data type can be passed into Mule and only transformed to what you want when your method executes
Why should I add a transformer if I already pass in a fundStatementParam? Shouldn't it execute the method on the Spring bean that has that object as a param? I even tell it which method to execute, the "execute" method.
I am also just getting started again with Mule after not using it for many years. In my project, everything is being written from scratch, and the param objects that are issued by a client are directly accepted and responded to by the destination component. It even runs in the same VM for the early stages, and arguably there is no need for Mule at all. But because there is very little overhead (no serialization losses when using the VM transport), it makes sense to enforce the patterns that will be needed in the very near future as the project starts integrating against disparate data sources and vendor platforms. That is the point that transformers will start to provide returns on the investment to write and maintain them.
Nobody knows your requirements as well as you do, and it sounds like you have the right questions in mind to get a good design.
Cheers, Brian
The main.java has the MuleClient testing code
MuleServerStartup.txt is the console info after starting the server with my app deployed
MuleClientStartup.txt is the info after running the client
MuleExecuteError.txt is the info on the console of the server after my client tries to execute the service
We are back to the server not being able to see the correct method
I am attaching my mule-config.xml that is deployed to the server
> I am thinking what is actually happening is I am mixing the concepts. I am trying to use old code, but not write the wrappers around the old code. Seems if you want to use the old code you don't have a choice, you need to write the transformers or wrappers that implement certain interfaces
That's correct. The transformers are there to do the work required so that the entry point resolver in use can find the right component method.
To illustrate, you *could* write a new entry point resolver that did things far differently than Mule does today, but that would make your code harder to work with by people that are familiar with Mule already. Instead, using a transformer to adapt your message to be compatible with one of the standard entry point resolvers is the preferred way to go.
Excepting that there are best practices and patterns outlined in the EIP book, all you really need to worry about is that the correct method is executed on the destination component and the caller is properly indicated, right? :-)
I thought I read that Mule doesn't transform the object you pass into Mule, nly when you decide to transform it does it change the object, but from what I see Mule is actually changing my parameter object to this ContentLengthInputStream and then trying to find a method that has that as a parameter. There is probably no way around that, but what Mule should actually do then is try to look for a method that has the original class that I passed in as a parameter rather than looking for this ContentLengthInputStream class
I looked at the stream and I will have to read the bytes out of it and try to reconstruct the object that I passed in. That can't be right.
Also it seems the annotations of Mule doesn't execute at all and it also doesn't seem to execute the @PostConstruct annotation. That is a problem, because I am developing my services with annotations and if Mule isn't going to execute my annotations it means my old services can't be used with Mule, I will have to develop new services specific to Mule for Mule
I see Mule is trying to find a method that has a parameter of type org.apache.commons.httpclient.ContentLengthInputStream when I execute the HTTP method, but it works fine using the VM method. Shouldn't Mule perform the same no matter what delivery method you choose? If it changes how it works for every type of delivery it is going to take alot of testing everytime you want to add a type of delivery
I thought I read that Mule doesn't transform the object you pass into Mule, only when you decide to transform it does it change the object, but from what I see Mule is actually changing my parameter object to this ContentLengthInputStream and then trying to find a method that has that as a parameter. There is probably no way around that, but what Mule should actually do then is try to look for a method that has the original class that I passed in as a parameter rather than looking for this ContentLengthInputStream class
I looked at the stream and I will have to read the bytes out of it and try to reconstruct the object that I passed in. That can't be right.
Also it seems the annotations of Mule doesn't execute at all and it also doesn't seem to execute the @PostConstruct annotation. That is a problem, because I am developing my services with annotations and if Mule isn't going to execute my annotations it means my old services can't be used with Mule, I will have to develop new services specific to Mule for Mule
*Calling my Spring bean* *using the VM method*
MuleClient client = new MuleClient(muleContext);Object[] args = new Object[]{"8550000053", "1031276775", from, to, "D"};
MuleMessage result = client.send("vm://retrieveFundStatementProc", args, null);
I pass in an array of objects to the method. The method "execute" is executed on RetrieveFundStatementProc Spring bean. I will log a JIRA about the @PostConstruct not getting executed, but that is another story. I am attaching the proc class. The vm:inbound-endpoint doesn't have a transformer associated (<vm:inbound-endpoint path="retrieveFundStatementProc" exchange-pattern="request-response"/>
)
*Calling my Spring bean using the HTTP method*
MuleClient client = new MuleClient(muleContext);Object[] args = new Object[]{"8550000053", "1031276775", from, to, "D"};
MuleMessage result = client.send("http://localhost:3883/retrieveFundStatementProc?method=execute", args, null);
Everything is exactly the same, but Mule says it can't find the execute method, because it is now looking for an execute method that has a parameter of org.apache.commons.httpclient.ContentLengthInputStreamThis is the definition of the end point
<http:inbound-endpoint
host="localhost" port="3883"
path="retrieveFundStatementProc"
exchange-pattern="request-response">
</http:inbound-endpoint>
I am including the config file also as an attachment
What I would have assumed is that Mule would act exactly the same no matter what method I choose to execute my code with, but it seems I need to do something specific when executing the code using the HTTP method. What would you suggest would be the best way for me to go forward? I don't know if I am using the mule client correctly when trying to execute my method using HTTP. I attached the whole testing project. Please only look at the test directory, because I only ran the test case
*This is the error message*
Message : Failed to find entry point for component, the following resolvers tried but failed: [
AnnotatedEntryPointResolver: Component: za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc@1ef3a22 doesn't have any annotated methods, skipping.
MethodHeaderPropertyEntryPointResolver: Could not find entry point on: "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc" with arguments: "{class org.apache.commons.httpclient.ContentLengthInputStream}"
CallableEntryPointResolver: Object "za.co.discoveryinvest.dataaccess.notificationcontrol.RetrieveFundStatementProc@1ef3a22" does not implement required interface "interface org.mule.api.lifecycle.Callable"
I have returned :)
*Calling my Spring bean using the HTTP method*
MuleClient client = new MuleClient(muleContext);Object[] args = new Object[]{"8550000053", "1031276775", from, to, "D"};
MuleMessage result = client.send("http://localhost:3883/retrieveFundStatementProc?method=execute", args, null);
Everything is exactly the same, but Mule says it can't find the execute method, because it is now looking for an execute method that has a parameter of org.apache.commons.httpclient.ContentLengthInputStream
What kind of transformer will I need if I use JSON or XML annotations in my parameter objects?
What are "Mule specific serialization attributes"?
What kind of transformer will I need if I use JSON or XML annotations in my parameter objects?
What are "Mule specific serialization attributes"?