org.eclipse.microprofile.lra.annotation.Compensate Maven / Gradle / Ivy
Show all versions of microprofile-lra-api Show documentation
/*
*******************************************************************************
* Copyright (c) 2018-2021 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.eclipse.microprofile.lra.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.eclipse.microprofile.lra.annotation.ws.rs.LRA;
/**
*
* If a resource method executes in the context of an LRA and if the containing class has a method annotated with
* @Compensate
then this method will be invoked if the LRA is cancelled. The resource should attempt to
* compensate for any actions it performed in the context of the LRA. If the annotation is present on more than one
* method then an arbitrary one will be chosen. The LRA specification makes no guarantees about when Compensate method
* will be invoked, just that it will eventually be called.
*
*
*
* In the case where the ability to compensate the Long Running Action is time bounded, you can limit the lifespan of
* the Long Running action by providing values for the {@link LRA#timeLimit()} and {@link LRA#timeUnit()} attributes.
* When the time limit is reached the LRA becomes eligible for automatic cancellation.
*
*
*
* If the annotation is applied to a JAX-RS resource method then the request method MUST be {@link jakarta.ws.rs.PUT}.
* The LRA context of the currently running LRA can be obtained by inspecting the incoming JAX-RS headers. If this LRA
* is nested then the parent LRA MUST be present in the header with the name {@link LRA#LRA_HTTP_PARENT_CONTEXT_HEADER}
* and the header value will be of type {@link java.net.URI}.
*
*
*
* If the annotated method is not a JAX-RS resource method then the LRA context of the currently running LRA and its
* parent LRA (if it is nested) can be obtained by adhering to predefined method signatures as defined in the LRA
* specification document. For example,
*
*
*
*
* @Compensate
* public void compensate(URI lraId, URI parentId) { ...}
*
*
*
*
* would be a valid compensation method declaration. If an invalid signature is detected, the implementation of this
* specification MUST prohibit successful startup of the application (e.g. with a runtime exception).
*
*
*
* If the participant cannot compensate immediately then it must report that the compensation request was received and
* that the compensation is in progress by either returning a future (such as
* {@link java.util.concurrent.CompletionStage}) which will eventually report one of the final states, or a
* 202 Accepted
JAX-RS response code or, in the case of non JAX-RS resource methods, by returning
* {@link ParticipantStatus#Compensating} (see the specification document for more details).
*
*
*
* Note that according to the state model defined by {@link LRAStatus}, it is not possible to receive compensation
* notifications after an LRA has been asked to cancel. Therefore combining this annotation with an
* @LRA
annotation that does not start a new LRA will result in a 412 PreCondition Failed
* JAX-RS response code. On the other hand, combining it with an @LRA
annotation that begins a new LRA
* can in certain use cases make sense, but in this case, the LRA that this method is being asked to compensate for will
* be unavailable.
*
*
*
* If the method is a JAX-RS resource method (or is a non JAX-RS method annotated with @Compensate
with
* return type jakarta.ws.rs.core.Response
) then the following are the only valid response codes:
*
*
*
* JAX-RS Compensation Response Codes
*
* Code
* Response Body
* Meaning
*
*
* 200
* Empty
* The resource has successfully compensated
*
*
* 202
* Empty
* The resource is still attempting compensation
*
*
* 409
* {@link ParticipantStatus} enum value
*
*
* The resource has failed to compensate. The payload contains the reason for the failure. A participant MUST remember
* this state until its {@link Forget} method is called.
*
*
* The actual value is not important but it MUST correspond to a valid {@link ParticipantStatus} enum value. For
* example, if compensation was not possible because the resource already completed (without being asked to) then a
* value such as {@link ParticipantStatus#Completed} would be appropriate or if it was due to a generic failure then
* {@link ParticipantStatus#FailedToCompensate} would be valid.
*
*
* Note that the actual state as reported by the {@link Status} method MUST be
* {@link ParticipantStatus#FailedToCompensate}
*
*
*
*
* 410
* Empty
* The resource does not know about the LRA
*
*
*
*
* The implementation will handle the return code 410 in the same way as the return code 200. Specifically, when the
* implementation calls the Compensate method as a result of the LRA being cancelled and the participant returns the
* code 410, the implementation assumes that the action is compensated and the participant returned a 410 since
* participant is allowed to forget about an action which is completely handled by the participant.
*
*
*
* If any other code is returned (or, in the 409 case, the body does not correspond to a valid state) then the
* implementation SHOULD either keep retrying or attempt to discover the status by calling the {@link Status} method if
* present or a combination of both. If the implementation stops retrying then it SHOULD log a warning. An example
* scenario where the implementation might attempt to invoke the compensate method twice and the status method is as
* follows:
*
*
*
* - The implementation invokes the compensate method via JAX-RS.
* - The JAX-RS server returns a 500 code (i.e., the notification does not reach the participant).
* - If there is a status method then the implementation uses that to get the current state of the participant. If the
* status is Active then the implementation may infer that the original request never reached the participant so it is
* safe to reinvoke the compensate method.
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Compensate {
}