You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Ben Pezzei <be...@gmail.com> on 2012/01/03 14:30:14 UTC

Retry-Mechanism

Hi

I am trying to use the Retry-Feature (added in 2.4.4).

Client is configured like this:

<bean id="retryStrategy" class="org.apache.cxf.clustering.RetryStrategy">
	<property name="maxNumberOfRetries" value="5"/>	
	<property name="delayBetweenRetries" value="7000"/>
</bean>

<jaxws:client id="someService"
                serviceClass="someClass">
	<jaxws:features>
        <clustering:failover>
            <clustering:strategy>
                <ref bean="retryStrategy"/>
            </clustering:strategy>
        </clustering:failover>
    </jaxws:features>
</jaxws:client>

The idea may be an automatic retry if an IOException occurs (timeout,
Connection refused
or similar).

Note, that we don't use any alternate Addresses in the Strategy (we set the
address before invocation):

BindingProvider bp = (BindingProvider) port;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
props.getEndpointAddress());

With this Setup (and if we set the address to some inaccessible url)
the retryStrategy is only invoked once
and stops after one iteration:

WARN - AbstractStaticFailoverStrategy.selectAlternateEndpoint(115) |
no alternate targets remain => giving up on failover

Since we need also some Businesslogic within the Retry-Feature (which
per se is not threadsafe), i'd like
to know, if there are other ways of doing this (Perhaps a
retryInterceptor)? If so, a short example may be highly
appreciated

regards
Ben

Re: Retry-Mechanism

Posted by sreeharsha <sr...@pearson.com>.
hi Sergey, 

I am trying to implement the failover to our rest services which take the
header content-type Multipart/formdata. 

I have noticed that when I call Invoke in ClientProxyImpl.java , the headers
are set from the OperationResourceInfo . After I implement the failover
retry strategy then when the method retryInvoke  is called then the previous
headers which has Content-type and Accept is now changed to have just Accept
and omitting the Content-Type and  hence throwing a null pointer at
org.apache.cxf.jaxrs.client.ClientProxyImpl$BodyWriter.doWriteBody(ClientProxyImpl.java:801). 

CODE SNIPPET. 

 InputStream excelInputStream  =
TestUploadFileService.class.getResourceAsStream(TEST_FILE); 
//            File spreadsheetURI = new File(url.toURI()); 
//            excelInputStream = new FileInputStream(spreadsheetURI); 

            final ContentDisposition cd = new
ContentDisposition("attachment;filename=spreadsheet.xls"); 
            final Attachment att = new Attachment("file", excelInputStream,
cd); 
            final Attachment spreadsheetType = new
Attachment("spreadsheetType", "text/plain", "SpreadJS"); 
            final List<Attachment> attachments = new
ArrayList<Attachment>(); 
            attachments.add(att); 
            attachments.add(spreadsheetType); 
            final MultipartBody multipartBody = new
MultipartBody(attachments); 
            FailoverFeature feature = new FailoverFeature(); 
            List<String> alternateAddresses = new ArrayList<String>(); 
           
alternateAddresses.add("http://localhost:8084/SpreadsheetTransformationService"); 
           
alternateAddresses.add("http://icdwdpvueweb-5:8080/SpreadsheetTransformationService"); 


            RetryStrategy strategy = new RetryStrategy(); 
            strategy.setMaxNumberOfRetries(4); 
            strategy.setAlternateAddresses(alternateAddresses); 
            strategy.setDelayBetweenRetries(5000); 
            feature.setStrategy(strategy); 
            List<Feature> features = new ArrayList<Feature>(); 
            features.add(feature); 
            List<String> prov = new ArrayList<String>(); 
            String spreadsheetTransformServiceUrl =
"http://localhost:8085/SpreadsheetTransformationService"; 

            JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean(); 
            bean.setAddress(spreadsheetTransformServiceUrl); 
            bean.setFeatures(features); 
            bean.setResourceClass(SpreadSheetTransformService.class); 
            WebClient  client1 = bean.createWebClient(); 
           
client1.back(true).path("http://localhost:8084/SpreadsheetTransformationService/import"); 
            final SpreadSheetTransformService service1 =
bean.create(SpreadSheetTransformService.class); 
            final Response response =
service1.transformToJSON(multipartBody); 
            final InputStream jsonResponse = (InputStream)
response.getEntity(); 

setRequestHeaders is the method being called in invoke to set the content
type.   

Idea regarding the retry is right but i think there is bug in forwarding the
headers from the first call to the retry alternate address on failure. 

Appreciate your help. 

Thanks, 
Sree 



