You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Raul <lu...@gmail.com> on 2012/02/02 18:52:42 UTC

ExceptionHandler in a ftp Route

I am lost again,

How can I associated an ExceptionHandler to the consumer of a FTP Route?

I am seeing the code of the method* processStrategyCommit *of the class
*GenericFileOnCompletion* and I watch that if there is a problem in the
execution of *commit()*, it is catching the exception and It's passed to
*handleException(e)*. 

I would like that all the exceptions are sending to my ErrorHandler and then
I would use a bean to control the exceptions. Is it posible?

I have used OnException, but it doesn't catch all the exception. (The
exceptions generate outside of the life of the exchage. Conection broken by
example)

I think that OnException is diferent of handlerError. Isn't it?

I have used a handlerError in my Route, but when I debug "
getExceptionHandler().handleException(newt);" there is no handlerExeption.

<bean id="myErrorHandler"
class="org.apache.camel.builder.DefaultErrorHandlerBuilder"/>  
	
<camelContext id="contextoCamel" errorHandlerRef="myErrorHandler">
    	<routeBuilder id="FTP-SWIFT" ref="escipionFtpComponente"/>  
</camelContext>

Thank you again.

--
View this message in context: http://camel.465427.n5.nabble.com/ExceptionHandler-in-a-ftp-Route-tp5451466p5451466.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: ExceptionHandler in a ftp Route

Posted by Babak Vahdat <ba...@swissonline.ch>.
Hi

In case no body else in the forum has got a better idea I propose you to log
a JIRA ticket, and if possible with a unit-test showing the problem you're
suffering from.

Babak

--
View this message in context: http://camel.465427.n5.nabble.com/ExceptionHandler-in-a-ftp-Route-tp5451466p5468895.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: ExceptionHandler in a ftp Route

Posted by Raul <lu...@gmail.com>.
Hi again babak,

I have made my own Synchronization  and I have added it at the begin of my
Process.

During the debug I could observe there were both Synchronizations:

- MySynchronization
- The Synchronization of GenericFileOnCompletion

I am using in my ftp route the option "move=.done", but to produce
Exceptions the ftp user have not authorization to move files.

All the code of myProcess is executed completely. Then it begin to process
the Synchonization of mine and next the synchronization of
GenericFileOnCompletion.

In both case, despite of the user haven't got autorization, the method
OnComplete() is executed instead of onFailure(). Perhaps it's ok because all
the code of myProcess is completed. But the processStrategy.commit() throw
an exception because it haven't autorization to "move" the file.

Actually mSynchronization is empty, only System.out.println... to confir
that the code is execute.

The important code, the code that really "move" the file continue been the
synchronization of GenericFileOnCompletion, but I don't see the way to
change the ExceptionHandler to catch the exception.

The GenericFileOnCompletion has a method to change the ExceptionHandler, 
/public void setExceptionHandler(ExceptionHandler exceptionHandler)/ but I
don't get to access to it since the exchange of myProcess. I see it in the
debug in the UnitOfWork, but I don't know get back the
GenericFileOnCompletion and change the ExceptionHandle. Perhaps isn't
possible because the methods are private and protect

I have thought make a Synchronization extending the class of
GenericFileOnCompletion because I really need is execute its code (to move,
delete, rename the file). This idea has 2 problems at least.

1) How get the parameter of this class since the myProcess. The constructor
is:

/public GenericFileOnCompletion(GenericFileEndpoint<T> endpoint,
GenericFileOperations<T> operations,
                                   GenericFile<T> file, String
absoluteFileName)/

2) I would need remove the orgininal GenericFileOnCompletion because
otherwise, both Synchronizations will try to move the file and like the
first point perhaps isn't possible.

I believe that this problem is very common. The FTP server can shutdown in
middle of the Process. problems with authorizations, problem with quotas of
disk, etc. In all this case the Process will finished ok, and the problem
will be to "move, delete or rename". And I imagine that everbody wants to
control this situations, not only writing in the log.

Thank you for all, Babak

Raúl.







--
View this message in context: http://camel.465427.n5.nabble.com/ExceptionHandler-in-a-ftp-Route-tp5451466p5467147.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: ExceptionHandler in a ftp Route

Posted by Babak Vahdat <ba...@swissonline.ch>.
Hi

>Hello again Babak,
>
>I have got to associate own custom ExceptionHandler to the Consumer of my
>FTP Route. But I continue to have problems to control
>"renaming/moving/deleting" of FTP.
>
>I have followed the code and the problem is that the ExceptionHandler of
>the Consumer is diferente of GenericFileOnCompletion.

Yeah that's the way it is right now by the existing code. There're two
different corners having ExceptionHandler injected to them:

