[mule-user] Beginner. Please help

7 views
Skip to first unread message

Kobus du Toit

unread,
Nov 29, 2010, 9:31:02 AM11/29/10
to us...@mule.codehaus.org
Hi

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


David Dossot

unread,
Nov 29, 2010, 11:36:27 AM11/29/10
to us...@mule.codehaus.org
Hi, 

You are right that modifying your existing Spring beans is not the way to go: Mule's philosophy is about allowing you to re-use your POJOs.

To achieve this, you can either:
  • add an object-to-string-transformer in the response phase of your inbound HTTP endpoint,
  • add another transform method that takes a java.io.InputStream on FundStatementProcTransformer
This will help ensuring a FundStatementParam object gets build before calling your POJO execute method.

HTH
D.

Kobus du Toit

unread,
Nov 30, 2010, 12:42:19 AM11/30/10
to us...@mule.codehaus.org
I tried the following

*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*
&lt;http:inbound-endpoint host="localhost" port="3883" path="retrieveFundStatementProc" exchange-pattern="request-response"&gt;
&lt;response&gt;
&lt;object-to-string-transformer/&gt;
&lt;/response&gt;
&lt;/http:inbound-endpoint&gt;


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

David Dossot

unread,
Nov 30, 2010, 12:53:05 AM11/30/10
to us...@mule.codehaus.org
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.

Clearly, the transformer should be in the source directory and not the test directory of your project. Do you use Mule IDE to deploy your project or Maven? Can you check the custom transformer class is correctly deployed as part of your Mule's application?

Also, I think the transformer needs to be loaded in the application context, else Mule has no way of finding it (but I may be wrong).

Can you try adding a custom-transformer element referring to your transformer class somewhere above the flow?

HTH
D.

Kobus du Toit

unread,
Nov 30, 2010, 1:06:48 AM11/30/10
to us...@mule.codehaus.org
I created a maven project and running in Netbeans so not deploying to the Mule server. I will try adding the custom transformer in the config file. How do I add it to the mule context? With spring there is a scan tag in the config file, but I don't see anything for Mule to tell it to scan the classpath

David Dossot

unread,
Nov 30, 2010, 1:10:23 AM11/30/10
to us...@mule.codehaus.org
That's why I think you need to either declare it with a custom-transformer element or as a Spring bean. I think both approach would allow Mule to discover it, though the former is clearer on the intent.

D.

Kobus du Toit

unread,
Nov 30, 2010, 1:16:23 AM11/30/10
to us...@mule.codehaus.org
I added the transformer manually, now it is executing. So seems either annotations don't work or they don't work in a test case

================================================================================
= 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

Kobus du Toit

unread,
Nov 30, 2010, 1:21:23 AM11/30/10
to us...@mule.codehaus.org
Getting close :)
I changed it so that the transformer gets executed on the endpoint. Now it does happen before the call and the call actually happens

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

Kobus du Toit

unread,
Nov 30, 2010, 1:52:55 AM11/30/10
to us...@mule.codehaus.org
I think in all the long posts my last question might have been lost

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.

Brian Topping

unread,
Nov 30, 2010, 2:19:46 AM11/30/10
to us...@mule.codehaus.org
While it is correct that you can chain a lot of transformers between your endpoint and your component to modify your param object appropriately, if you are writing the component from scratch, there's no practical reason not to just accept the param object as you are passing it without additional transformers.

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

Kobus du Toit

unread,
Nov 30, 2010, 2:48:10 AM11/30/10
to us...@mule.codehaus.org
Maybe my issues are because I am running it in a test case. What happens when you run the muleclient in a test case? Does it start a mule server? It doesn't seem to execute the mule annotations or even annotations like @PostConstruct. I will try to deploy the zip to my mule server and test then. I haven't tried to find the info on how to setup the mule client to connect to a remote server. Do you maybe have an example, if not, google will hopefully come up with something :)

Kobus du Toit

unread,
Nov 30, 2010, 4:10:03 AM11/30/10
to us...@mule.codehaus.org
I deployed my app now to the mule server and I wrote a new project with using the MuleClient

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

mule-config.xml
MuleServerStartup.txt
MuleExecuteError.txt
MuleClientStartup.txt
Main.java

Kobus du Toit

unread,
Nov 30, 2010, 7:27:33 AM11/30/10
to us...@mule.codehaus.org
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

Brian Topping

unread,
Nov 30, 2010, 11:49:57 AM11/30/10
to us...@mule.codehaus.org
On Nov 30, 2010, at 7:27 AM, Kobus du Toit wrote:

> 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? :-)

David Dossot

unread,
Nov 30, 2010, 11:50:37 AM11/30/10
to us...@mule.codehaus.org
I take it you're sub-classing FunctionalTestCase for your tests: then yes, it runs a Mule server. To have a Mule client connected to this server, simply do: new MuleClient(context).

Also, unless you use a different Mule version when running your test cases, the behavior should be the same as with running on Mule.

D.

David Dossot

unread,
Nov 30, 2010, 11:51:46 AM11/30/10
to us...@mule.codehaus.org
Transformers and entry-point resolvers should be all the "wrapping" you need for your code.

D.

Brian Topping

