use of io.narayana.sra.annotation.SRA in project narayana by jbosstm.
the class TripController method bookTrip.
/**
* The quickstart scenario is:
*
* start LRA 1
* Book hotel
* start LRA 2
* start LRA 3
* Book flight option 1
* start LRA 4
* Book flight option 2
*
* @param hotelName hotel name
* @param hotelGuests number of beds required
* @param flightSeats number of people flying
*/
@POST
@Path("/book")
@Produces(MediaType.APPLICATION_JSON)
// delayClose because we want the LRA to be associated with a booking until the user confirms the booking
@SRA(value = SRA.Type.REQUIRED, delayCommit = true)
public Response bookTrip(@HeaderParam(SRA_HTTP_HEADER) String SRAId, @QueryParam(HotelController.HOTEL_NAME_PARAM) @DefaultValue("") String hotelName, @QueryParam(HotelController.HOTEL_BEDS_PARAM) @DefaultValue("1") Integer hotelGuests, @QueryParam(FlightController.FLIGHT_NUMBER_PARAM) @DefaultValue("") String flightNumber, @QueryParam(FlightController.ALT_FLIGHT_NUMBER_PARAM) @DefaultValue("") String altFlightNumber, @QueryParam(FlightController.FLIGHT_SEATS_PARAM) @DefaultValue("1") Integer flightSeats, @QueryParam("mstimeout") @DefaultValue("500") Long timeout) throws BookingException {
Booking hotelBooking = bookHotel(hotelName, hotelGuests);
Booking flightBooking1 = bookFlight(flightNumber, flightSeats);
Booking flightBooking2 = bookFlight(altFlightNumber, flightSeats);
Booking tripBooking = new Booking(SRAId, "Trip", hotelBooking, flightBooking1, flightBooking2);
return Response.status(Response.Status.CREATED).entity(tripBooking).build();
}
use of io.narayana.sra.annotation.SRA in project narayana by jbosstm.
the class ServerSRAFilter method filter.
// // TODO figure out how to disable the filters for the coordinator (they remove the
// private boolean isCoordinator() {
// return resourceInfo.getResourceClass().getName().equals("org.jboss.narayana.rts.lra.coordinator.io.narayana.sra.demo.api.Coordinator")
// }
@Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
Method method = resourceInfo.getResourceMethod();
MultivaluedMap<String, String> headers = containerRequestContext.getHeaders();
SRA.Type type = null;
Annotation transactional = method.getDeclaredAnnotation(SRA.class);
URL lraId;
URL newLRA = null;
URL suspendedLRA = null;
URL incommingLRA = null;
String recoveryUrl = null;
boolean isLongRunning = false;
if (transactional == null)
transactional = method.getDeclaringClass().getDeclaredAnnotation(SRA.class);
if (transactional != null) {
type = ((SRA) transactional).value();
// ((Transactional) transactional).delayClose();
isLongRunning = false;
// TODO((Transactional) transactional).cancelOnFamily();
Response.Status.Family[] cancel0nFamily = { Response.Status.Family.SERVER_ERROR };
// TODO((Transactional) transactional).cancelOn();
Response.Status[] cancel0n = {};
if (cancel0nFamily.length != 0)
containerRequestContext.setProperty(CANCEL_ON_FAMILY_PROP, cancel0nFamily);
if (cancel0n.length != 0)
containerRequestContext.setProperty(CANCEL_ON_PROP, cancel0n);
}
if (type == null) {
Current.clearContext(headers);
// not transactional
return;
}
boolean enlist = true;
boolean endAnnotation = method.isAnnotationPresent(Commit.class) || method.isAnnotationPresent(Prepare.class) || method.isAnnotationPresent(OnePhaseCommit.class);
if (headers.containsKey(SRA_HTTP_HEADER))
// TODO filters for asynchronous JAX-RS motheods should not throw exceptions
incommingLRA = new URL(headers.getFirst(SRA_HTTP_HEADER));
if (endAnnotation && incommingLRA == null) {
return;
}
switch(type) {
case // a txn must be present
MANDATORY:
checkForTx(type, incommingLRA, true);
lraId = incommingLRA;
// txId is not null
resumeTransaction(incommingLRA);
break;
case // a txn must not be present
NEVER:
checkForTx(type, incommingLRA, false);
enlist = false;
lraId = null;
break;
case NOT_SUPPORTED:
// suspend any currently active transaction
// previous = AtomicAction.suspend();
enlist = false;
suspendedLRA = incommingLRA;
lraId = null;
break;
case REQUIRED:
if (incommingLRA != null) {
lraId = incommingLRA;
resumeTransaction(incommingLRA);
} else {
lraTrace(containerRequestContext, null, "ServerLRAFilter before: REQUIRED start new LRA");
newLRA = lraId = startLRA(null, method, getTimeOut(method));
}
break;
case REQUIRES_NEW:
// previous = AtomicAction.suspend();
suspendedLRA = incommingLRA;
lraTrace(containerRequestContext, suspendedLRA, "ServerLRAFilter before: REQUIRES_NEW start new LRA");
newLRA = lraId = startLRA(incommingLRA, method, getTimeOut(method));
break;
case SUPPORTS:
lraId = incommingLRA;
if (incommingLRA != null) {
resumeTransaction(incommingLRA);
}
break;
default:
lraId = incommingLRA;
}
if (lraId == null) {
lraTrace(containerRequestContext, lraId, "ServerLRAFilter before: removing header");
// the method call needs to run without a transaction
Current.clearContext(headers);
// non transactional
return;
} else {
lraTrace(containerRequestContext, lraId, "ServerLRAFilter before: adding header");
// headers.putSingle(LRA_HTTP_HEADER, lraId.toString());
}
if (isLongRunning)
newLRA = null;
// store state with the current thread. TODO for the async version use containerRequestContext.setProperty("lra", Current.peek());
// make the current LRA available to the called method
Current.updateLRAContext(lraId, headers);
if (newLRA != null)
Current.putState("newLRA", newLRA);
lraTrace(containerRequestContext, lraId, "ServerLRAFilter before: making LRA available to injected SRAClient");
// make the current LRA available to the called method
lraClient.setCurrentSRA(lraId);
// TODO make sure it is possible to do compensations inside a new LRA
if (!endAnnotation && enlist) {
// don't enlist for methods marked with Compensate, Complete or Leave
URI baseUri = containerRequestContext.getUriInfo().getBaseUri();
Map<String, String> terminateURIs = lraClient.getTerminationUris(resourceInfo.getResourceClass(), baseUri, true);
String timeLimitStr = terminateURIs.get(SRAClient.TIMELIMIT_PARAM_NAME);
long timeLimit = timeLimitStr == null ? SRAClient.DEFAULT_TIMEOUT_MILLIS : Long.valueOf(timeLimitStr);
try {
recoveryUrl = lraClient.joinSRAWithLinkHeader(lraId, timeLimit, terminateURIs.get("Link"));
} catch (IllegalSRAStateException e) {
lraTrace(containerRequestContext, lraId, "ServerLRAFilter before: aborting with " + e.getMessage());
throw e;
} catch (WebApplicationException e) {
lraTrace(containerRequestContext, lraId, "ServerLRAFilter before: aborting with " + e.getMessage());
throw new GenericSRAException(lraId, e.getResponse().getStatus(), e.getMessage(), e);
}
headers.putSingle(RTS_HTTP_RECOVERY_HEADER, recoveryUrl);
}
/* if (method.isAnnotationPresent(Leave.class)) {
// leave the LRA
String compensatorId = getCompensatorId(lraId, containerRequestContext.getUriInfo().getBaseUri());
lraTrace(containerRequestContext, lraId, "leaving LRA");
lraClient.leaveLRA(lraId, compensatorId);
// let the compensator know which lra he left by leaving the header intact
}*/
lraTrace(containerRequestContext, lraId, "ServerLRAFilter before: making LRA available as a thread local");
// FilterState.setCurrentLRA(new FilterState(lraId, newLRA, suspendedLRA, recoveryUrl));
}
Aggregations