A: On GenericFileConsumer inherited from DefaultConsumer
B: On GenericFileOnCompletion itself


>
>During the execution of FTP route is invoked the method
>*processExchange*of the class
>* GenericFileConsumer<T> *then a "OnCompletion" is added of this way:
>
>*exchange.addOnCompletion(new GenericFileOnCompletion<T>(endpoint,
>operations, target, absoluteFileName));*
>
>The exceptionHandler of this GenericFileOnCompletion is null, I belived
>that it used the exceptionHandler of the Consumer. And like you indicated
>me, if exceptionHandler is null then the LoggingExceptionHandler is used.
>
>The key is  to change the ExceptionHandler of  GenericFileOnCompletion but
>I don't know how do it.

O.K. What I tried to show you was a solution to provide a custom
ExceptionHandler for the corner A but if you want to do the same for the
corner B as well then just forget the already preexisting
GenericFileOnCompletion added by GenericFileConsumer itself. Just add
*one* more Synchronization of *yours* as well on the exchange:


   from("...")Š
     .process(new Processor() {
        public void process(Exchange exchange) throws Exception {
            Synchronization mySynchronizationImpl = ...

            exchange.addOnCompletion(myOnCompletion);
        }).
   to("...");

And by your Synchronization react accordingly on the

   void onFailure(Exchange exchange);


callback by your mySynchronizationImpl.


>
>I have reread your advice and I have some doubt. First you say:
>
>" If you want to react differently on an encountered exception you can
>inject your own custom ExceptionHandler (for example into a FileConsumer)"

Yes the unit-test I already provided demonstrates this case. However it
seems this is not what you want, so as already said *add* your *own*
custom Synchronization on the inflight exchange.

>
>I think like this class uses "new" is not possible inject the my
>ExceptionHandler to the GenericFileOnCompletion. Is it?

I don't understand this question.

>
>On the other hand, you indicated me that other solution would be:
>
> "provide your own Synchronization implementation and do:
>
>exchange.addOnCompletion(MyHandler)
>
>For example from inside a Processor inside your route"
>
>In this case,  will MyHandler be a simple class that implements
>Synchonization?

Exactly, see the sample route above.

>
>How  can I control with MyHandler the Exceptions of the "other"
>addOnCompletion? I mean, the Exceptions don't control of the "other"
>addOnCompletion are the problems during the "renaming/moving/deleting"

Don't worry about other preexisting attached Synchronizations on the
exchange object, just concentrate on your *own* implementation. For
example when there's a failure event then Synchronization.onFailure
() method of *all* attached Synchronizations on exchange get a callback
one after the other and each can react on the failure the way they want.
See UnitOfWorkHelper.doneSynchronizations().

Last but not least by no means what I'm explaining here should be
understood as the best way to solve your problem and maybe others on the
forum have got a better idea for your use case.

Babak

>
>Thank you again.
>
>
>--
>View this message in context:
>http://camel.465427.n5.nabble.com/ExceptionHandler-in-a-ftp-Route-tp545146
>6p5463890.html
>Sent from the Camel - Users mailing list archive at Nabble.com.



Re: ExceptionHandler in a ftp Route

Posted by Raul <lu...@gmail.com>.
Hello again Babak,

I have got to associate own custom ExceptionHandler to the Consumer of my
FTP Route. But I continue to have problems to control
"renaming/moving/deleting" of FTP.

I have followed the code and the problem is that the ExceptionHandler of
the Consumer is diferente of GenericFileOnCompletion.

During the execution of FTP route is invoked the method
*processExchange*of the class
* GenericFileConsumer<T> *then a "OnCompletion" is added of this way:

*exchange.addOnCompletion(new GenericFileOnCompletion<T>(endpoint,
operations, target, absoluteFileName));*

The exceptionHandler of this GenericFileOnCompletion is null, I belived
that it used the exceptionHandler of the Consumer. And like you indicated
me, if exceptionHandler is null then the LoggingExceptionHandler is used.

The key is  to change the ExceptionHandler of  GenericFileOnCompletion but
I don't know how do it.

I have reread your advice and I have some doubt. First you say:

" If you want to react differently on an encountered exception you can
inject your own custom ExceptionHandler (for example into a FileConsumer)"

I think like this class uses "new" is not possible inject the my
ExceptionHandler to the GenericFileOnCompletion. Is it?

On the other hand, you indicated me that other solution would be:

 "provide your own Synchronization implementation and do:

exchange.addOnCompletion(MyHandler)

For example from inside a Processor inside your route"

In this case,  will MyHandler be a simple class that implements
Synchonization?

How  can I control with MyHandler the Exceptions of the "other"
addOnCompletion? I mean, the Exceptions don't control of the "other"
addOnCompletion are the problems during the "renaming/moving/deleting"

Thank you again.


--
View this message in context: http://camel.465427.n5.nabble.com/ExceptionHandler-in-a-ftp-Route-tp5451466p5463890.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: ExceptionHandler in a ftp Route

Posted by Babak Vahdat <ba...@swissonline.ch>.
Hi

The following unit-test should demonstrate how to do it in Java (doing the
same in Spring-XML should be also straight forward):

Babak

import java.util.HashMap;
import java.util.Map;

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.spi.ExceptionHandler;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;

public class CustomExceptionHandlerTest extends CamelTestSupport {

    @Test
    public void useOfCustomizedExceptionHandler() throws Exception {
        FtpComponent component = context.getComponent("ftp",
FtpComponent.class);
        FtpEndpoint<?> endpoint = (FtpEndpoint<?>)
component.createEndpoint("ftp://inbox?noop=true");

        ExceptionHandler myExceptionHandler = new MyExceptionHandler();
        Map<String, Object> consumerProperties = new HashMap<String,
Object>();
        consumerProperties.put("exceptionHandler", myExceptionHandler);
        endpoint.setConsumerProperties(consumerProperties);

        // verify that our own propriety ExceptionHandler has been setup as
expected ...
        RemoteFileConsumer<?> consumer = endpoint.createConsumer(new
Processor() {

            @Override
            public void process(Exchange exchange) throws Exception {
                // noop
            }
        });

        assertSame(consumer.getExceptionHandler(), myExceptionHandler);
    }

    private static class MyExceptionHandler implements ExceptionHandler {

        @Override
        public void handleException(String message, Exchange exchange,
Throwable exception) {
            throw new RuntimeCamelException(message, exception);
        }

        @Override
        public void handleException(String message, Throwable exception) {
            handleException(message, null, exception);
        }

        @Override
        public void handleException(Throwable exception) {
            handleException(null, null, exception);
        }

    }

}


--
View this message in context: http://camel.465427.n5.nabble.com/ExceptionHandler-in-a-ftp-Route-tp5451466p5460365.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: ExceptionHandler in a ftp Route

Posted by Raul <lu...@gmail.com>.
Hi Babak,

Could you say me how inject my own custom ExceptionHandler to the Consumer
of my FTP Route?

I am using Spring to define my Route

<camelContext id="myCamelContext"
xmlns="http://camel.apache.org/schema/spring">
    	<routeBuilder id="myFTPRoute" ref="FtpRute"/>  
</camelContext>

FtpRoute is a class that extends RouteBuilder.

I would be very grateful.



--
View this message in context: http://camel.465427.n5.nabble.com/ExceptionHandler-in-a-ftp-Route-tp5451466p5459947.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: ExceptionHandler in a ftp Route

Posted by Raul <lu...@gmail.com>.
Hello Babak,

I have read your thread [2] and the problem of "renaming/moving/deleting" is
of mine.

I believe that it's posible control a ftp route with 3 elements:

I will use an example

//Exception control
onException(Exception.class).bean(myErrorControl).handled(true).to("mock:error");

// FTP Route.
from(ftp:server/path?....&processStrategy=#myProcessStrategy&PollStrategy=#myPollStrategy).bean(myProcess);

1) *On Exception*:  With this route we can control all the exception during
the life of the Exchange. So, all  exceptions don't control in the bean
myProcess. (by example one division by 0)

2)* PollStrategy*: With this class we can control the problem during the
poll. By example the server is shutdown.