--
View this message in context: http://cxf.547215.n5.nabble.com/Retry-Mechanism-tp5116890p5762229.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Retry-Mechanism

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 09/01/12 12:43, Ben Pezzei wrote:
> Hi
>
> 2012/1/4 Sergey Beryozkin<sb...@gmail.com>:
>> May be there's a bug in the FailoverTargetSelector's logic when the
>> addresses are specified like this, I looked at the code and I'm not what is
>> going on there, can you please experiment with setting this same
>> (alternative) address in the strategy bean ?
>
> Well, it looks like a bug
>
> Since, we have multiple clients, which should retry a service, the
> code looks like this:
>
>          FailoverFeature failoverFeature = new FailoverFeature();
>          RetryStrategy failoverStrategy = new RetryStrategy();
>          List<String>  alternateAddress=new ArrayList<String>();
>          alternateAddress.add(props.getEndpointAddress());
>          failoverStrategy.setAlternateAddresses(alternateAddress);
>          failoverStrategy.setMaxNumberOfRetries(5);
>          failoverStrategy.setDelayBetweenRetries(2000);
>          failoverFeature.setStrategy(failoverStrategy);
>
>          failoverFeature.initialize(client,client.getBus());
>
> where client is created by:
> 		Client client = ClientProxy.getClient(port);
> and port is the created by spring with<jaxws:client...>
>
> With this setup, the situation is like before (service is invoked twice).
> If an additional alternateAddress is added
>          alternateAddress.add(props.getEndpointAddress());
> the service is invoked 3times (1 failure, 2 retries), so it looks like
> that maxNumberOfRetries is ignored, and the list alternateAddresses
> is iterated.
>

I fixed it for 2.5.x/2.4.x & the trunk, I think it should work now for 
Endpoints (your original approach) too, but I was only able to add a 
JAX-RS test for alternate addresses; was not easy to update the 
SOAP-based test with WSDLs, but the failover feature is applied the same 
way irrespectively of the frontend, so this single test should be ok, 
give it a try please.

I think may be we should actually add a DelegatingRetryStrategy which 
would work with whatever strategy is actually used to select the 
alternate endpoints/addresses; guess can be done a bit later



> So the question remains, how to build an outFaultInterceptor which
> retries (resets the chain?), since we won't/can't upgrade to a possible
> patched cxf-release (or manually patch the sources)
>
If you can not move to the latest CXFs then consider extending 
RetryStrategy and override getNextAlternate the same way it is done on 
the trunk and set the custom strategy on the FailoverFeature

Cheers, Sergey

> tnx&  regards
> Ben


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: Retry-Mechanism

Posted by Ben Pezzei <be...@gmail.com>.
Hi

2012/1/4 Sergey Beryozkin <sb...@gmail.com>:
> May be there's a bug in the FailoverTargetSelector's logic when the
> addresses are specified like this, I looked at the code and I'm not what is
> going on there, can you please experiment with setting this same
> (alternative) address in the strategy bean ?

Well, it looks like a bug

Since, we have multiple clients, which should retry a service, the
code looks like this:

        FailoverFeature failoverFeature = new FailoverFeature();
        RetryStrategy failoverStrategy = new RetryStrategy();
        List<String> alternateAddress=new ArrayList<String>();
        alternateAddress.add(props.getEndpointAddress());
        failoverStrategy.setAlternateAddresses(alternateAddress);
        failoverStrategy.setMaxNumberOfRetries(5);
        failoverStrategy.setDelayBetweenRetries(2000);
        failoverFeature.setStrategy(failoverStrategy);

        failoverFeature.initialize(client,client.getBus());

where client is created by:
		Client client = ClientProxy.getClient(port);
and port is the created by spring with <jaxws:client...>

With this setup, the situation is like before (service is invoked twice).
If an additional alternateAddress is added
        alternateAddress.add(props.getEndpointAddress());
the service is invoked 3times (1 failure, 2 retries), so it looks like
that maxNumberOfRetries is ignored, and the list alternateAddresses
is iterated.

So the question remains, how to build an outFaultInterceptor which
retries (resets the chain?), since we won't/can't upgrade to a possible
patched cxf-release (or manually patch the sources)

tnx & regards
Ben

Re: Retry-Mechanism

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 03/01/12 13:30, Ben Pezzei wrote:
> Hi
>
> I am trying to use the Retry-Feature (added in 2.4.4).
>
> Client is configured like this:
>
> <bean id="retryStrategy" class="org.apache.cxf.clustering.RetryStrategy">
> 	<property name="maxNumberOfRetries" value="5"/>	
> 	<property name="delayBetweenRetries" value="7000"/>
> </bean>
>
> <jaxws:client id="someService"
>                  serviceClass="someClass">
> 	<jaxws:features>
>          <clustering:failover>
>              <clustering:strategy>
>                  <ref bean="retryStrategy"/>
>              </clustering:strategy>
>          </clustering:failover>
>      </jaxws:features>
> </jaxws:client>
>
> The idea may be an automatic retry if an IOException occurs (timeout,
> Connection refused
> or similar).
>
> Note, that we don't use any alternate Addresses in the Strategy (we set the
> address before invocation):
>
> BindingProvider bp = (BindingProvider) port;
> bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
> props.getEndpointAddress());
>

May be there's a bug in the FailoverTargetSelector's logic when the 
addresses are specified like this, I looked at the code and I'm not what 
is going on there, can you please experiment with setting this same 
(alternative) address in the strategy bean ?

> With this Setup (and if we set the address to some inaccessible url)
> the retryStrategy is only invoked once
> and stops after one iteration:
>
> WARN - AbstractStaticFailoverStrategy.selectAlternateEndpoint(115) |
> no alternate targets remain =>  giving up on failover
>
> Since we need also some Businesslogic within the Retry-Feature (which
> per se is not threadsafe), i'd like
> to know, if there are other ways of doing this (Perhaps a
> retryInterceptor)? If so, a short example may be highly
> appreciated
>
Cheers, Sergey

> regards
> Ben


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com