unread,
Nov 30, 2010, 12:13:05 PM11/30/10
to us...@mule.codehaus.org
Also note that a FunctionalTestCase is an "integration test" that is packaged in the JUnit test framework.  This can be a little confusing because the name JUnit implies to some folks that everything using it is a unit test.  It's not.  

A unit test is going to just test the little bits of the code that you need to confirm work... that when you send your component a foo as a parameter, you get a bar in return.  As long as you have tested every line of your component, there's *almost* no need to launch the mule server with FunctionalTestCase in an integration test.

The caveat is that if you are concerned that your component might not actually run in the server at all (even though you know that every line of the functionality does what it's supposed to), you must create an integration test that launches the server.  See the difference?

Clearly, both kinds of tests are necessary for a full test scenario, but far more unit tests than integration tests.  Integration tests are easier to write for the beginner, but take more time to execute during a build, something that is important in very large builds since the server might take ten seconds to launch and JUnit might take 100ms.  

Kobus du Toit

unread,
Dec 1, 2010, 1:13:26 AM12/1/10
to us...@mule.codehaus.org
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, 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

David Dossot

unread,
Dec 1, 2010, 1:46:00 AM12/1/10
to us...@mule.codehaus.org

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

Not sure exactly what you mean by that. When you do synchronous operations over a stream-capable transport, Mule uses a java.io.InputSteam (forget about the particular implementation, only the interface matters here) as the message payload. If you don't want to benefit from that, simply unify all your payloads to, say, byte[] or String with a transformer and you'll be done.
 
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

This is again very unclear. Aren't you receiving an InputStream only when you POST data to the HTTP inbound endpoint? Are you saying that when you pass a non stream payload over the VM endpoint you're also receiving an InputStream in your component?
 
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.

What do you mean by "passed in"? Do you serialize a Java object and HTTP POST it to Mule? If that's the case, for sure you need to use a deserializer on Mule side.
 
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

This is a completely different topic: if you think there is a bug with annotations support, please file a JIRA.

D.

Kobus du Toit

unread,
Dec 1, 2010, 4:26:31 AM12/1/10
to us...@mule.codehaus.org
I will post tomorrow some more detail and try to explain what I was trying to say

David Dossot

unread,
Dec 1, 2010, 10:26:28 AM12/1/10
to us...@mule.codehaus.org
Agreed, this discussion needs a good reboot :)

Kobus du Toit

unread,
Dec 2, 2010, 6:21:13 AM12/2/10
to us...@mule.codehaus.org
I have returned :)

*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 (&lt;vm:inbound-endpoint path="retrieveFundStatementProc" exchange-pattern="request-response"/&gt;
)

*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
&lt;http:inbound-endpoint


host="localhost" port="3883"
path="retrieveFundStatementProc"

exchange-pattern="request-response"&gt;
&lt;/http:inbound-endpoint&gt;
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"

MuleFundStatements2.zip
mulefundstatements2-functional-test-config.xml
RetrieveFundStatementProc.java

David Dossot

unread,
Dec 2, 2010, 1:35:36 PM12/2/10
to us...@mule.codehaus.org

I have returned :)

Me too :)

*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);

I don't think "method=execute" does anything here.

Note that this will HTTP POST a byte representation of "args", which I think will be created by using the standard Java serialization mechanism.


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

Because FundStatementResult is not annotated with a JAX-WS or JAX-RS or Mule specific serialization attributes, no particuloar deserialization strategy can be automatically picked-up.

To stick with your (reasonable) requirement not to modify FundStatementResult, you need to help Mule a little and add a transformer in your inbound HTTP endpoint to deserialize the stream into an object. A byte-array-to-object-transformer should do the trick.

Personally, I'd rather use JSON or XML as the wire-format for my serialized objects when I send them over HTTP, but default Java serialization should work just fine.

HTH
D.

Kobus du Toit

unread,
Dec 2, 2010, 4:05:02 PM12/2/10
to us...@mule.codehaus.org
Thank you. I will try tomorrow morning when I get to work

What kind of transformer will I need if I use JSON or XML annotations in my parameter objects?
What are "Mule specific serialization attributes"?

David Dossot

unread,
Dec 2, 2010, 4:41:16 PM12/2/10
to us...@mule.codehaus.org
What kind of transformer will I need if I use JSON or XML annotations in my parameter objects?

I didn't have any XML nor JSON annotations in mind and was more thinking in term of using standard transformers like object-to-xml-transformer / xml-to-object-transformer or json:object-to-json-transformer / json:json-to-object-transformer applied directly to your array of values.

 
What are "Mule specific serialization attributes"?

For ex: @Payload or @Xpath (read http://blogs.mulesoft.org/pattern-based-configuration-hello-simple-service/ for an example about using them).

D.

Kobus du Toit

unread,
Dec 3, 2010, 1:58:25 AM12/3/10
to us...@mule.codehaus.org
I will have a look at that also during next week. Thank you. My code is working now. I am very happy :)

David Dossot

unread,
Dec 3, 2010, 2:00:51 AM12/3/10
to us...@mule.codehaus.org
Cool, I'm glad to read that. I knew the solution was really close :)

D.
Reply all
Reply to author
Forward
0 new messages