3) *ProcessStrategy*: With this class we can control the problem like
""renaming/moving/deleting". But it isn't easy make this class (at least for
me) with a clear code. I am using the code of *FtpProcessStrategyFactory*
for my class. In my example only control "move" operation.

Below a show my example of MyProcessEstrategy. The method most important is
*prepareOnStartup*.  The code in this method is necesary to actually the
files are moved.

I wouldn't need this class if I could change the  LoggingExceptionHandler (I
don't know nothing about the log) Is it possible indicate to 
LoggingExceptionHandler that use one class indicated for me to control the
Exception?

Perhaps, another option would be use your advice
"exchange.addOnCompletion(MyHandler)". I will try. But I like I am using all
component by default. The default code will be executed 
" exchange.addOnCompletion(new GenericFileOnCompletion<T>(endpoint,
operations, target, absoluteFileName));" won't it? Then I will have 2
OnCompletion. One by default and another in myProcess

The ideal would be can indicate the ExceptionHandler in the uri like
processStrategy or pollStrategy.

My idea is control the route with these 3 elements, but I will prefer don't
use ProcessStrategy.

If I have understand well your thread [2], as you might have appreciated, my
english isn't the best ,  you will could use a similar scenary

I've recently worked with camel and I can be talking nonsense or
complicating the code more than necessary.


public class MyProcessEstrategia <FTPFile> extends
		*GenericFileRenameProcessStrategy*<FTPFile> {

	public EscipionProcessEstrategia() {
    }
	
	@Override
	public boolean begin(GenericFileOperations<FTPFile> operations,
			GenericFileEndpoint<FTPFile> endpoint, Exchange exchange,
			GenericFile<FTPFile> file) throws Exception {
		// TODO Auto-generated method stub
		boolean retorno= true;
		
		System.out.println("****** BEGIN PROCESS ESTRATEGIA ***********");
		try {
			retorno =super.begin(operations, endpoint, exchange, file);
		}catch (Exception e){
			System.out.println("Process Estrategia Begin:"+ e.getCause());
			System.out.println("Process Estrategia Begin:"+ e.getMessage());
		}
		return retorno;
	}

	
	@Override
	public void rollback(GenericFileOperations<FTPFile> operations,
			GenericFileEndpoint<FTPFile> endpoint, Exchange exchange,
			GenericFile<FTPFile> file) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("****** ROLLBACK PROCESS ESTRATEGIA ***********");
		try {
			super.rollback(operations, endpoint, exchange, file);
		}catch (Exception e){
			System.out.println("Process Estrategia RollBack:"+ e.getCause());
			System.out.println("Process Estrategia RollBack:"+ e.getMessage());
			System.out.println("Process Estrategia RollBack:"+
file.getAbsoluteFilePath()+file.getFileName());
		}
	}
	
	@Override
	public void commit(GenericFileOperations<FTPFile> operations,
			GenericFileEndpoint<FTPFile> endpoint, Exchange exchange,
			GenericFile<FTPFile> file) throws Exception {
		// TODO Auto-generated method stub
		
		System.out.println("****** COMMIT PROCESS ESTRATEGIA ***********");
				
		try {
			super.commit(operations, endpoint, exchange, file);
		}catch (Exception e){
			System.out.println("Process Estrategia Commit:"+ e.getCause());
			System.out.println("Process Estrategia Commit:"+ e.getMessage());
			System.out.println("Process Estrategia Commit:"+
file.getAbsoluteFilePath()+file.getFileName());
		}
		
		
	}
	@Override
	public void prepareOnStartup(GenericFileOperations<FTPFile> operations,
			GenericFileEndpoint<FTPFile> endpoint) throws Exception {
		// TODO Auto-generated method stub
	
		try {
			super.prepareOnStartup(operations, endpoint);
		
			//Necesario para que se muevan ("renombren") los ficheros.
			Expression moveExpression=    new
SimpleExpression("${file:parent}/.done/${file:onlyname}");
			GenericFileExpressionRenamer<FTPFile> renamer = new
GenericFileExpressionRenamer<FTPFile>();
		    renamer.setExpression(moveExpression);
	        setCommitRenamer(renamer);	
			
			
		}catch (Exception e){
			System.out.println("Process Estrategia prepareOnStartup :"+
e.getCause());
			System.out.println("Process Estrategia prepareOnStartup:"+
e.getMessage());
		}
		
		
		
	}
	
}

Thank you.


--
View this message in context: http://camel.465427.n5.nabble.com/ExceptionHandler-in-a-ftp-Route-tp5451466p5453941.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: ExceptionHandler in a ftp Route

Posted by Babak Vahdat <ba...@swissonline.ch>.
Hi

errorHandlerRef gets invoked when the routing of a given exchange fails,
however the ExceptionHandler on GenericFileOnCompletion handles exceptions
encountered *specific* to the file component and it's derivatives.

The default ExceptionHandler Impl is LoggingExceptionHandler which on it's
turn *only* logs the exception & continues, that's it! If you want to react
differently on an encountered exception you can inject your own custom
ExceptionHandler (for example into a FileConsumer). The other option is to
provide your own Synchronization [1] implementation and do:

exchange.addOnCompletion(MyHandler)

For example from inside a Processor inside your route.

BTW just in case of your interest there's another thread [2] about this I
started while ago however without any answer :-)

[1]
https://svn.apache.org/repos/asf/camel/trunk/camel-core/src/main/java/org/apache/camel/spi/Synchronization.java
[2]
http://camel.465427.n5.nabble.com/Does-the-FileConsumer-swallow-an-exception-by-just-only-logging-it-td5054954.html

Babak  

--
View this message in context: http://camel.465427.n5.nabble.com/ExceptionHandler-in-a-ftp-Route-tp5451466p5451941.html
Sent from the Camel - Users mailing list archive at Nabble.com.