├── .editorconfig ├── .github └── ISSUE_TEMPLATE │ └── 01-compatible-certification-request.md ├── .gitignore ├── .mvn └── wrapper │ └── maven-wrapper.properties ├── CONTRIBUTING.adoc ├── LICENSE ├── NOTICE ├── README.adoc ├── api ├── NOTICE ├── bnd.bnd ├── pom.xml └── src │ └── main │ ├── java │ └── org │ │ └── eclipse │ │ └── microprofile │ │ └── lra │ │ ├── LRAResponse.java │ │ ├── annotation │ │ ├── AfterLRA.java │ │ ├── Compensate.java │ │ ├── Complete.java │ │ ├── Forget.java │ │ ├── LRAStatus.java │ │ ├── ParticipantStatus.java │ │ ├── Status.java │ │ └── ws │ │ │ └── rs │ │ │ ├── LRA.java │ │ │ └── Leave.java │ │ └── package-info.java │ └── resources │ └── META-INF │ ├── LICENSE │ └── NOTICE ├── mvnw ├── mvnw.cmd ├── pom.xml ├── spec ├── NOTICE ├── pom.xml └── src │ └── main │ ├── asciidoc │ ├── images │ │ ├── arch.png │ │ ├── lra-state-model.png │ │ ├── lra-state-model.txt │ │ ├── lra.png │ │ ├── lra.sd │ │ ├── participant-state-model.png │ │ └── participant-state-model.txt │ ├── license-alv2.asciidoc │ ├── license-efsl.asciidoc │ ├── microprofile-lra-spec.asciidoc │ └── release_notes.asciidoc │ └── resources │ └── META-INF │ ├── LICENSE │ └── NOTICE └── tck ├── README.adoc ├── pom.xml └── src └── main ├── java └── org │ └── eclipse │ └── microprofile │ └── lra │ └── tck │ ├── JaxRsActivator.java │ ├── LRAClientOps.java │ ├── LraTckConfigBean.java │ ├── TckCancelOnTests.java │ ├── TckContextTests.java │ ├── TckInvalidSignaturesTests.java │ ├── TckLRATypeTests.java │ ├── TckParticipantTests.java │ ├── TckRecoveryTests.java │ ├── TckTestBase.java │ ├── TckTests.java │ ├── TckUnknownStatusTests.java │ ├── TckUnknownTests.java │ ├── participant │ ├── activity │ │ ├── Activity.java │ │ └── ActivityStorage.java │ ├── api │ │ ├── AfterLRAListener.java │ │ ├── AfterLRAParticipant.java │ │ ├── ContextTckResource.java │ │ ├── GenericLRAException.java │ │ ├── IllegalLRAStateException.java │ │ ├── LRATypeTckInterface.java │ │ ├── LRATypeTckInterfaceResource.java │ │ ├── LRATypeTckResource.java │ │ ├── LRATypeTckSuperclass.java │ │ ├── LRATypeTckSuperclassResource.java │ │ ├── LRAUnknownResource.java │ │ ├── LRAUnknownStatusResource.java │ │ ├── LraCancelOnResource.java │ │ ├── LraResource.java │ │ ├── NoLRAResource.java │ │ ├── NonParticipatingTckResource.java │ │ ├── ParticipatingTckResource.java │ │ ├── RecoveryResource.java │ │ ├── ResourceParent.java │ │ ├── Scenario.java │ │ ├── UriMessageBodyWriter.java │ │ └── WrongHeaderException.java │ ├── invalid │ │ └── LRAResourceWithoutCompensateOrAfteRLRA.java │ └── nonjaxrs │ │ ├── InvalidAfterLRASignatureListener.java │ │ ├── InvalidArgumentTypesParticipant.java │ │ ├── InvalidReturnTypeParticipant.java │ │ ├── TooManyArgsParticipant.java │ │ └── valid │ │ ├── LongBusinessMethodParticipant.java │ │ ├── ValidLRACSParticipant.java │ │ └── ValidLRAParticipant.java │ └── service │ ├── LRAMetricAssertions.java │ ├── LRAMetricRest.java │ ├── LRAMetricService.java │ ├── LRAMetricType.java │ ├── LRATestService.java │ └── spi │ ├── LRACallbackException.java │ └── LRARecoveryService.java └── resources └── META-INF ├── LICENSE ├── NOTICE └── tck /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # http://editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | indent_style = space 9 | indent_size = 4 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | 18 | [*.asciidoc] 19 | trim_trailing_whitespace = false 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/01-compatible-certification-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Compatible Certification Request 3 | about: Start a request for a compatible certification 4 | title: 'MicroProfile LRA [Version] Compatible Certification Request' 5 | labels: 'Certification :trophy:' 6 | assignees: '' 7 | 8 | --- 9 | 10 | - [ ] Organization Name ("Organization") and, if applicable, URL:
11 | // Add here 12 | - [ ] Product Name, Version and download URL (if applicable):
13 | // Add here 14 | - [ ] Specification Name, Version and download URL:
15 | // Add here 16 | - [ ] (Optional) TCK Version, digital SHA-256 fingerprint and download URL:
17 | // Add here 18 | - [ ] Public URL of TCK Results Summary:
19 | // Add here 20 | - [ ] Any Additional Specification Certification Requirements:
21 | // Add here 22 | - [ ] Java runtime used to run the implementation:
23 | // Add here 24 | - [ ] Summary of the information for the certification environment, operating system, cloud, ...:
25 | // Add here 26 | - [ ] By checking this box I acknowledge that the Organization I represent accepts the terms of the [EFTL](https://www.eclipse.org/legal/tck.php). 27 | - [ ] By checking this box I attest that all TCK requirements have been met, including any compatibility rules. 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Maven 2 | target 3 | 4 | # Idea 5 | .idea 6 | *.iml 7 | 8 | # Eclipse 9 | .project 10 | .classpath 11 | .settings 12 | .metadata 13 | .checkstyle 14 | 15 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | wrapperVersion=3.3.2 18 | distributionType=only-script 19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.8/apache-maven-3.8.8-bin.zip 20 | -------------------------------------------------------------------------------- /CONTRIBUTING.adoc: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2019 Contributors to the Eclipse Foundation 3 | // 4 | // See the NOTICE file(s) distributed with this work for additional 5 | // information regarding copyright ownership. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // You may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | ## How to contribute 21 | 22 | Do you want to contribute to this project? Here is what you can do: 23 | 24 | * Fork the repository, make changes, then do a pull request. 25 | ** Remember to https://help.github.com/articles/signing-commits/[sign your commits] 26 | ** Make sure you have signed the https://www.eclipse.org/legal/ECA.php[Eclipse Contributor Agreement] 27 | * https://github.com/eclipse/microprofile-lra/issues[Create or fix an issue]. 28 | * https://gitter.im/eclipse/microprofile-lra[Join us on Gitter to discuss this project]. 29 | * Join our https://calendar.google.com/calendar/embed?src=gbnbc373ga40n0tvbl88nkc3r4%40group.calendar.google.com[weekly meeting] on Mondays at https://www.timeanddate.com/time/map/[10h00 GMT]. 30 | ** https://docs.google.com/document/d/1HBPiXpsXcQp9T8JeoT-IDs-EblZX1SxuTV5qjUPzwrM/edit[Minutes and Agenda]. 31 | ** https://eclipse.zoom.us/j/949859967[Meeting room]. 32 | * Join the discussions on the https://groups.google.com/forum/#!forum/microprofile[MicroProfile Google Group] 33 | * https://microprofile.io/blog/[Contribute a blog post]. 34 | 35 | Also see the https://wiki.eclipse.org/MicroProfile/ContributingGuidelines[MicroProfile Contributing Guidelines] on the https://wiki.eclipse.org/MicroProfile[Eclipse MicroProfile wiki page] 36 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | ========================================================================= 2 | == NOTICE file corresponding to section 4(d) of the Apache License, == 3 | == Version 2.0, in this case for Microprofile LRA == 4 | ========================================================================= 5 | 6 | This product includes software developed at 7 | The Apache Software Foundation (http://www.apache.org/). 8 | 9 | 10 | SPDXVersion: SPDX-2.1 11 | PackageName: Eclipse Microprofile 12 | PackageHomePage: http://www.eclipse.org/microprofile 13 | PackageLicenseDeclared: Apache-2.0 14 | 15 | PackageCopyrightText: 16 | Michael Musgrove mmusgrov@redhat.com 17 | Nicola Ferraro ni.ferraro@gmail.com 18 | Ondra Chaloupka ochaloup@redhat.com 19 | Tom Jenkinson tom.jenkinson@redhat.com 20 | Martin Stefanko mstefank@redhat.com 21 | Rudy De Busscher rdebusscher@gmail.com 22 | 23 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2019 Contributors to the Eclipse Foundation 3 | // 4 | // See the NOTICES file(s) distributed with this work for additional 5 | // information regarding copyright ownership. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | image:https://badges.gitter.im/eclipse/microprofile-lra.svg[link="https://gitter.im/eclipse/microprofile-lra?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] 20 | 21 | # Long Running Actions for MicroProfile 22 | 23 | == Introduction 24 | 25 | The specification introduces APIs for services to coordinate activities. 26 | 27 | The main thrust of the proposal introduces an API for loosely coupled 28 | services to coordinate long running activities in such a way as to 29 | guarantee a globally consistent outcome without the need to take locks 30 | on data. 31 | 32 | == Motivation 33 | 34 | In a loosely coupled service based environment there is sometimes a need 35 | for different services to provide consistency guarantees. Typical 36 | examples include: 37 | 38 | * order processing involving three services (take order, bill customer, 39 | ship product). If the shipping service finds that it is out of stock 40 | then the customer will have been billed with no prospect of receiving 41 | his item; 42 | * an airline overbooks a flight which means that the booking count and 43 | the flight capacity are inconsistent. 44 | 45 | There are various ways that systems overcome such inconsistency but it 46 | would be advantageous to provide a generic solution which handles 47 | failure conditions, maintains state for those flows that span long 48 | periods of time and ensures that remedial activities are called 49 | correctly. 50 | 51 | Traditional techniques for guaranteeing consistency in distributed 52 | environments has focused on XA transactions where locks may be held for 53 | long periods thereby introducing strong coupling between services and 54 | decreasing concurrency to unacceptable levels. Additionally, if such a 55 | transaction aborts then valuable work which may be valid will be rolled 56 | back. In view of these issues an alternative approach is desirable. 57 | 58 | Goals 59 | 60 | * support long running actions 61 | * no strong coupling between services 62 | * allow actions to finish early 63 | * allow compensating actions if a business activity is cancelled 64 | 65 | == Contributing 66 | 67 | Do you want to contribute to this project? link:CONTRIBUTING.adoc[Find out how you can help here]. 68 | 69 | == Building 70 | 71 | This project uses the Apache Maven Wrapper plugin for predictable builds and to build it type `./mvnw clean install`. To check which version of maven the project is currently using type `./mvnw -version`. 72 | -------------------------------------------------------------------------------- /api/NOTICE: -------------------------------------------------------------------------------- 1 | ========================================================================= 2 | == NOTICE file corresponding to section 4(d) of the Apache License, == 3 | == Version 2.0, in this case for Microprofile LRA == 4 | ========================================================================= 5 | 6 | This product includes software developed at 7 | The Apache Software Foundation (http://www.apache.org/). 8 | 9 | 10 | SPDXVersion: SPDX-2.1 11 | PackageName: Eclipse Microprofile 12 | PackageHomePage: http://www.eclipse.org/microprofile 13 | PackageLicenseDeclared: Apache-2.0 14 | 15 | PackageCopyrightText: 16 | Michael Musgrove mmusgrov@redhat.com 17 | Nicola Ferraro ni.ferraro@gmail.com 18 | Ondra Chaloupka ochaloup@redhat.com 19 | Tom Jenkinson tom.jenkinson@redhat.com 20 | Martin Stefanko mstefank@redhat.com 21 | Rudy De Busscher rdebusscher@gmail.com 22 | 23 | -------------------------------------------------------------------------------- /api/bnd.bnd: -------------------------------------------------------------------------------- 1 | -exportcontents: \ 2 | org.eclipse.microprofile.* 3 | Bundle-SymbolicName: org.eclipse.microprofile.lra 4 | Bundle-Name: MicroProfile LRA Bundle 5 | Bundle-License: Apache License, Version 2.0 6 | -------------------------------------------------------------------------------- /api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | 20 | 21 | 22 | org.eclipse.microprofile.lra 23 | microprofile-lra-parent 24 | 2.1-SNAPSHOT 25 | 26 | 27 | microprofile-lra-api 28 | MicroProfile LRA API 29 | Eclipse MicroProfile LRA - API 30 | 31 | 32 | 33 | jakarta.ws.rs 34 | jakarta.ws.rs-api 35 | 36 | 37 | jakarta.enterprise 38 | jakarta.enterprise.cdi-api 39 | 40 | 41 | biz.aQute.bnd 42 | biz.aQute.bnd.annotation 43 | 44 | 45 | org.osgi 46 | org.osgi.service.cdi 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /api/src/main/java/org/eclipse/microprofile/lra/LRAResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2020-2021 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | 21 | package org.eclipse.microprofile.lra; 22 | 23 | import jakarta.ws.rs.core.Response; 24 | 25 | /** 26 | * The utility class that will create the correct {@link Response} or 27 | * {@link jakarta.ws.rs.core.Response.ResponseBuilder} for the response that should be returned from the LRA JAX-RS 28 | * methods. 29 | */ 30 | public final class LRAResponse { 31 | 32 | private LRAResponse() { 33 | } 34 | 35 | public static Response compensated() { 36 | return Builder.compensated().build(); 37 | } 38 | 39 | public static Response compensated(Object entity) { 40 | return Builder.compensated(entity).build(); 41 | } 42 | 43 | public static Response compensating() { 44 | return Builder.compensating().build(); 45 | } 46 | 47 | public static Response compensating(Object entity) { 48 | return Builder.compensating(entity).build(); 49 | } 50 | 51 | public static Response failedToCompensate() { 52 | return Builder.failedToCompensate().build(); 53 | } 54 | 55 | public static Response failedToCompensate(Object entity) { 56 | return Builder.failedToCompensate(entity).build(); 57 | } 58 | 59 | public static Response completed() { 60 | return Builder.completed().build(); 61 | } 62 | 63 | public static Response completed(Object entity) { 64 | return Builder.completed(entity).build(); 65 | } 66 | 67 | public static Response completing() { 68 | return Builder.completing().build(); 69 | } 70 | 71 | public static Response completing(Object entity) { 72 | return Builder.completing(entity).build(); 73 | } 74 | 75 | public static Response failedToComplete() { 76 | return Builder.failedToComplete().build(); 77 | } 78 | 79 | public static Response failedToComplete(Object entity) { 80 | return Builder.failedToComplete(entity).build(); 81 | } 82 | 83 | public static final class Builder { 84 | public static Response.ResponseBuilder compensated() { 85 | return Response.ok(); 86 | } 87 | 88 | public static Response.ResponseBuilder compensated(Object entity) { 89 | return Response.ok(entity); 90 | } 91 | 92 | public static Response.ResponseBuilder compensating() { 93 | return Response.accepted(); 94 | } 95 | 96 | public static Response.ResponseBuilder compensating(Object entity) { 97 | return Response.accepted(entity); 98 | } 99 | 100 | public static Response.ResponseBuilder failedToCompensate() { 101 | return Response.status(Response.Status.CONFLICT); 102 | } 103 | 104 | public static Response.ResponseBuilder failedToCompensate(Object entity) { 105 | return Response.status(Response.Status.CONFLICT).entity(entity); 106 | } 107 | 108 | public static Response.ResponseBuilder completed() { 109 | return Response.ok(); 110 | } 111 | 112 | public static Response.ResponseBuilder completed(Object entity) { 113 | return Response.ok(entity); 114 | } 115 | 116 | public static Response.ResponseBuilder completing() { 117 | return Response.accepted(); 118 | } 119 | 120 | public static Response.ResponseBuilder completing(Object entity) { 121 | return Response.accepted(entity); 122 | } 123 | 124 | public static Response.ResponseBuilder failedToComplete() { 125 | return Response.status(Response.Status.CONFLICT); 126 | } 127 | 128 | public static Response.ResponseBuilder failedToComplete(Object entity) { 129 | return Response.status(Response.Status.CONFLICT).entity(entity); 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /api/src/main/java/org/eclipse/microprofile/lra/annotation/AfterLRA.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019-2021 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.annotation; 21 | 22 | import java.lang.annotation.ElementType; 23 | import java.lang.annotation.Retention; 24 | import java.lang.annotation.RetentionPolicy; 25 | import java.lang.annotation.Target; 26 | 27 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 28 | 29 | /** 30 | *

31 | * If a JAX-RS resource method is annotated with {@link LRA} and is invoked in the context of an LRA then the resource 32 | * can ask to be notified when the LRA finishes by marking one of the other methods in the class with the 33 | * @AfterLRA annotation. 34 | *

35 | * 36 | *

37 | * The listener can register interest in the final outcome of an LRA at any time up until the LRA has reached a final 38 | * state. In other words, if an LRA is closing or cancelling then listener registrations should be allowed. This is in 39 | * contrast to registering for participant callbacks which are only allowed if the LRA is active. A consequence of this 40 | * statement is that if a class is annotated with both the AfterLRA and the {@link Compensate} annotations 41 | * and the LRA has already started closing or cancelling then the {@link LRA} method invocation will fail with a 42 | * 412 Precondition Failed JAX-RS response code because the {@link Compensate} method requires LRA to be 43 | * Active. Without the {@link Compensate} method present, the after LRA listener would be registered successfully. 44 | *

45 | * 46 | *

47 | * If the AfterLRA method is also a JAX-RS resource method then it MUST use the {@link jakarta.ws.rs.PUT} 48 | * request method. In this case, the LRA context is made available to the annotated method via an HTTP header with the 49 | * name {@link LRA#LRA_HTTP_ENDED_CONTEXT_HEADER} and the final status is passed to the method as plain text 50 | * corresponding to one of the {@link LRAStatus} enum values. If this LRA was nested then the parent LRA MUST be present 51 | * in the header {@link org.eclipse.microprofile.lra.annotation.ws.rs.LRA#LRA_HTTP_PARENT_CONTEXT_HEADER} and value is 52 | * of type {@link java.net.URI}. For example: 53 | *

54 | * 55 | *
56 |  * 
57 |  *   @PUT
58 |  *   @AfterLRA
59 |  *   public Response afterEnd(@HeaderParam(LRA_HTTP_ENDED_CONTEXT_HEADER) URI lraId,
60 |  *                            @HeaderParam(LRA_HTTP_PARENT_CONTEXT_HEADER) URI parentLraId,
61 |  *                            Status status)
62 |  * 
63 |  * 
64 | * 65 | *

66 | * The implementation SHOULD keep resending the notification until it receives a 200 OK status code from 67 | * the resource method (which means that the method SHOULD be idempotent). If it stops retrying a warning message SHOULD 68 | * be logged. 69 | *

70 | * 71 | *

72 | * If the AfterLRA method is not a JAX-RS resource method then the id of the LRA and its final status can 73 | * be obtained by ensuring that the annotated method conforms to the signature: 74 | *

75 | * 76 | *
77 |  * 
78 |  *     public void onLRAEnd(URI lraId, LRAStatus status)
79 |  * 
80 |  * 
81 | * 82 | *

83 | * The return type is ignored and the method name is not significant. 84 | *

85 | */ 86 | @Retention(RetentionPolicy.RUNTIME) 87 | @Target({ElementType.METHOD}) 88 | public @interface AfterLRA { 89 | } 90 | -------------------------------------------------------------------------------- /api/src/main/java/org/eclipse/microprofile/lra/annotation/Forget.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018-2021 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | 21 | package org.eclipse.microprofile.lra.annotation; 22 | 23 | import java.lang.annotation.ElementType; 24 | import java.lang.annotation.Retention; 25 | import java.lang.annotation.RetentionPolicy; 26 | import java.lang.annotation.Target; 27 | 28 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 29 | 30 | /** 31 | *

32 | * If a participant is unable to complete or compensate immediately (i.e., it has indicated that the request has been 33 | * accepted and is in progress) or because of a failure (i.e., will never be able to finish) then it must remember the 34 | * fact (by reporting it when asked for its {@link Status}) until explicitly told that it can clean up using this 35 | * @Forget annotation. 36 | *

37 | * 38 | *

39 | * Similar remarks apply if the participant was enlisted in a nested LRA 40 | * ({@link org.eclipse.microprofile.lra.annotation.ws.rs.LRA.Type#NESTED}). Actions performed in the context of a nested 41 | * LRA must remain compensatable until the participant is explicitly told it can clean up using this 42 | * @Forget annotation. 43 | *

44 | * 45 | *

46 | * If the annotation is applied to a JAX-RS resource method then the request method MUST be 47 | * {@link jakarta.ws.rs.DELETE}. The context of the currently running LRA can be obtained by inspecting the incoming 48 | * JAX-RS headers. If this LRA is nested then the parent LRA MUST be present in the header with the name 49 | * {@link LRA#LRA_HTTP_PARENT_CONTEXT_HEADER} and value is of type {@link java.net.URI}. 50 | *

51 | * 52 | *

53 | * If the annotated method is not a JAX-RS resource method, the context of the currently running LRA can be obtained by 54 | * adhering to a predefined method signature as defined in the LRA specification document. Similarly the method may 55 | * determine whether or not it runs with a nested LRA by providing a parameter to hold the parent context. For example, 56 | *

57 | * 58 | *
 59 |  *     
 60 |  *          @Forget
 61 |  *          public void forget(URI lraId, URI parentId) { ...}
 62 |  *     
 63 |  * 
64 | * 65 | *

66 | * would be a valid forget method declaration. If an invalid signature is detected the implementation of this 67 | * specification MUST prohibit successful startup of the application (e.g. with a runtime exception). 68 | *

69 | * 70 | *

71 | * Since the participant generally needs to know the id of the LRA in order to clean up there is generally no benefit to 72 | * combining this annotation with the {@link LRA} annotation (though it is not prohibited). 73 | *

74 | * 75 | *

76 | * Related information is provided in the javadoc for the {@link Status}. 77 | *

78 | *

79 | * If the method is a JAX-RS resource method (or is a non JAX-RS method annotated with @Forget with 80 | * return type jakarta.ws.rs.core.Response) then the following are the only valid response codes: 81 | *

82 | * 83 | * 84 | * 85 | * 86 | * 87 | * 88 | * 89 | * 90 | * 91 | * 92 | * 93 | * 94 | * 95 | * 96 | * 97 | * 98 | * 99 | * 100 | *
JAX-RS Response Codes For Forget Methods 
CodeResponse BodyMeaning
200EmptyThe participant may have removed all knowledge of the LRA
410EmptyThe method does not know about the LRA
101 | * 102 | *

103 | * If any other code is returned then the implementation SHOULD keep retrying. If it stops retrying, a warning message 104 | * SHOULD be logged. 105 | *

106 | */ 107 | @Retention(RetentionPolicy.RUNTIME) 108 | @Target({ElementType.METHOD}) 109 | public @interface Forget { 110 | } 111 | -------------------------------------------------------------------------------- /api/src/main/java/org/eclipse/microprofile/lra/annotation/LRAStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018-2021 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | 21 | package org.eclipse.microprofile.lra.annotation; 22 | 23 | /** 24 | * A representation of the status of a Long Running Action according to a LRA state model: 25 | * 26 | * The initial state {@link #Active} is entered when an LRA is created. 27 | * 28 | * The state {@link #Cancelling} is entered when a request to cancel an LRA is received. The transition to end state 29 | * {@link #Cancelled} should occur when all the enlisted participants have indicated that they successfully compensated 30 | * for any actions they performed when the LRA was executing. If any participant could not, and will never be able to, 31 | * compensate then the final state of {@link #FailedToCancel} is entered. 32 | * 33 | * The state {@link #Closing} is entered when a request to close an LRA is received. The transition to end state 34 | * {@link #Closed} should occur when all the enlisted participants have indicated that they successfully completed any 35 | * actions they performed when the LRA was executing. If any participant could not, and will never be able to, complete 36 | * then the final state of {@link #FailedToClose} is entered. 37 | * 38 | * This specification expects that this enum is consumable in JAX-RS implementations passed as an entity parameter. This 39 | * means that if the JAX-RS implementation does not support enum types as entity parameters then the implementation of 40 | * this specification should provide a custom message body reader that will handle this parsing. 41 | */ 42 | public enum LRAStatus { 43 | /** 44 | * The LRA has not yet been asked to Close or Cancel 45 | */ 46 | Active, 47 | /** 48 | * The LRA is currently informing participants that they should compensate for any work they performed when the LRA 49 | * was active 50 | */ 51 | Cancelling, 52 | /** 53 | * All participants associated with the LRA have successfully compensated for any work they performed when the LRA 54 | * was active 55 | */ 56 | Cancelled, 57 | /** 58 | * One or more participants associated with the LRA were not able to compensate for the work they performed when the 59 | * LRA was active 60 | */ 61 | FailedToCancel, 62 | /** 63 | * The LRA is asking all participants to complete 64 | */ 65 | Closing, 66 | /** 67 | * The LRA successfully told all participants to complete 68 | */ 69 | Closed, 70 | /** 71 | * One or more participants associated with the LRA were not able to complete the work they performed when the LRA 72 | * was active 73 | */ 74 | FailedToClose, 75 | } 76 | -------------------------------------------------------------------------------- /api/src/main/java/org/eclipse/microprofile/lra/annotation/ParticipantStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018-2021 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | 21 | package org.eclipse.microprofile.lra.annotation; 22 | 23 | import org.eclipse.microprofile.lra.annotation.ws.rs.Leave; 24 | 25 | /** 26 | * A representation of the status of a participant according to a participant state model: 27 | * 28 | * The initial state {@link #Active} is entered when a participant is first associated with a Long Running Action. 29 | * 30 | * The state {@link #Compensating} is entered when a compensate notification is received (which indicates that the 31 | * associated LRA was cancelled). The transition to end state {@link #Compensated} should occur when the participant has 32 | * compensated for any actions it performed when the LRA was executing. If compensation is not, and will never be, 33 | * possible then the final state of {@link #FailedToCompensate} is entered and the participant cannot leave this state 34 | * until it receives a {@link Forget} notification. 35 | * 36 | * The state {@link #Completing} is entered when a complete notification is received (which indicates that the 37 | * associated LRA was closed). This state is followed by the {@link #Completed} or {@link #FailedToComplete} state 38 | * depending upon whether the participant was or was not able to tidy up. 39 | * 40 | * Note that a particant can leave this state model via the {@link Leave} annotation provided that the associated LRA is 41 | * in the state {@link LRAStatus#Active}. 42 | * 43 | * The name value of the enum should be returned by participant methods marked with the {@link Status}, 44 | * {@link Compensate} and {@link Complete} annotations. 45 | */ 46 | public enum ParticipantStatus { 47 | /** 48 | * The participant has not yet been asked to Complete or Compensate 49 | */ 50 | Active, 51 | /** 52 | * The participant is currently compensating for any work it performed 53 | */ 54 | Compensating, 55 | /** 56 | * The participant has successfully compensated for any work it performed 57 | */ 58 | Compensated, 59 | /** 60 | * The participant was not able to compensate for the work it performed (and it must remember it could not 61 | * compensate until such time that it receives a forget message ({@link Forget}) 62 | */ 63 | FailedToCompensate, 64 | /** 65 | * The participant is tidying up after being told to complete 66 | */ 67 | Completing, 68 | /** 69 | * The participant has confirmed that is has completed any tidy-up actions 70 | */ 71 | Completed, 72 | /** 73 | * The participant was unable to tidy-up 74 | */ 75 | FailedToComplete, 76 | } 77 | -------------------------------------------------------------------------------- /api/src/main/java/org/eclipse/microprofile/lra/annotation/Status.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018-2021 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | 21 | package org.eclipse.microprofile.lra.annotation; 22 | 23 | import java.lang.annotation.ElementType; 24 | import java.lang.annotation.Retention; 25 | import java.lang.annotation.RetentionPolicy; 26 | import java.lang.annotation.Target; 27 | 28 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 29 | 30 | import jakarta.ws.rs.core.Response; 31 | 32 | /** 33 | *

34 | * The LRA specification supports distributed communications amongst software components and due to the unreliable 35 | * nature of networks, messages/requests can be lost, delayed, duplicated, etc., so the implementation component 36 | * responsible for invoking {@link Compensate} and {@link Complete} annotated methods may lose track of the status of a 37 | * participant. In this case, ideally it would just resend the completion or compensation notification but if the 38 | * participant (the class that contains the Compensate and Complete annotations) does not support idempotency then it 39 | * must be able to report its status by by annotating one of the methods with this @Status annotation. 40 | * The annotated method should report the status according to one of the {@link ParticipantStatus} enum values. 41 | *

42 | * 43 | *

44 | * If the annotation is applied to a JAX-RS resource method then the request method MUST be {@link jakarta.ws.rs.GET}. 45 | * The context of the currently running LRA can be obtained by inspecting the incoming JAX-RS headers. If this LRA is 46 | * nested then the parent LRA MUST be present in the header with the name {@link LRA#LRA_HTTP_PARENT_CONTEXT_HEADER} and 47 | * value is of type {@link java.net.URI}. 48 | *

49 | * 50 | *

51 | * If the annotated method is not a JAX-RS resource method, the context of the currently running LRA can be obtained by 52 | * adhering to a predefined method signature as defined in the LRA specification document. Similarly the method may 53 | * determine whether or not it runs with a nested LRA by providing a parameter to hold the parent context. For example, 54 | *

55 | * 56 | *
 57 |  *     
 58 |  *          @Status
 59 |  *          public void status(URI lraId, URI parentId) { ...}
 60 |  *     
 61 |  * 
62 | * 63 | *

64 | * would be a valid status method declaration. If an invalid signature is detected the implementation of this 65 | * specification MUST prohibit successful startup of the application (e.g., with a runtime exception). 66 | *

67 | * 68 | *

69 | * If the participant has already responded successfully to an invocation of the {@link Compensate} or {@link Complete} 70 | * method then it may report 410 Gone HTTP status code or in case of non-JAX-RS method returning 71 | * {@link ParticipantStatus} to return null. 72 | *

73 | * 74 | *

75 | * Since the participant generally needs to know the id of the LRA in order to report its status there is generally no 76 | * benefit to combining this annotation with the @LRA annotation (though it is not prohibited). 77 | *

78 | * 79 | *

80 | * If the method is a JAX-RS resource method (or is a non JAX-RS method annotated with @Status with 81 | * return type {@link Response}) then the following are the only valid response codes: 82 | *

83 | * 84 | * 85 | * 86 | * 87 | * 88 | * 89 | * 90 | * 91 | * 92 | * 93 | * 94 | * 95 | * 96 | * 97 | * 98 | * 99 | * 100 | * 101 | * 102 | * 103 | * 104 | * 105 | * 106 | *
JAX-RS Response Codes For Status Methods 
CodeResponse BodyMeaning
200{@link ParticipantStatus} enum valueThe current status of the participant
202EmptyThe resource is attempting to determine the status and the caller should retry later
410EmptyThe method does not know about the LRA
107 | * 108 | *

109 | * The implementation will handle the return code 410 in the same way as the return code 200. Specifically, when the 110 | * implementation calls the Status method after it has called the Complete or Compensated method and received a response 111 | * which indicates that the process is in progress (with a return code 202, for example). The response code 410 which is 112 | * received when calling this Status annotated method, MUST be interpreted by the implementation that the process is 113 | * successfully completed and the participant already forgot about the LRA. 114 | *

115 | */ 116 | @Retention(RetentionPolicy.RUNTIME) 117 | @Target({ElementType.METHOD}) 118 | public @interface Status { 119 | } 120 | -------------------------------------------------------------------------------- /api/src/main/java/org/eclipse/microprofile/lra/annotation/ws/rs/Leave.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018-2021 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | 21 | package org.eclipse.microprofile.lra.annotation.ws.rs; 22 | 23 | import java.lang.annotation.ElementType; 24 | import java.lang.annotation.Retention; 25 | import java.lang.annotation.RetentionPolicy; 26 | import java.lang.annotation.Target; 27 | 28 | /** 29 | *

30 | * If a resource method is annotated with @Leave and is invoked in the context of an LRA and if the 31 | * bean class has registered a participant with that LRA then it will be removed from the LRA just before the bean 32 | * method is entered. The participant can forget about this LRA, in particular it will not be asked to complete or 33 | * compensate when the LRA is subsequently ended. Even though the method runs without an LRA context, the implementation 34 | * MUST still make the context available via a JAX-RS header and any outgoing JAX-RS invocations performed by the method 35 | * will still carry the context that the participant has just left. Therefore the business logic must be careful about 36 | * any JAX-RS invocations it makes in the body of the annotated method which may result in other resources being 37 | * enlisted with the LRA. 38 | *

39 | * 40 | *

41 | * If the resource method (or class) is also annotated with @LRA the method will execute with the 42 | * context dictated by the @LRA annotation. If this @LRA annotation results in the 43 | * creation of a new LRA then the participant will still be removed from the incoming context and will be enlisted with 44 | * the new context (and the method will execute with this new context). Note that in this case the context exposed in 45 | * the @LRA_HTTP_CONTEXT_HEADER JAX-RS header will be set to the new LRA (and not the original one), 46 | * i.e., the original context will not be available to the business logic. 47 | *

48 | * 49 | *

50 | * Also note that it is not possible to join or leave an LRA that has already been asked to cancel or close since that 51 | * would conflict with the the participant state model as defined in the LRA specification. 52 | *

53 | * 54 | *

55 | * Leaving a particular LRA has no effect on any other LRA - i.e., the same resource can be enlisted with many different 56 | * LRAs and leaving one particular LRA will not affect its participation in any of the other LRAs it has joined. 57 | *

58 | */ 59 | @Retention(RetentionPolicy.RUNTIME) 60 | @Target({ElementType.METHOD}) 61 | public @interface Leave { 62 | } 63 | -------------------------------------------------------------------------------- /api/src/main/java/org/eclipse/microprofile/lra/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | ******************************************************************************/ 20 | 21 | /** 22 | *

23 | * Microprofile LRA Support. 24 | */ 25 | 26 | @org.osgi.annotation.versioning.Version("2.0") 27 | package org.eclipse.microprofile.lra; 28 | -------------------------------------------------------------------------------- /api/src/main/resources/META-INF/NOTICE: -------------------------------------------------------------------------------- 1 | ========================================================================= 2 | == NOTICE file corresponding to section 4(d) of the Apache License, == 3 | == Version 2.0, in this case for Microprofile LRA == 4 | ========================================================================= 5 | 6 | This product includes software developed at 7 | The Apache Software Foundation (http://www.apache.org/). 8 | 9 | 10 | SPDXVersion: SPDX-2.1 11 | PackageName: Eclipse Microprofile 12 | PackageHomePage: http://www.eclipse.org/microprofile 13 | PackageLicenseDeclared: Apache-2.0 14 | 15 | PackageCopyrightText: 16 | Michael Musgrove mmusgrov@redhat.com 17 | Nicola Ferraro ni.ferraro@gmail.com 18 | Ondra Chaloupka ochaloup@redhat.com 19 | Tom Jenkinson tom.jenkinson@redhat.com 20 | Martin Stefanko mstefank@redhat.com 21 | Rudy De Busscher rdebusscher@gmail.com 22 | 23 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | 20 | 21 | org.eclipse.microprofile 22 | microprofile-parent 23 | 2.11 24 | 25 | 26 | org.eclipse.microprofile.lra 27 | microprofile-lra-parent 28 | MicroProfile Long Running Actions 29 | 2.1-SNAPSHOT 30 | Eclipse MicroProfile LRA - Parent POM 31 | pom 32 | 33 | http://microprofile.io 34 | 35 | 36 | 2018 37 | 2.10 38 | 39 | 1.1.4 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Apache License, Version 2.0 49 | https://www.apache.org/licenses/LICENSE-2.0.txt 50 | repo 51 | A business-friendly OSS license 52 | 53 | 54 | 55 | 56 | Eclipse Foundation 57 | http://www.eclipse.org/ 58 | 59 | 60 | 61 | GitHub 62 | https://github.com/eclipse/microprofile-lra/issues 63 | 64 | 65 | 66 | 67 | MicroProfile Community 68 | https://groups.google.com/forum/#!forum/microprofile 69 | 70 | 71 | 72 | 73 | scm:git:https://github.com/eclipse/microprofile-lra.git 74 | scm:git:git@github.com:eclipse/microprofile-lra.git 75 | https://github.com/eclipse/microprofile-lra 76 | HEAD 77 | 78 | 79 | 80 | 81 | 82 | biz.aQute.bnd 83 | biz.aQute.bnd.annotation 84 | 5.3.0 85 | provided 86 | 87 | 88 | org.osgi 89 | org.osgi.service.cdi 90 | 1.0.0 91 | provided 92 | 93 | 94 | 95 | org.eclipse.microprofile.lra 96 | microprofile-lra-api 97 | ${project.version} 98 | provided 99 | 100 | 101 | 102 | 103 | 104 | api 105 | tck 106 | spec 107 | 108 | 109 | -------------------------------------------------------------------------------- /spec/NOTICE: -------------------------------------------------------------------------------- 1 | ========================================================================= 2 | == NOTICE file corresponding to section 4(d) of the Apache License, == 3 | == Version 2.0, in this case for Microprofile LRA == 4 | ========================================================================= 5 | 6 | This product includes software developed at 7 | The Apache Software Foundation (http://www.apache.org/). 8 | 9 | 10 | SPDXVersion: SPDX-2.1 11 | PackageName: Eclipse Microprofile 12 | PackageHomePage: http://www.eclipse.org/microprofile 13 | PackageLicenseDeclared: Apache-2.0 14 | 15 | PackageCopyrightText: 16 | Michael Musgrove mmusgrov@redhat.com 17 | Nicola Ferraro ni.ferraro@gmail.com 18 | Ondra Chaloupka ochaloup@redhat.com 19 | Tom Jenkinson tom.jenkinson@redhat.com 20 | Martin Stefanko mstefank@redhat.com 21 | Rudy De Busscher rdebusscher@gmail.com 22 | 23 | -------------------------------------------------------------------------------- /spec/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 4.0.0 18 | 19 | 20 | 21 | org.eclipse.microprofile.lra 22 | microprofile-lra-parent 23 | 2.1-SNAPSHOT 24 | 25 | 26 | org.eclipse.microprofile.lra 27 | microprofile-lra-spec 28 | pom 29 | MicroProfile LRA Specification 30 | MicroProfile LRA Specification :: Specification 31 | 32 | 33 | -------------------------------------------------------------------------------- /spec/src/main/asciidoc/images/arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microprofile/microprofile-lra/486dbe9207620177de791157cae8949d9e3e89f4/spec/src/main/asciidoc/images/arch.png -------------------------------------------------------------------------------- /spec/src/main/asciidoc/images/lra-state-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microprofile/microprofile-lra/486dbe9207620177de791157cae8949d9e3e89f4/spec/src/main/asciidoc/images/lra-state-model.png -------------------------------------------------------------------------------- /spec/src/main/asciidoc/images/lra-state-model.txt: -------------------------------------------------------------------------------- 1 | /' 2 | Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Source for this PlantUML state diagram 17 | see plantuml.com 18 | '/ 19 | @startuml 20 | 21 | @startuml 22 | [*] --> NoLRAContext 23 | 24 | state "NoLRAContext" as NoLRAContext 25 | NoLRAContext : "There is no active LRA context" 26 | 27 | state NoLRAContext { 28 | NoLRAContext --> LRAContext : startLRA 29 | LRAContext --> NoLRAContext : cancel failed 30 | LRAContext --> NoLRAContext : cancelled 31 | LRAContext --> NoLRAContext : close failed 32 | LRAContext --> NoLRAContext : closed 33 | } 34 | 35 | state LRAContext { 36 | [*] --> ActiveLRA : startLRA 37 | ActiveLRA : "LRA exists and has not yet been asked to close or cancel" 38 | note left of ActiveLRA : initial state 39 | ActiveLRA --> Cancelling : cancel 40 | state "FailedToCancel" as FailedToCancel 41 | FailedToCancel : "One or more participants\ndid not compensate" 42 | state "Cancelling" as Cancelling 43 | Cancelling : "One or more participants\nare still compensating" 44 | state "Closing" as Closing 45 | Closing : "One or more participants\nare still completing" 46 | state "Closed" as Closed 47 | Closed : "All participants\nhave completed" 48 | state "FailedToClose" as FailedToClose 49 | FailedToClose : "One or more participants\ndid not complete" 50 | state "Cancelled" as Cancelled 51 | Cancelled : "All participants\nhave compensated" 52 | 53 | Cancelling --> Cancelled 54 | Cancelling --> FailedToCancel 55 | 56 | ActiveLRA --> Closing : close 57 | Closing --> Closed 58 | Closing --> FailedToClose 59 | 60 | Closed --> Cancelling : cancel (transition is only allowed if LRA is nested) 61 | } 62 | @enduml 63 | 64 | -------------------------------------------------------------------------------- /spec/src/main/asciidoc/images/lra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microprofile/microprofile-lra/486dbe9207620177de791157cae8949d9e3e89f4/spec/src/main/asciidoc/images/lra.png -------------------------------------------------------------------------------- /spec/src/main/asciidoc/images/lra.sd: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 Contributors to the Eclipse Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | service:Service 16 | lra:LRA[a] 17 | service1:Service1[a] 18 | service2:Service2[a] 19 | compensator1:Compensator1[a] 20 | compensator2:Compensator2[a] 21 | 22 | service:lra.startLRA 23 | service:service1.operation 24 | service1:lra.addCompensator 25 | service:service2.operation 26 | service2:lra.addCompensator 27 | service:lra.cancel 28 | lra:compensator1.compensate 29 | lra:compensator2.compensate 30 | -------------------------------------------------------------------------------- /spec/src/main/asciidoc/images/participant-state-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microprofile/microprofile-lra/486dbe9207620177de791157cae8949d9e3e89f4/spec/src/main/asciidoc/images/participant-state-model.png -------------------------------------------------------------------------------- /spec/src/main/asciidoc/images/participant-state-model.txt: -------------------------------------------------------------------------------- 1 | /' 2 | Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Source for this PlantUML state diagram 17 | see plantuml.com 18 | '/ 19 | /` java -jar plantuml.jar participant-state-model.txt `/ 20 | @startuml 21 | [*] --> NotEnlisted 22 | 23 | state "NotEnlisted" as NotEnlisted 24 | NotEnlisted : "The participant is not\n associated with any LRA" 25 | 26 | state NotEnlisted { 27 | NotEnlisted --> Enlisted : joinLRA 28 | Enlisted --> NotEnlisted : completed 29 | Enlisted --> NotEnlisted : compensated 30 | Enlisted --> NotEnlisted : forget 31 | Enlisted --> NotEnlisted : leave 32 | } 33 | 34 | state Enlisted { 35 | [*] --> Active : join 36 | Active : "The participant has joined the LRA and has not yet been asked to compensate or complete" 37 | note left of Active : initial state 38 | Active --> Compensating : compensate 39 | state "FailedToCompensate" as FailedToCompensate 40 | FailedToCompensate : "Must wait for the\n forget message" 41 | state "FailedToComplete" as CannotComplete 42 | CannotComplete : "Must wait for the\n forget message" 43 | state "Compensating" as Compensating 44 | Compensating : "The participant was\nnotified that the\nLRA was cancelled" 45 | state "Completing" as Completing 46 | Completing : "The participant was\nnotified that the\nLRA was closed" 47 | state "Completed" as Completed 48 | Completed : "Participant can now clean up and forget\nthe LRA or must wait for forget message\nif enlisted in nested LRA" 49 | state "Compensated" as Compensated 50 | Compensated : "Participant can now clean up\nand forget the LRA" 51 | 52 | Compensating --> Compensated 53 | Compensating --> FailedToCompensate 54 | 55 | Active --> Completing : complete 56 | Completing --> Completed 57 | Completing --> CannotComplete 58 | 59 | Completed --> Compensating : compensate (transition is only allowed \nif the participant is enlisted in nested LRA) 60 | } 61 | @enduml 62 | -------------------------------------------------------------------------------- /spec/src/main/asciidoc/license-alv2.asciidoc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Contributors to the Eclipse Foundation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | [subs="normal"] 16 | .... 17 | 18 | Specification: {doctitle} 19 | 20 | Version: {revnumber} 21 | 22 | Status: {revremark} 23 | 24 | Release: {revdate} 25 | 26 | Copyright (c) 2016-2017 Eclipse Microprofile Contributors: 27 | {authors} 28 | 29 | Licensed under the Apache License, Version 2.0 (the "License"); 30 | you may not use this file except in compliance with the License. 31 | You may obtain a copy of the License at 32 | 33 | http://www.apache.org/licenses/LICENSE-2.0 34 | 35 | Unless required by applicable law or agreed to in writing, software 36 | distributed under the License is distributed on an "AS IS" BASIS, 37 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 38 | See the License for the specific language governing permissions and 39 | limitations under the License. 40 | 41 | .... 42 | -------------------------------------------------------------------------------- /spec/src/main/asciidoc/license-efsl.asciidoc: -------------------------------------------------------------------------------- 1 | [subs="normal"] 2 | .... 3 | Specification: {doctitle} 4 | Version: {revnumber} 5 | Status: {revremark} 6 | Release: {revdate} 7 | .... 8 | 9 | == Copyright 10 | 11 | Copyright (c) {inceptionYear} , {currentYear} Eclipse Foundation. 12 | 13 | === Eclipse Foundation Specification License 14 | 15 | By using and/or copying this document, or the Eclipse Foundation 16 | document from which this statement is linked, you (the licensee) agree 17 | that you have read, understood, and will comply with the following 18 | terms and conditions: 19 | 20 | Permission to copy, and distribute the contents of this document, or 21 | the Eclipse Foundation document from which this statement is linked, in 22 | any medium for any purpose and without fee or royalty is hereby 23 | granted, provided that you include the following on ALL copies of the 24 | document, or portions thereof, that you use: 25 | 26 | * link or URL to the original Eclipse Foundation document. 27 | * All existing copyright notices, or if one does not exist, a notice 28 | (hypertext is preferred, but a textual representation is permitted) 29 | of the form: "Copyright (c) [$date-of-document] 30 | Eclipse Foundation, Inc. \<>" 31 | 32 | Inclusion of the full text of this NOTICE must be provided. We 33 | request that authorship attribution be provided in any software, 34 | documents, or other items or products that you create pursuant to the 35 | implementation of the contents of this document, or any portion 36 | thereof. 37 | 38 | No right to create modifications or derivatives of Eclipse Foundation 39 | documents is granted pursuant to this license, except anyone may 40 | prepare and distribute derivative works and portions of this document 41 | in software that implements the specification, in supporting materials 42 | accompanying such software, and in documentation of such software, 43 | PROVIDED that all such works include the notice below. HOWEVER, the 44 | publication of derivative works of this document for use as a technical 45 | specification is expressly prohibited. 46 | 47 | The notice is: 48 | 49 | "Copyright (c) [$date-of-document] Eclipse Foundation. This software or 50 | document includes material copied from or derived from [title and URI 51 | of the Eclipse Foundation specification document]." 52 | 53 | ==== Disclaimers 54 | 55 | THIS DOCUMENT IS PROVIDED "AS IS," AND THE COPYRIGHT 56 | HOLDERS AND THE ECLIPSE FOUNDATION MAKE NO REPRESENTATIONS OR 57 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 58 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, 59 | NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE 60 | SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS 61 | WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR 62 | OTHER RIGHTS. 63 | 64 | THE COPYRIGHT HOLDERS AND THE ECLIPSE FOUNDATION WILL NOT BE LIABLE 65 | FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT 66 | OF ANY USE OF THE DOCUMENT OR THE PERFORMANCE OR IMPLEMENTATION OF THE 67 | CONTENTS THEREOF. 68 | 69 | The name and trademarks of the copyright holders or the Eclipse 70 | Foundation may NOT be used in advertising or publicity pertaining to 71 | this document or its contents without specific, written prior 72 | permission. Title to copyright in this document will at all times 73 | remain with copyright holders. 74 | -------------------------------------------------------------------------------- /spec/src/main/asciidoc/release_notes.asciidoc: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2019-2021 Contributors to the Eclipse Foundation 3 | // 4 | // See the NOTICE file(s) distributed with this work for additional 5 | // information regarding copyright ownership. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // You may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | 19 | [[release_notes_10]] 20 | == Release Notes for MicroProfile LRA 1.0 21 | 22 | http://download.eclipse.org/microprofile/microprofile-lra-1.0/microprofile-lra.pdf[MicroProfile LRA Spec PDF] 23 | http://download.eclipse.org/microprofile/microprofile-lra-1.0/microprofile-lra.html[MicroProfile LRA Spec HTML] 24 | http://download.eclipse.org/microprofile/microprofile-lra-1.0/apidocs/[MicroProfile Propagation LRA Javadocs] 25 | 26 | Key features: 27 | 28 | A transaction model which isn’t full ACID: 29 | 30 | - an activity reflects business interactions 31 | - all scoped work must be compensatable 32 | - activities are visible to other services 33 | - when an activity ends all work is either accepted or all work is compensated 34 | - the LRA model defines the triggers for when and where compensation actions are executed 35 | - defines annotations for the safe/transactional execution of activities supporting long running activities involving loosely coupled processes 36 | 37 | Supports: 38 | 39 | - relaxion of atomicity (using nested transactions); 40 | - locking is optional (=> loss of isolation); 41 | - forward progress by allowing work to finish early, to provisionally perform subsets of work (nesting), time bounds, composition of activities 42 | 43 | Provides CDI annotations: 44 | 45 | .LRA Annotations 46 | |=== 47 | |Annotation |Description |JAX-RS 48 | 49 | |@LRA 50 | |Controls the life cycle of an LRA 51 | |Yes 52 | 53 | |@AfterLRA 54 | |Notification that an LRA has finished 55 | |Yes/Optional 56 | |=== 57 | 58 | .Participant Annotations 59 | |=== 60 | |Annotation |Description |JAX-RS 61 | 62 | |@Compensate 63 | |Indicates that the method should be invoked if the LRA is cancelled. 64 | |Optional 65 | 66 | |@Complete 67 | |Indicates that the method should be invoked if the LRA is closed. 68 | |Optional 69 | 70 | |@Leave 71 | |Indicates that this class is no longer interested in this LRA. 72 | |Yes 73 | 74 | |@Status 75 | |When the annotated method is invoked it should report the status. 76 | |Optional 77 | 78 | |@Forget 79 | |The method may release any resources associated with the LRA 80 | |Optional 81 | |=== 82 | 83 | * reactive support: 84 | ** CompletionStage 85 | ** @Suspended AsyncResponse 86 | ** HTTP 202 Accepted response code 87 | 88 | To get started, add this dependency to your project: 89 | 90 | [source,xml] 91 | ---- 92 | 93 | org.eclipse.microprofile.lra 94 | microprofile-lra-api 95 | 1.0 96 | provided 97 | 98 | ---- 99 | 100 | Create a JAX-RS business resource and annotate the methods that you would like to be included in a long running action 101 | using the @LRA annotation. Minimally you should define which business method should be run if the LRA is cancelled 102 | using the @Compensate annotation. 103 | 104 | [source,java] 105 | ---- 106 | @Path("resource") 107 | public class SimpleParticipant { 108 | @PUT 109 | @Path("action") 110 | @LRA(value = LRA.Type.REQUIRED) 111 | public Response businessOp(@HeaderParam(LRA_HTTP_RECOVERY_HEADER) URI recoveryId, 112 | @HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 113 | // perform some business action in the context of the LRA with id lraId 114 | return Response.ok().build(); 115 | } 116 | 117 | @PUT 118 | @Path("compensate") 119 | @Compensate 120 | public Response compensateWork(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 121 | // compensate for any actions that were performed in the context of the LRA with id lraId 122 | 123 | return Response.ok().build(); 124 | } 125 | } 126 | ---- 127 | -------------------------------------------------------------------------------- /spec/src/main/resources/META-INF/NOTICE: -------------------------------------------------------------------------------- 1 | ========================================================================= 2 | == NOTICE file corresponding to section 4(d) of the Apache License, == 3 | == Version 2.0, in this case for Microprofile LRA == 4 | ========================================================================= 5 | 6 | This product includes software developed at 7 | The Apache Software Foundation (http://www.apache.org/). 8 | 9 | 10 | SPDXVersion: SPDX-2.1 11 | PackageName: Eclipse Microprofile 12 | PackageHomePage: http://www.eclipse.org/microprofile 13 | PackageLicenseDeclared: Apache-2.0 14 | 15 | PackageCopyrightText: 16 | Michael Musgrove mmusgrov@redhat.com 17 | Nicola Ferraro ni.ferraro@gmail.com 18 | Ondra Chaloupka ochaloup@redhat.com 19 | Tom Jenkinson tom.jenkinson@redhat.com 20 | Martin Stefanko mstefank@redhat.com 21 | Rudy De Busscher rdebusscher@gmail.com 22 | 23 | -------------------------------------------------------------------------------- /tck/README.adoc: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | = Running the Microprofile LRA TCK 17 | 18 | == Hardware Requirements 19 | 20 | All systems should meet the following recommended hardware requirements: 21 | 22 | * CPU running at 2.0 GHz or higher 23 | * 4 GB of RAM or more 24 | 25 | == Software Requirements 26 | 27 | You can run this TCK on platforms running the Solaris, Linux, Windows, and Mac OS with the following software installed: 28 | 29 | * Maven 30 | * JDK8+ 31 | 32 | The TCK uses `JUnit 4` and `Arquillian`. 33 | 34 | == SPI 35 | 36 | In order to run TCK, the implementors must provide an implementation of 37 | `org.eclipse.microprofile.lra.tck.service.spi.LraRecoveryService` and declare 38 | it as a CDI bean so it can be used in the TCK environment. 39 | 40 | == Configuration 41 | 42 | The LRA TCK suite can be parametrized by following properties, handled in the suite with MicroProfile Config 43 | 44 | `lra.tck.base.url`:: 45 | The URL where the TCK suite deployment is exposed at. The TCK suite will construct path based on this URL. 46 | The default base URL is `http://localhost:8180`. This property needs to be provided for the container, 47 | and for the tests themselves (failsafe/surefire) too. 48 | `lra.tck.timeout.factor`:: 49 | Timeout factor adjust timeout values used in the TCK suite. The default value is `1.0`. 50 | When set bigger than `1.0` then timeout value will be bigger and waiting time is longer. 51 | When set-up lower then the timeouts will be shorter. 52 | Thus on slower machines it's expected longer timeouts will be needed. For example if test expects 53 | some waiting time to be 10 seconds and this factor is set to `1.5` then the result waiting time is 15 seconds. 54 | The timeout factor must be configured as system property because of the test limitations. 55 | `lra.http.recovery.host`, `lra.http.recovery.port`, `lra.http.recovery.path`:: 56 | Hostname, port and path for the recovery endpoint that will be contacted in tests checking recovery capabilities. 57 | 58 | == Prerequisites for the MicroProfile LRA TCK implementation 59 | 60 | * `pom.xml` dependencies are set-up 61 | * the LRA TCK suite requires MicroProfile Config 62 | * a default Arquillian container is configured in `arquillian.xml` (tests manually deploy with use of `@ArquillianResource Deployer`) 63 | * JAX-RS `ClientBuilder` is used to run REST calls from tests to tested application. Provide the implementation of the 64 | JAX-RS `ClientBuilder` on the test class path. 65 | 66 | === Setting-up pom.xml dependencies and running the tests 67 | 68 | To enable the tests in your implementation of this specification you need to add the following dependency to your build: 69 | 70 | [source, xml] 71 | ---- 72 | 73 | org.eclipse.microprofile.lra 74 | microprofile-lra-tck 75 | ${version.microprofile-lra-tck-to-test} 76 | test 77 | 78 | ---- 79 | 80 | Next you need to specify what are tests to be run. You need to inject the TCK suite tests to be run automatically. 81 | Here we use integration tests with `maven failsafe` where dependency to scan is set to include particular test classes. 82 | 83 | [source, xml] 84 | ---- 85 | 86 | 87 | 88 | org.apache.maven.plugins 89 | maven-failsafe-plugin 90 | 91 | 92 | org.eclipse.microprofile.lra:microprofile-lra-tck 93 | 94 | 95 | **/*Test*.java 96 | 97 | 98 | 99 | 100 | 101 | ---- 102 | 103 | === MicroProfile Config being available 104 | 105 | The testsuite uses configuration while expecting MicroProfile Config is available. The maven coordinates 106 | of config are `org.eclipse.microprofile.config:microprofile-config-api`. 107 | 108 | === Arquillian container 109 | 110 | The `arquillian-*.xml` has to define a container that will be started and managed by Arquillian lifecycle 111 | but that provide a way to deploy and undeploy deployments. That container to be expected with default type `suite`. 112 | 113 | 114 | [source, xml] 115 | ---- 116 | 117 | 118 | 119 | 120 | 121 | ... 122 | 123 | 124 | 125 | ---- 126 | 127 | == SPI 128 | 129 | * The TCK provides an SPI `LRARecoveryService` which is retrived through the 130 | `ServiceLoader` mechanism. The implmenter is required to provide an 131 | implementation of this interface in order to run the TCK. 132 | 133 | == Debugging tests 134 | 135 | Debugging is dependent on the TCK implementor. The implementor configures Arquillian to use particular runtime 136 | to deploy the test deployments and run the LRA client side implementation there. In general we can say that 137 | the runtime needs to define java debug properties `-Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y`. 138 | Then debugger may be connected to port 8787 and to track the test execution. 139 | 140 | -------------------------------------------------------------------------------- /tck/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | 20 | 21 | org.eclipse.microprofile.lra 22 | microprofile-lra-parent 23 | 2.1-SNAPSHOT 24 | 25 | 26 | microprofile-lra-tck 27 | MicroProfile LRA TCK 28 | LRA TCK 29 | jar 30 | 31 | 32 | 1.3 33 | 34 | 35 | 36 | 37 | 38 | org.eclipse.microprofile 39 | microprofile-tck-bom 40 | ${version.microprofile.tck.bom} 41 | pom 42 | import 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.eclipse.microprofile.lra 50 | microprofile-lra-api 51 | 52 | 53 | 54 | jakarta.ws.rs 55 | jakarta.ws.rs-api 56 | 57 | 58 | 59 | jakarta.enterprise 60 | jakarta.enterprise.cdi-api 61 | 62 | 63 | 64 | jakarta.json 65 | jakarta.json-api 66 | 67 | 68 | 69 | org.eclipse.microprofile.config 70 | microprofile-config-api 71 | ${version.microprofile.config} 72 | provided 73 | 74 | 75 | 76 | junit 77 | junit 78 | 79 | 80 | 81 | org.hamcrest 82 | hamcrest-all 83 | 84 | 85 | 86 | org.jboss.arquillian.junit 87 | arquillian-junit-container 88 | 89 | 90 | 91 | org.jboss.shrinkwrap 92 | shrinkwrap-api 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/JaxRsActivator.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck; 21 | 22 | import jakarta.ws.rs.ApplicationPath; 23 | import jakarta.ws.rs.core.Application; 24 | 25 | @ApplicationPath("/") 26 | public class JaxRsActivator extends Application { 27 | } 28 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/LraTckConfigBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | 21 | package org.eclipse.microprofile.lra.tck; 22 | 23 | import org.eclipse.microprofile.config.inject.ConfigProperty; 24 | 25 | import jakarta.enterprise.context.ApplicationScoped; 26 | import jakarta.inject.Inject; 27 | 28 | @ApplicationScoped 29 | public class LraTckConfigBean { 30 | 31 | /** 32 | * Definition of LRA default timeout which should be used by any method which needs to work with timeout 33 | */ 34 | private static final Long LRA_TIMEOUT_MILLIS = 50000L; 35 | 36 | /** 37 | * Name of the config property that is used as factor adjusting timeout values used in the testsuite. 38 | */ 39 | public static final String LRA_TCK_TIMEOUT_FACTOR_PROPETY_NAME = "lra.tck.timeout.factor"; 40 | 41 | /** 42 | * Name of the config property which is used to configure the TCK base url. See 43 | * {@link LraTckConfigBean#tckSuiteBaseUrl}. 44 | */ 45 | public static final String LRA_TCK_BASE_URL_PROPERTY_NAME = "lra.tck.base.url"; 46 | 47 | /** 48 | *

49 | * Timeout factor which adjusts waiting time and timeouts for the TCK suite. 50 | *

51 | * The default value is set to 1.0 which means the defined timeout is multiplied by 1. 52 | *

53 | * If you wish the test waits longer then set the value bigger than 1.0. If you wish the test waits 54 | * shorter time than designed or the timeout is elapsed faster then set the value less than 1.0 55 | */ 56 | @Inject 57 | @ConfigProperty(name = LRA_TCK_TIMEOUT_FACTOR_PROPETY_NAME, defaultValue = "1.0") 58 | private double timeoutFactor; 59 | 60 | /** 61 | * Base URL where the LRA suite is started at. It's URL where container exposes the test suite deployment. The test 62 | * paths will be constructed based on this base URL. 63 | *

64 | * The default base URL where TCK suite is expected to be started is http://localhost:8180/. 65 | */ 66 | @Inject 67 | @ConfigProperty(name = LRA_TCK_BASE_URL_PROPERTY_NAME, defaultValue = "http://localhost:8180/") 68 | private String tckSuiteBaseUrl; 69 | 70 | /** 71 | * Adjusting the default timeout by the specified timeout factor which can be defined by user when property 72 | * {@code #LRA_TCK_TIMEOUT_FACTOR_PROPETY_NAME} is defined. 73 | * 74 | * @return default timeout adjusted with timeout factor 75 | */ 76 | public long getDefaultTimeout() { 77 | return adjustTimeout(LraTckConfigBean.LRA_TIMEOUT_MILLIS); 78 | } 79 | 80 | /** 81 | * Adjusting the provided value by timeout factor defined for the TCK suite. 82 | * 83 | * @param timeout 84 | * timeout value to be adjusted by {@code #LRA_TCK_TIMEOUT_FACTOR_PROPETY_NAME} 85 | * @return value of adjusted timeout 86 | */ 87 | public long adjustTimeout(long timeout) { 88 | return adjustTimeout(timeout, timeoutFactor); 89 | } 90 | 91 | private long adjustTimeout(long timeout, double timeoutFactor) { 92 | if (timeout < 0 || timeoutFactor < 0) { 93 | throw new IllegalArgumentException(String.format( 94 | "Provided arguments (timeout=%d, timeoutFactor=%.2f) have to be positive", timeout, timeoutFactor)); 95 | } 96 | return (long) Math.ceil(timeout * timeoutFactor); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/TckInvalidSignaturesTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck; 21 | 22 | import static org.junit.Assert.assertThrows; 23 | 24 | import org.eclipse.microprofile.lra.tck.participant.invalid.LRAResourceWithoutCompensateOrAfteRLRA; 25 | import org.eclipse.microprofile.lra.tck.participant.nonjaxrs.InvalidAfterLRASignatureListener; 26 | import org.eclipse.microprofile.lra.tck.participant.nonjaxrs.InvalidArgumentTypesParticipant; 27 | import org.eclipse.microprofile.lra.tck.participant.nonjaxrs.InvalidReturnTypeParticipant; 28 | import org.eclipse.microprofile.lra.tck.participant.nonjaxrs.TooManyArgsParticipant; 29 | import org.jboss.arquillian.container.spi.client.container.DeploymentException; 30 | import org.jboss.arquillian.container.test.api.Deployer; 31 | import org.jboss.arquillian.container.test.api.Deployment; 32 | import org.jboss.arquillian.junit.Arquillian; 33 | import org.jboss.arquillian.test.api.ArquillianResource; 34 | import org.jboss.shrinkwrap.api.ShrinkWrap; 35 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 36 | import org.jboss.shrinkwrap.api.spec.WebArchive; 37 | import org.junit.After; 38 | import org.junit.Rule; 39 | import org.junit.Test; 40 | import org.junit.rules.TestName; 41 | import org.junit.runner.RunWith; 42 | 43 | /** 44 | *

45 | * TCK that verifies that invalid non-JAX-RS participant method signatures are reported during deployment 46 | *

47 | * 48 | *

49 | * Each test deploys an archive containing single invalid participant containing an error in its participant method 50 | * signature and expects that such deployment is aborted according to the specification. 51 | *

52 | */ 53 | @RunWith(Arquillian.class) 54 | public class TckInvalidSignaturesTests { 55 | 56 | private static final String INVALID_RETURN_TYPE_DEPLOYMENT = "nonjaxrs-return-type-deploy"; 57 | private static final String TOO_MANY_ARGS_DEPLOYMENT = "too-many-args-deploy"; 58 | private static final String INVALID_ARGUMENT_TYPE_DEPLOYMENT = "nonjaxrs-argument-type-deploy"; 59 | private static final String INVALID_AFTER_LRA_SIGNATURE_DEPLOYMENT = "invalid-after-lra-deploy"; 60 | private static final String INVALID_LRA_RESOURCE_DEPLOYMENT = "invalid-lra-resource-deploy"; 61 | 62 | @Rule 63 | public DeploymentNameRule deploymentNameRule = new DeploymentNameRule(); 64 | 65 | @ArquillianResource 66 | private Deployer deployer; 67 | 68 | @Deployment(name = INVALID_RETURN_TYPE_DEPLOYMENT, managed = false) 69 | public static WebArchive deployInvalidReturnTypeParticipant() { 70 | return createArchive(InvalidReturnTypeParticipant.class); 71 | } 72 | 73 | @Deployment(name = TOO_MANY_ARGS_DEPLOYMENT, managed = false) 74 | public static WebArchive deployTooManyArgsParticipant() { 75 | return createArchive(TooManyArgsParticipant.class); 76 | } 77 | 78 | @Deployment(name = INVALID_ARGUMENT_TYPE_DEPLOYMENT, managed = false) 79 | public static WebArchive deployInvalidArgumentTypeParticipant() { 80 | return createArchive(InvalidArgumentTypesParticipant.class); 81 | } 82 | 83 | @Deployment(name = INVALID_AFTER_LRA_SIGNATURE_DEPLOYMENT, managed = false) 84 | public static WebArchive deployInvalidAfterLRASignatureResource() { 85 | return createArchive(InvalidAfterLRASignatureListener.class); 86 | } 87 | 88 | @Deployment(name = INVALID_LRA_RESOURCE_DEPLOYMENT, managed = false) 89 | public static WebArchive deployInvalidLRAResource() { 90 | return createArchive(LRAResourceWithoutCompensateOrAfteRLRA.class); 91 | } 92 | 93 | private static WebArchive createArchive(Class resourceClass) { 94 | String archiveName = resourceClass.getSimpleName(); 95 | return ShrinkWrap 96 | .create(WebArchive.class, archiveName + ".war") 97 | .addClasses(resourceClass, JaxRsActivator.class) 98 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); 99 | } 100 | 101 | @After 102 | public void after() { 103 | deployer.undeploy(deploymentNameRule.deploymentName); 104 | } 105 | 106 | /** 107 | * Verify that invalid return type (String) in participant method is detected 108 | */ 109 | @Test 110 | public void invalidReturnTypeInParticipantMethodTest() { 111 | testInvalidDeployment(INVALID_RETURN_TYPE_DEPLOYMENT); 112 | } 113 | 114 | /** 115 | * Verify that too many arguments (more than 2) in partcipant method are detected 116 | */ 117 | @Test 118 | public void tooManyArgsInParticipantMethodTest() { 119 | testInvalidDeployment(TOO_MANY_ARGS_DEPLOYMENT); 120 | } 121 | 122 | /** 123 | * Verify that invalid type of argument (int) in participant method is detected 124 | */ 125 | @Test 126 | public void invalidArgumentTypeInParticipantMethodTest() { 127 | testInvalidDeployment(INVALID_ARGUMENT_TYPE_DEPLOYMENT); 128 | } 129 | 130 | /** 131 | * Verify that invalid @AfterLRA method signature is detected 132 | */ 133 | @Test 134 | public void invalidAfterLRASignatureTest() { 135 | testInvalidDeployment(INVALID_AFTER_LRA_SIGNATURE_DEPLOYMENT); 136 | } 137 | 138 | /** 139 | * Verify that invalid LRA resource which does not contain any of @Compensate or @AfterLRA methods is detected 140 | */ 141 | @Test 142 | public void invalidLRAResourceWithoutCompensateOrAfterLRATest() { 143 | testInvalidDeployment(INVALID_LRA_RESOURCE_DEPLOYMENT); 144 | } 145 | 146 | private void testInvalidDeployment(String deploymentName) { 147 | deploymentNameRule.deploymentName = deploymentName; 148 | assertThrows(DeploymentException.class, () -> deployer.deploy(deploymentName)); 149 | } 150 | 151 | private static final class DeploymentNameRule extends TestName { 152 | 153 | String deploymentName; 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/TckTestBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck; 21 | 22 | import static org.junit.Assert.assertEquals; 23 | 24 | import java.net.URL; 25 | import java.util.logging.Logger; 26 | 27 | import org.eclipse.microprofile.lra.LRAResponse; 28 | import org.eclipse.microprofile.lra.tck.participant.activity.Activity; 29 | import org.eclipse.microprofile.lra.tck.participant.api.LraResource; 30 | import org.eclipse.microprofile.lra.tck.service.LRAMetricService; 31 | import org.eclipse.microprofile.lra.tck.service.LRATestService; 32 | import org.eclipse.microprofile.lra.tck.service.spi.LRARecoveryService; 33 | import org.jboss.arquillian.test.api.ArquillianResource; 34 | import org.jboss.shrinkwrap.api.ShrinkWrap; 35 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 36 | import org.jboss.shrinkwrap.api.spec.WebArchive; 37 | import org.junit.After; 38 | import org.junit.Before; 39 | import org.junit.Rule; 40 | import org.junit.rules.TestName; 41 | 42 | import jakarta.inject.Inject; 43 | import jakarta.ws.rs.client.WebTarget; 44 | import jakarta.ws.rs.core.Response; 45 | 46 | /** 47 | * Base testsuite class for in-container tests. It provides {@link Before} and @{@link After} junit hooks to clean the 48 | * environment. 49 | */ 50 | public class TckTestBase { 51 | private static final Logger LOGGER = Logger.getLogger(TckTestBase.class.getName()); 52 | 53 | @Rule 54 | public TestName testName = new TestName(); 55 | 56 | @Inject 57 | private LraTckConfigBean config; 58 | 59 | @Inject 60 | LRATestService lraTestService; 61 | 62 | @Inject 63 | private LRAMetricService lraMetricService; 64 | 65 | @ArquillianResource 66 | private URL deploymentURL; 67 | 68 | LRAClientOps lraClient; 69 | 70 | WebTarget tckSuiteTarget; 71 | 72 | static WebArchive deploy(String archiveName) { 73 | return ShrinkWrap 74 | .create(WebArchive.class, archiveName + ".war") 75 | .addPackages(false, TckTestBase.class.getPackage(), 76 | LRAResponse.class.getPackage(), 77 | Activity.class.getPackage(), 78 | LraResource.class.getPackage(), 79 | LRAMetricService.class.getPackage(), 80 | LRARecoveryService.class.getPackage()) 81 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); 82 | } 83 | 84 | @Before 85 | public void before() { 86 | LOGGER.info("Running test: " + testName.getMethodName()); 87 | 88 | lraTestService.start(deploymentURL); 89 | lraMetricService.clear(); 90 | this.lraClient = lraTestService.getLRAClient(); 91 | this.tckSuiteTarget = lraTestService.getTCKSuiteTarget(); 92 | } 93 | 94 | @After 95 | public void after() { 96 | lraTestService.stop(); 97 | } 98 | 99 | void checkStatusAndCloseResponse(Response.Status expectedStatus, Response response, WebTarget resourcePath) { 100 | try { 101 | assertEquals("Not expected status at call '" + resourcePath.getUri() + "'", 102 | expectedStatus.getStatusCode(), response.getStatus()); 103 | } finally { 104 | response.close(); 105 | } 106 | } 107 | 108 | String checkStatusReadAndCloseResponse(Response.Status expectedStatus, Response response, WebTarget resourcePath) { 109 | try { 110 | assertEquals("Response status on call to '" + resourcePath.getUri() + "' failed to match.", 111 | expectedStatus.getStatusCode(), response.getStatus()); 112 | return response.readEntity(String.class); 113 | } finally { 114 | response.close(); 115 | } 116 | } 117 | 118 | /** 119 | * The started LRA will be named based on the class name and the running test name. 120 | */ 121 | String lraClientId() { 122 | return this.getClass().getSimpleName() + "#" + testName.getMethodName(); 123 | } 124 | 125 | /** 126 | * Returning default timeout configured for the TCK tests. 127 | */ 128 | long lraTimeout() { 129 | return config.getDefaultTimeout(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/TckUnknownStatusTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck; 21 | 22 | import java.net.URI; 23 | 24 | import org.eclipse.microprofile.lra.tck.participant.api.LRAUnknownStatusResource; 25 | import org.eclipse.microprofile.lra.tck.participant.api.Scenario; 26 | import org.eclipse.microprofile.lra.tck.service.LRAMetricAssertions; 27 | import org.eclipse.microprofile.lra.tck.service.LRATestService; 28 | import org.jboss.arquillian.container.test.api.Deployment; 29 | import org.jboss.arquillian.junit.Arquillian; 30 | import org.jboss.shrinkwrap.api.spec.WebArchive; 31 | import org.junit.Before; 32 | import org.junit.Test; 33 | import org.junit.runner.RunWith; 34 | 35 | import jakarta.inject.Inject; 36 | import jakarta.ws.rs.WebApplicationException; 37 | import jakarta.ws.rs.client.Entity; 38 | import jakarta.ws.rs.client.WebTarget; 39 | import jakarta.ws.rs.core.Response; 40 | 41 | /** 42 | * TCK Tests related to the 410 status code handling. Version with a Status method. 43 | */ 44 | @RunWith(Arquillian.class) 45 | public class TckUnknownStatusTests extends TckTestBase { 46 | 47 | @Inject 48 | private LRAMetricAssertions lraMetric; 49 | 50 | @Inject 51 | private LRATestService lraTestService; 52 | 53 | @Deployment(name = "tckunkownstatus") 54 | public static WebArchive deploy() { 55 | return TckUnknownStatusTests.deploy(TckUnknownStatusTests.class.getSimpleName().toLowerCase()); 56 | } 57 | 58 | @Before 59 | public void before() { 60 | super.before(); 61 | } 62 | 63 | @Test 64 | public void compensate_retry() throws WebApplicationException { 65 | String lraIdString = invoke(Scenario.COMPENSATE_RETRY); 66 | URI lraId = URI.create(lraIdString); 67 | 68 | lraTestService.waitForRecovery(lraId); 69 | 70 | lraMetric.assertCompensatedEquals("Number of calls to @Compensate incorrect", 71 | 1, lraId, LRAUnknownStatusResource.class); 72 | lraMetric.assertStatus("Expect @Status was called", lraId, LRAUnknownStatusResource.class); 73 | lraMetric.assertAfterLRA("Expect @AfterLRA was called", lraId, LRAUnknownStatusResource.class); 74 | lraMetric.assertCancelled("Expect Cancel was called", lraId, LRAUnknownStatusResource.class); 75 | } 76 | 77 | @Test 78 | public void complete_retry() throws WebApplicationException { 79 | String lraIdString = invoke(Scenario.COMPLETE_RETRY); 80 | URI lraId = URI.create(lraIdString); 81 | 82 | lraTestService.waitForRecovery(lraId); 83 | 84 | lraMetric.assertCompletedEquals("Number of calls to @Complete incorrect", 85 | 1, lraId, LRAUnknownStatusResource.class); 86 | lraMetric.assertStatus("Expect @Status was called", lraId, LRAUnknownStatusResource.class); 87 | lraMetric.assertAfterLRA("Expect @AfterLRA was called", lraId, LRAUnknownStatusResource.class); 88 | lraMetric.assertClosed("Expect Close was called", lraId, LRAUnknownStatusResource.class); 89 | } 90 | 91 | private String invoke(Scenario scenario) { 92 | WebTarget resourcePath = tckSuiteTarget.path(LRAUnknownStatusResource.LRA_CONTROLLER_PATH) 93 | .path(LRAUnknownStatusResource.TRANSACTIONAL_WORK_PATH) 94 | .queryParam("scenario", scenario.name()); 95 | Response response = resourcePath.request().put(Entity.text("")); 96 | 97 | return checkStatusReadAndCloseResponse(Response.Status.fromStatusCode(scenario.getPathResponseCode()), response, 98 | resourcePath); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/TckUnknownTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck; 21 | 22 | import static org.hamcrest.MatcherAssert.assertThat; 23 | 24 | import java.net.URI; 25 | 26 | import org.eclipse.microprofile.lra.tck.participant.api.LRAUnknownResource; 27 | import org.eclipse.microprofile.lra.tck.participant.api.Scenario; 28 | import org.eclipse.microprofile.lra.tck.service.LRAMetricAssertions; 29 | import org.eclipse.microprofile.lra.tck.service.LRAMetricService; 30 | import org.eclipse.microprofile.lra.tck.service.LRAMetricType; 31 | import org.eclipse.microprofile.lra.tck.service.LRATestService; 32 | import org.hamcrest.Matchers; 33 | import org.jboss.arquillian.container.test.api.Deployment; 34 | import org.jboss.arquillian.junit.Arquillian; 35 | import org.jboss.shrinkwrap.api.spec.WebArchive; 36 | import org.junit.Before; 37 | import org.junit.Test; 38 | import org.junit.runner.RunWith; 39 | 40 | import jakarta.inject.Inject; 41 | import jakarta.ws.rs.WebApplicationException; 42 | import jakarta.ws.rs.client.Entity; 43 | import jakarta.ws.rs.client.WebTarget; 44 | import jakarta.ws.rs.core.Response; 45 | 46 | /** 47 | * TCK Tests related to the 410 status code handling. Version without a Status method. 48 | */ 49 | @RunWith(Arquillian.class) 50 | public class TckUnknownTests extends TckTestBase { 51 | 52 | @Inject 53 | private LRAMetricAssertions lraMetric; 54 | 55 | @Inject 56 | private LRAMetricService lraMetricService; 57 | 58 | @Inject 59 | private LRATestService lraTestService; 60 | 61 | @Deployment(name = "tckunkown") 62 | public static WebArchive deploy() { 63 | return TckTestBase.deploy(TckUnknownTests.class.getSimpleName().toLowerCase()); 64 | } 65 | 66 | @Before 67 | public void before() { 68 | super.before(); 69 | } 70 | 71 | @Test 72 | public void compensate_immediate() throws WebApplicationException { 73 | String lraIdString = invoke(Scenario.COMPENSATE_IMMEDIATE); 74 | URI lraId = URI.create(lraIdString); 75 | 76 | lraTestService.waitForRecovery(lraId); 77 | 78 | lraMetric.assertCompensated("Expect @Compensate was called", lraId, LRAUnknownResource.class); 79 | lraMetric.assertAfterLRA("Expect @AfterLRA was called", lraId, LRAUnknownResource.class); 80 | lraMetric.assertCancelled("Expect final Cancel was called", lraId, LRAUnknownResource.class); 81 | } 82 | 83 | @Test 84 | public void compensate_retry() throws WebApplicationException { 85 | String lraIdString = invoke(Scenario.COMPENSATE_RETRY); 86 | URI lraId = URI.create(lraIdString); 87 | 88 | lraTestService.waitForRecovery(lraId); 89 | 90 | int compensatedCalled = lraMetricService.getMetric(LRAMetricType.Compensated, 91 | lraId, LRAUnknownResource.class); 92 | assertThat("Expect @Compensate was called", compensatedCalled, Matchers.greaterThanOrEqualTo(2)); 93 | lraMetric.assertAfterLRA("Expect @AfterLRA was called", lraId, LRAUnknownResource.class); 94 | lraMetric.assertCancelled("Expect final Cancel was called", lraId, LRAUnknownResource.class); 95 | } 96 | 97 | @Test 98 | public void complete_immediate() throws WebApplicationException { 99 | String lraIdString = invoke(Scenario.COMPLETE_IMMEDIATE); 100 | URI lraId = URI.create(lraIdString); 101 | 102 | lraTestService.waitForRecovery(lraId); 103 | 104 | lraMetric.assertCompleted("Expect @Complete was called", lraId, LRAUnknownResource.class); 105 | lraMetric.assertAfterLRA("Expect @AfterLRA was called", lraId, LRAUnknownResource.class); 106 | lraMetric.assertClosed("Expect final Close was called", lraId, LRAUnknownResource.class); 107 | } 108 | 109 | @Test 110 | public void complete_retry() throws WebApplicationException { 111 | String lraIdString = invoke(Scenario.COMPLETE_RETRY); 112 | URI lraId = URI.create(lraIdString); 113 | 114 | lraTestService.waitForRecovery(lraId); 115 | 116 | int compensatedCalled = lraMetricService.getMetric(LRAMetricType.Completed, 117 | lraId, LRAUnknownResource.class); 118 | assertThat("Expect @Compensate was called", compensatedCalled, Matchers.greaterThanOrEqualTo(2)); 119 | lraMetric.assertAfterLRA("Expect @AfterLRA was called", lraId, LRAUnknownResource.class); 120 | lraMetric.assertClosed("Expect final Close was called", lraId, LRAUnknownResource.class); 121 | } 122 | 123 | private String invoke(Scenario scenario) { 124 | WebTarget resourcePath = tckSuiteTarget.path(LRAUnknownResource.LRA_CONTROLLER_PATH) 125 | .path(LRAUnknownResource.TRANSACTIONAL_WORK_PATH) 126 | .queryParam("scenario", scenario.name()); 127 | Response response = resourcePath.request().put(Entity.text("")); 128 | 129 | return checkStatusReadAndCloseResponse(Response.Status.fromStatusCode(scenario.getPathResponseCode()), response, 130 | resourcePath); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/activity/Activity.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.activity; 21 | 22 | import java.io.Serializable; 23 | import java.net.URI; 24 | import java.util.concurrent.atomic.AtomicInteger; 25 | 26 | import org.eclipse.microprofile.lra.annotation.ParticipantStatus; 27 | 28 | /** 29 | * A simple DTO that provides information about the work processed in the TCK suite resources. 30 | */ 31 | public class Activity implements Serializable { 32 | private static final long serialVersionUID = 1L; 33 | 34 | private URI lraId; 35 | private URI recoveryUri; 36 | private String statusUrl; 37 | private ParticipantStatus status; 38 | private String endData; 39 | 40 | private final AtomicInteger acceptedCount = new AtomicInteger(0); 41 | 42 | public Activity(URI lraId) { 43 | this.setLraId(lraId); 44 | } 45 | 46 | public URI getLraId() { 47 | return lraId; 48 | } 49 | 50 | public Activity setLraId(URI lraId) { 51 | this.lraId = lraId; 52 | return this; 53 | } 54 | 55 | public URI getRecoveryUri() { 56 | return recoveryUri; 57 | } 58 | 59 | public Activity setRecoveryUri(URI recoveryUri) { 60 | this.recoveryUri = recoveryUri; 61 | return this; 62 | } 63 | 64 | public String getStatusUrl() { 65 | return statusUrl; 66 | } 67 | 68 | public Activity setStatusUrl(String statusUrl) { 69 | this.statusUrl = statusUrl; 70 | return this; 71 | } 72 | 73 | public ParticipantStatus getStatus() { 74 | return status; 75 | } 76 | 77 | public Activity setStatus(ParticipantStatus status) { 78 | this.status = status; 79 | return this; 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return "Activity{" + 85 | "lraId='" + getLraId() + '\'' + 86 | ", recoveryUri='" + getRecoveryUri() + '\'' + 87 | ", statusUrl='" + getStatusUrl() + '\'' + 88 | ", status=" + getStatus() + 89 | ", endData='" + getEndData() + '\'' + 90 | '}'; 91 | } 92 | 93 | public int getAndDecrementAcceptCount() { 94 | return getAcceptedCount().getAndDecrement(); 95 | } 96 | 97 | public String getEndData() { 98 | return endData; 99 | } 100 | 101 | public Activity setEndData(String endData) { 102 | this.endData = endData; 103 | return this; 104 | } 105 | 106 | public AtomicInteger getAcceptedCount() { 107 | return acceptedCount; 108 | } 109 | 110 | public Activity setAcceptedCount(int acceptedCount) { 111 | this.acceptedCount.set(acceptedCount); 112 | return this; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/activity/ActivityStorage.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.activity; 21 | 22 | import java.net.URI; 23 | import java.util.ArrayList; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | import java.util.Map; 27 | 28 | import jakarta.enterprise.context.ApplicationScoped; 29 | import jakarta.ws.rs.WebApplicationException; 30 | import jakarta.ws.rs.core.Response; 31 | import jakarta.ws.rs.core.UriInfo; 32 | 33 | /** 34 | * Storing activities processed by resources during TCK suite run. 35 | */ 36 | @ApplicationScoped 37 | public class ActivityStorage { 38 | private Map activities = new HashMap<>(); 39 | 40 | public Activity getActivityAndAssertExistence(URI lraId, UriInfo jaxrsContext) { 41 | if (!activities.containsKey(lraId)) { 42 | String errorMessage = String.format("Activity store does not contain LRA id '%s', " 43 | + "invoked from endpoint '%s'", lraId, jaxrsContext.getPath()); 44 | throw new WebApplicationException(Response.status(410).entity(errorMessage).build()); 45 | } 46 | 47 | return activities.get(lraId); 48 | } 49 | 50 | public List findAll() { 51 | return new ArrayList<>(activities.values()); 52 | } 53 | 54 | public Activity add(Activity activity) { 55 | activities.putIfAbsent(activity.getLraId(), activity); 56 | return activities.get(activity.getLraId()); 57 | } 58 | 59 | public void remove(URI id) { 60 | activities.remove(id); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/AfterLRAListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; 23 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_ENDED_CONTEXT_HEADER; 24 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_RECOVERY_HEADER; 25 | 26 | import java.net.URI; 27 | 28 | import org.eclipse.microprofile.lra.annotation.AfterLRA; 29 | import org.eclipse.microprofile.lra.annotation.LRAStatus; 30 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 31 | import org.eclipse.microprofile.lra.tck.service.LRATestService; 32 | 33 | import jakarta.enterprise.context.ApplicationScoped; 34 | import jakarta.inject.Inject; 35 | import jakarta.ws.rs.HeaderParam; 36 | import jakarta.ws.rs.PUT; 37 | import jakarta.ws.rs.Path; 38 | import jakarta.ws.rs.core.Response; 39 | 40 | /** 41 | * resource for testing that methods annotated with {@link AfterLRA} are notified correctly when an LRA terminates 42 | */ 43 | @ApplicationScoped 44 | @Path(AfterLRAListener.AFTER_LRA_LISTENER_PATH) 45 | public class AfterLRAListener extends ResourceParent { 46 | public static final String AFTER_LRA_LISTENER_PATH = "after-lra-listener"; 47 | public static final String AFTER_LRA_LISTENER_WORK = "work"; 48 | 49 | private static final String AFTER_LRA = "/after"; 50 | 51 | @Inject 52 | private LRATestService lraTestService; 53 | 54 | @PUT 55 | @Path(AFTER_LRA_LISTENER_WORK) 56 | @LRA(value = LRA.Type.REQUIRED, end = false) 57 | public Response activityWithLRA(@HeaderParam(LRA_HTTP_RECOVERY_HEADER) URI recoveryId, 58 | @HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 59 | return Response.ok().build(); 60 | } 61 | 62 | @PUT 63 | @Path(AFTER_LRA) 64 | @AfterLRA // this method will be called when the LRA associated with the method activityWithLRA finishes 65 | public Response afterLRA(@HeaderParam(LRA_HTTP_ENDED_CONTEXT_HEADER) URI lraId, LRAStatus status) { 66 | return lraTestService.processAfterLRAInfo(lraId, status, AfterLRAListener.class, 67 | AFTER_LRA_LISTENER_PATH + AFTER_LRA); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/AfterLRAParticipant.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; 23 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_ENDED_CONTEXT_HEADER; 24 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_RECOVERY_HEADER; 25 | 26 | import java.net.URI; 27 | 28 | import org.eclipse.microprofile.lra.LRAResponse; 29 | import org.eclipse.microprofile.lra.annotation.AfterLRA; 30 | import org.eclipse.microprofile.lra.annotation.Compensate; 31 | import org.eclipse.microprofile.lra.annotation.Complete; 32 | import org.eclipse.microprofile.lra.annotation.LRAStatus; 33 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 34 | import org.eclipse.microprofile.lra.tck.service.LRAMetricService; 35 | import org.eclipse.microprofile.lra.tck.service.LRAMetricType; 36 | import org.eclipse.microprofile.lra.tck.service.LRATestService; 37 | 38 | import jakarta.enterprise.context.ApplicationScoped; 39 | import jakarta.inject.Inject; 40 | import jakarta.ws.rs.HeaderParam; 41 | import jakarta.ws.rs.PUT; 42 | import jakarta.ws.rs.Path; 43 | import jakarta.ws.rs.core.Response; 44 | 45 | /** 46 | * resource for testing that methods annotated with {@link AfterLRA} are notified correctly when an LRA terminates 47 | */ 48 | @ApplicationScoped 49 | @Path(AfterLRAParticipant.AFTER_LRA_PARTICIPANT_PATH) 50 | public class AfterLRAParticipant { 51 | public static final String AFTER_LRA_PARTICIPANT_PATH = "after-lra-participant"; 52 | public static final String AFTER_LRA_PARTICIPANT_WORK = "work"; 53 | 54 | private static final String AFTER_LRA = "/after"; 55 | 56 | @Inject 57 | private LRAMetricService lraMetricService; 58 | 59 | @Inject 60 | private LRATestService lraTestService; 61 | 62 | @PUT 63 | @Path("/complete") 64 | @Complete 65 | public Response completeWork(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 66 | lraMetricService.incrementMetric(LRAMetricType.Completed, lraId, AfterLRAParticipant.class); 67 | return LRAResponse.completed(); 68 | } 69 | 70 | @PUT 71 | @Path("/compensate") 72 | @Compensate 73 | public Response compensateWork(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 74 | lraMetricService.incrementMetric(LRAMetricType.Compensated, lraId, AfterLRAParticipant.class); 75 | 76 | return LRAResponse.compensated(); 77 | } 78 | 79 | @PUT 80 | @Path(AFTER_LRA_PARTICIPANT_WORK) 81 | @LRA(value = LRA.Type.REQUIRED, end = false) 82 | public Response activityWithLRA(@HeaderParam(LRA_HTTP_RECOVERY_HEADER) URI recoveryId, 83 | @HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 84 | return Response.ok().build(); 85 | } 86 | 87 | @PUT 88 | @Path(AFTER_LRA) 89 | @AfterLRA // this method will be called when the LRA associated with the method activityWithLRA finishes 90 | public Response afterEnd(@HeaderParam(LRA_HTTP_ENDED_CONTEXT_HEADER) URI lraId, LRAStatus status) { 91 | return lraTestService.processAfterLRAInfo(lraId, status, AfterLRAParticipant.class, 92 | AFTER_LRA_PARTICIPANT_PATH + AFTER_LRA); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/GenericLRAException.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | 21 | package org.eclipse.microprofile.lra.tck.participant.api; 22 | 23 | import java.net.URI; 24 | 25 | import jakarta.ws.rs.WebApplicationException; 26 | 27 | public class GenericLRAException extends WebApplicationException { 28 | private static final long serialVersionUID = 1L; 29 | 30 | private URI lraId; 31 | 32 | public URI getLraId() { 33 | return lraId; 34 | } 35 | 36 | public GenericLRAException(URI lraId, String message, Throwable cause) { 37 | super(String.format("%s: %s", lraId, message), cause); 38 | 39 | this.lraId = lraId; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/IllegalLRAStateException.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import java.net.URI; 23 | 24 | import jakarta.ws.rs.WebApplicationException; 25 | 26 | public class IllegalLRAStateException extends WebApplicationException { 27 | private final URI lraId; 28 | 29 | /** 30 | * Creation of LRA state exception. 31 | * 32 | * @param lraId 33 | * LRA id that is behind this exception 34 | * @param message 35 | * error message of this exception 36 | */ 37 | public IllegalLRAStateException(URI lraId, String message) { 38 | super(String.format("%s, lra id: %s", message, lraId.toASCIIString())); 39 | 40 | this.lraId = lraId; 41 | } 42 | 43 | public URI getLraId() { 44 | return this.lraId; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckInterface.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; 23 | 24 | import java.net.URI; 25 | 26 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 27 | 28 | import jakarta.ws.rs.GET; 29 | import jakarta.ws.rs.HeaderParam; 30 | import jakarta.ws.rs.Path; 31 | import jakarta.ws.rs.core.Response; 32 | 33 | public interface LRATypeTckInterface { 34 | 35 | String REQUIRED_PATH = "/required"; 36 | String REQUIRES_NEW_PATH = "/requires-new"; 37 | String SUPPORTS_PATH = "/supports"; 38 | String NOT_SUPPORTED_PATH = "/not-supported"; 39 | String MANDATORY_PATH = "/mandatory"; 40 | String NEVER_PATH = "/never"; 41 | 42 | String REQUIRED_WITH_END_FALSE_PATH = "/end-required"; 43 | String REQUIRES_NEW_WITH_END_FALSE_PATH = "/end-requires-new"; 44 | String SUPPORTS_WITH_END_FALSE_PATH = "/end-supports"; 45 | String NOT_SUPPORTED_WITH_END_FALSE_PATH = "/end-not-supported"; 46 | String MANDATORY_WITH_END_FALSE_PATH = "/end-mandatory"; 47 | String NEVER_WITH_END_FALSE_PATH = "/end-never"; 48 | 49 | @GET 50 | @Path(REQUIRED_PATH) 51 | @LRA(value = LRA.Type.REQUIRED) 52 | Response requiredLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 53 | 54 | @GET 55 | @Path(REQUIRES_NEW_PATH) 56 | @LRA(value = LRA.Type.REQUIRES_NEW) 57 | Response requiresNewLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 58 | 59 | @GET 60 | @Path(MANDATORY_PATH) 61 | @LRA(value = LRA.Type.MANDATORY) 62 | Response mandatoryLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 63 | 64 | @GET 65 | @Path(SUPPORTS_PATH) 66 | @LRA(value = LRA.Type.SUPPORTS) 67 | Response supportsLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 68 | 69 | @GET 70 | @Path(NOT_SUPPORTED_PATH) 71 | @LRA(value = LRA.Type.NOT_SUPPORTED) 72 | Response notSupportedLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 73 | 74 | @GET 75 | @Path(NEVER_PATH) 76 | @LRA(value = LRA.Type.NEVER) 77 | Response neverLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 78 | 79 | @GET 80 | @Path(REQUIRED_WITH_END_FALSE_PATH) 81 | @LRA(value = LRA.Type.REQUIRED, end = false) 82 | Response requiredEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 83 | 84 | @GET 85 | @Path(REQUIRES_NEW_WITH_END_FALSE_PATH) 86 | @LRA(value = LRA.Type.REQUIRES_NEW, end = false) 87 | Response requiresNewEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 88 | 89 | @GET 90 | @Path(MANDATORY_WITH_END_FALSE_PATH) 91 | @LRA(value = LRA.Type.MANDATORY, end = false) 92 | Response mandatoryEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 93 | 94 | @GET 95 | @Path(SUPPORTS_WITH_END_FALSE_PATH) 96 | @LRA(value = LRA.Type.SUPPORTS, end = false) 97 | Response supportsEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 98 | 99 | @GET 100 | @Path(NOT_SUPPORTED_WITH_END_FALSE_PATH) 101 | @LRA(value = LRA.Type.NOT_SUPPORTED, end = false) 102 | Response notSupportedEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 103 | 104 | @GET 105 | @Path(NEVER_WITH_END_FALSE_PATH) 106 | @LRA(value = LRA.Type.NEVER, end = false) 107 | Response neverEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 108 | } 109 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckInterfaceResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import java.net.URI; 23 | 24 | import jakarta.ws.rs.Path; 25 | import jakarta.ws.rs.core.Response; 26 | 27 | @Path(LRATypeTckInterfaceResource.TCK_LRA_TYPE_INTERFACE_RESOURCE_PATH) 28 | public class LRATypeTckInterfaceResource extends ResourceParent implements LRATypeTckInterface { 29 | 30 | public static final String TCK_LRA_TYPE_INTERFACE_RESOURCE_PATH = "lra-type-tck-interface-resource"; 31 | 32 | public Response requiredLRA(URI lraId) { 33 | return Response.ok(lraId).build(); 34 | } 35 | 36 | public Response requiresNewLRA(URI lraId) { 37 | return Response.ok(lraId).build(); 38 | } 39 | 40 | public Response mandatoryLRA(URI lraId) { 41 | return Response.ok(lraId).build(); 42 | } 43 | 44 | public Response supportsLRA(URI lraId) { 45 | return Response.ok(lraId).build(); 46 | } 47 | 48 | public Response notSupportedLRA(URI lraId) { 49 | return Response.ok(lraId).build(); 50 | } 51 | 52 | public Response neverLRA(URI lraId) { 53 | return Response.ok(lraId).build(); 54 | } 55 | 56 | public Response requiredEndLRA(URI lraId) { 57 | return Response.ok(lraId).build(); 58 | } 59 | 60 | public Response requiresNewEndLRA(URI lraId) { 61 | return Response.ok(lraId).build(); 62 | } 63 | 64 | public Response mandatoryEndLRA(URI lraId) { 65 | return Response.ok(lraId).build(); 66 | } 67 | 68 | public Response supportsEndLRA(URI lraId) { 69 | return Response.ok(lraId).build(); 70 | } 71 | 72 | public Response notSupportedEndLRA(URI lraId) { 73 | return Response.ok(lraId).build(); 74 | } 75 | 76 | public Response neverEndLRA(URI lraId) { 77 | return Response.ok(lraId).build(); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; 23 | 24 | import java.net.URI; 25 | 26 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 27 | 28 | import jakarta.enterprise.context.ApplicationScoped; 29 | import jakarta.ws.rs.GET; 30 | import jakarta.ws.rs.HeaderParam; 31 | import jakarta.ws.rs.Path; 32 | import jakarta.ws.rs.core.Response; 33 | 34 | @ApplicationScoped 35 | @Path(LRATypeTckResource.TCK_LRA_TYPE_RESOURCE_PATH) 36 | public class LRATypeTckResource extends ResourceParent { 37 | 38 | public static final String TCK_LRA_TYPE_RESOURCE_PATH = "lra-type-tck-resource"; 39 | 40 | public static final String REQUIRED_PATH = "/required"; 41 | public static final String REQUIRES_NEW_PATH = "/requires-new"; 42 | public static final String SUPPORTS_PATH = "/supports"; 43 | public static final String NOT_SUPPORTED_PATH = "/not-supported"; 44 | public static final String MANDATORY_PATH = "/mandatory"; 45 | public static final String NEVER_PATH = "/never"; 46 | 47 | public static final String REQUIRED_WITH_END_FALSE_PATH = "/end-required"; 48 | public static final String REQUIRES_NEW_WITH_END_FALSE_PATH = "/end-requires-new"; 49 | public static final String SUPPORTS_WITH_END_FALSE_PATH = "/end-supports"; 50 | public static final String NOT_SUPPORTED_WITH_END_FALSE_PATH = "/end-not-supported"; 51 | public static final String MANDATORY_WITH_END_FALSE_PATH = "/end-mandatory"; 52 | public static final String NEVER_WITH_END_FALSE_PATH = "/end-never"; 53 | 54 | // resource methods for each LRA.Type attribute 55 | 56 | @GET 57 | @Path(REQUIRED_PATH) 58 | @LRA(value = LRA.Type.REQUIRED) 59 | public Response requiredLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 60 | return Response.ok(lraId).build(); 61 | } 62 | 63 | @GET 64 | @Path(REQUIRES_NEW_PATH) 65 | @LRA(value = LRA.Type.REQUIRES_NEW) 66 | public Response requiresNewLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 67 | return Response.ok(lraId).build(); 68 | } 69 | 70 | @GET 71 | @Path(MANDATORY_PATH) 72 | @LRA(value = LRA.Type.MANDATORY) 73 | public Response mandatoryLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 74 | return Response.ok(lraId).build(); 75 | } 76 | 77 | @GET 78 | @Path(SUPPORTS_PATH) 79 | @LRA(value = LRA.Type.SUPPORTS) 80 | public Response supportsLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 81 | return Response.ok(lraId).build(); 82 | } 83 | 84 | @GET 85 | @Path(NOT_SUPPORTED_PATH) 86 | @LRA(value = LRA.Type.NOT_SUPPORTED) 87 | public Response notSupportedLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 88 | return Response.ok(lraId).build(); 89 | } 90 | 91 | @GET 92 | @Path(NEVER_PATH) 93 | @LRA(value = LRA.Type.NEVER) 94 | public Response neverLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 95 | return Response.ok(lraId).build(); 96 | } 97 | 98 | // similar set of resources methods but with the LRA.end attribute set to false 99 | 100 | @GET 101 | @Path(REQUIRED_WITH_END_FALSE_PATH) 102 | @LRA(value = LRA.Type.REQUIRED, end = false) 103 | public Response requiredEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 104 | return Response.ok(lraId).build(); 105 | } 106 | 107 | @GET 108 | @Path(REQUIRES_NEW_WITH_END_FALSE_PATH) 109 | @LRA(value = LRA.Type.REQUIRES_NEW, end = false) 110 | public Response requiresNewEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 111 | return Response.ok(lraId).build(); 112 | } 113 | 114 | @GET 115 | @Path(MANDATORY_WITH_END_FALSE_PATH) 116 | @LRA(value = LRA.Type.MANDATORY, end = false) 117 | public Response mandatoryEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 118 | return Response.ok(lraId).build(); 119 | } 120 | 121 | @GET 122 | @Path(SUPPORTS_WITH_END_FALSE_PATH) 123 | @LRA(value = LRA.Type.SUPPORTS, end = false) 124 | public Response supportsEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 125 | return Response.ok(lraId).build(); 126 | } 127 | 128 | @GET 129 | @Path(NOT_SUPPORTED_WITH_END_FALSE_PATH) 130 | @LRA(value = LRA.Type.NOT_SUPPORTED, end = false) 131 | public Response notSupportedEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 132 | return Response.ok(lraId).build(); 133 | } 134 | 135 | @GET 136 | @Path(NEVER_WITH_END_FALSE_PATH) 137 | @LRA(value = LRA.Type.NEVER, end = false) 138 | public Response neverEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 139 | return Response.ok(lraId).build(); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckSuperclass.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; 23 | 24 | import java.net.URI; 25 | 26 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 27 | 28 | import jakarta.ws.rs.GET; 29 | import jakarta.ws.rs.HeaderParam; 30 | import jakarta.ws.rs.Path; 31 | import jakarta.ws.rs.core.Response; 32 | 33 | public abstract class LRATypeTckSuperclass extends ResourceParent { 34 | 35 | public static final String REQUIRED_PATH = "/required"; 36 | public static final String REQUIRES_NEW_PATH = "/requires-new"; 37 | public static final String SUPPORTS_PATH = "/supports"; 38 | public static final String NOT_SUPPORTED_PATH = "/not-supported"; 39 | public static final String MANDATORY_PATH = "/mandatory"; 40 | public static final String NEVER_PATH = "/never"; 41 | 42 | public static final String REQUIRED_WITH_END_FALSE_PATH = "/end-required"; 43 | public static final String REQUIRES_NEW_WITH_END_FALSE_PATH = "/end-requires-new"; 44 | public static final String SUPPORTS_WITH_END_FALSE_PATH = "/end-supports"; 45 | public static final String NOT_SUPPORTED_WITH_END_FALSE_PATH = "/end-not-supported"; 46 | public static final String MANDATORY_WITH_END_FALSE_PATH = "/end-mandatory"; 47 | public static final String NEVER_WITH_END_FALSE_PATH = "/end-never"; 48 | 49 | @GET 50 | @Path(REQUIRED_PATH) 51 | @LRA(value = LRA.Type.REQUIRED) 52 | public abstract Response requiredLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 53 | 54 | @GET 55 | @Path(REQUIRES_NEW_PATH) 56 | @LRA(value = LRA.Type.REQUIRES_NEW) 57 | public abstract Response requiresNewLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 58 | 59 | @GET 60 | @Path(MANDATORY_PATH) 61 | @LRA(value = LRA.Type.MANDATORY) 62 | public abstract Response mandatoryLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 63 | 64 | @GET 65 | @Path(SUPPORTS_PATH) 66 | @LRA(value = LRA.Type.SUPPORTS) 67 | public abstract Response supportsLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 68 | 69 | @GET 70 | @Path(NOT_SUPPORTED_PATH) 71 | @LRA(value = LRA.Type.NOT_SUPPORTED) 72 | public abstract Response notSupportedLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 73 | 74 | @GET 75 | @Path(NEVER_PATH) 76 | @LRA(value = LRA.Type.NEVER) 77 | public abstract Response neverLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 78 | 79 | @GET 80 | @Path(REQUIRED_WITH_END_FALSE_PATH) 81 | @LRA(value = LRA.Type.REQUIRED, end = false) 82 | public abstract Response requiredEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 83 | 84 | @GET 85 | @Path(REQUIRES_NEW_WITH_END_FALSE_PATH) 86 | @LRA(value = LRA.Type.REQUIRES_NEW, end = false) 87 | public abstract Response requiresNewEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 88 | 89 | @GET 90 | @Path(MANDATORY_WITH_END_FALSE_PATH) 91 | @LRA(value = LRA.Type.MANDATORY, end = false) 92 | public abstract Response mandatoryEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 93 | 94 | @GET 95 | @Path(SUPPORTS_WITH_END_FALSE_PATH) 96 | @LRA(value = LRA.Type.SUPPORTS, end = false) 97 | public abstract Response supportsEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 98 | 99 | @GET 100 | @Path(NOT_SUPPORTED_WITH_END_FALSE_PATH) 101 | @LRA(value = LRA.Type.NOT_SUPPORTED, end = false) 102 | public abstract Response notSupportedEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 103 | 104 | @GET 105 | @Path(NEVER_WITH_END_FALSE_PATH) 106 | @LRA(value = LRA.Type.NEVER, end = false) 107 | public abstract Response neverEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId); 108 | } 109 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRATypeTckSuperclassResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import java.net.URI; 23 | 24 | import jakarta.ws.rs.Path; 25 | import jakarta.ws.rs.core.Response; 26 | 27 | @Path(LRATypeTckSuperclassResource.TCK_LRA_TYPE_SUPERCLASS_RESOURCE_PATH) 28 | public class LRATypeTckSuperclassResource extends LRATypeTckSuperclass { 29 | 30 | public static final String TCK_LRA_TYPE_SUPERCLASS_RESOURCE_PATH = "lra-type-tck-superclass-resource"; 31 | 32 | public Response requiredLRA(URI lraId) { 33 | return Response.ok(lraId).build(); 34 | } 35 | 36 | public Response requiresNewLRA(URI lraId) { 37 | return Response.ok(lraId).build(); 38 | } 39 | 40 | public Response mandatoryLRA(URI lraId) { 41 | return Response.ok(lraId).build(); 42 | } 43 | 44 | public Response supportsLRA(URI lraId) { 45 | return Response.ok(lraId).build(); 46 | } 47 | 48 | public Response notSupportedLRA(URI lraId) { 49 | return Response.ok(lraId).build(); 50 | } 51 | 52 | public Response neverLRA(URI lraId) { 53 | return Response.ok(lraId).build(); 54 | } 55 | 56 | public Response requiredEndLRA(URI lraId) { 57 | return Response.ok(lraId).build(); 58 | } 59 | 60 | public Response requiresNewEndLRA(URI lraId) { 61 | return Response.ok(lraId).build(); 62 | } 63 | 64 | public Response mandatoryEndLRA(URI lraId) { 65 | return Response.ok(lraId).build(); 66 | } 67 | 68 | public Response supportsEndLRA(URI lraId) { 69 | return Response.ok(lraId).build(); 70 | } 71 | 72 | public Response notSupportedEndLRA(URI lraId) { 73 | return Response.ok(lraId).build(); 74 | } 75 | 76 | public Response neverEndLRA(URI lraId) { 77 | return Response.ok(lraId).build(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/LRAUnknownResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; 23 | 24 | import java.net.URI; 25 | import java.util.HashMap; 26 | import java.util.Map; 27 | import java.util.logging.Logger; 28 | 29 | import org.eclipse.microprofile.lra.annotation.Compensate; 30 | import org.eclipse.microprofile.lra.annotation.Complete; 31 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 32 | import org.eclipse.microprofile.lra.tck.service.LRAMetricService; 33 | import org.eclipse.microprofile.lra.tck.service.LRAMetricType; 34 | 35 | import jakarta.enterprise.context.ApplicationScoped; 36 | import jakarta.inject.Inject; 37 | import jakarta.ws.rs.HeaderParam; 38 | import jakarta.ws.rs.NotFoundException; 39 | import jakarta.ws.rs.PUT; 40 | import jakarta.ws.rs.Path; 41 | import jakarta.ws.rs.Produces; 42 | import jakarta.ws.rs.QueryParam; 43 | import jakarta.ws.rs.core.MediaType; 44 | import jakarta.ws.rs.core.Response; 45 | 46 | /** 47 | * TCK Tests related to the 410 status code handling. Version without a Status method. 48 | */ 49 | @ApplicationScoped 50 | @Path(LRAUnknownResource.LRA_CONTROLLER_PATH) 51 | public class LRAUnknownResource extends ResourceParent { 52 | public static final String LRA_CONTROLLER_PATH = "lraUnknownController"; 53 | public static final String TRANSACTIONAL_WORK_PATH = "work"; 54 | 55 | private static final Logger LOGGER = Logger.getLogger(LRAUnknownResource.class.getName()); 56 | private static final String AFTER_LRA = "/after"; 57 | 58 | private Map scenarioMap = new HashMap<>(); 59 | 60 | @Inject 61 | private LRAMetricService lraMetricService; 62 | 63 | @PUT 64 | @Path(TRANSACTIONAL_WORK_PATH) 65 | @LRA 66 | public Response activityWithLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId, 67 | @QueryParam("scenario") Scenario scenario) { 68 | 69 | scenarioMap.put(lraId.toASCIIString(), scenario); 70 | // scenario.pathResponseCode determines if /complete or /compensate will be called. 71 | return Response.status(scenario.getPathResponseCode()).entity(lraId).build(); 72 | } 73 | 74 | @PUT 75 | @Path("/complete") 76 | @Produces(MediaType.APPLICATION_JSON) 77 | @Complete 78 | public Response completeWork(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) 79 | throws NotFoundException { 80 | lraMetricService.incrementMetric(LRAMetricType.Completed, lraId, LRAUnknownResource.class); 81 | 82 | // flow for the following cases 83 | // Scenario.COMPLETE_RETRY 84 | // -> /complete -> 202 85 | // -> /complete -> 410 (recalled to find final status by implementation) 86 | 87 | // Scenario.COMPLETE_IMMEDIATE 88 | // -> /complete -> 410 89 | 90 | int responseCode = 410; 91 | Scenario scenario = scenarioMap.get(lraId.toASCIIString()); 92 | if (scenario == Scenario.COMPLETE_RETRY) { 93 | responseCode = 202; // The 'action' is in progress 94 | scenarioMap.remove(lraId.toASCIIString()); // so that by next call the return status is 410. 95 | } 96 | 97 | LOGGER.info(String.format("LRA id '%s' was completed", lraId.toASCIIString())); 98 | return Response.status(responseCode).build(); 99 | } 100 | 101 | @PUT 102 | @Path("/compensate") 103 | @Produces(MediaType.APPLICATION_JSON) 104 | @Compensate 105 | public Response compensateWork(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) 106 | throws NotFoundException { 107 | 108 | lraMetricService.incrementMetric(LRAMetricType.Compensated, lraId, LRAUnknownResource.class); 109 | 110 | // flow for the following cases 111 | // Scenario.COMPENSATE_RETRY 112 | // -> /compensate -> 202 113 | // -> /compensate -> 410 (recalled to find final status by implementation) 114 | 115 | // Scenario.COMPENSATE_IMMEDIATE 116 | // -> /compensate -> 410 117 | 118 | int responseCode = 410; 119 | Scenario scenario = scenarioMap.get(lraId.toASCIIString()); 120 | if (scenario == Scenario.COMPENSATE_RETRY) { 121 | responseCode = 202; // The 'action' is in progress 122 | scenarioMap.remove(lraId.toASCIIString()); // so that by next call the return status is 410. 123 | } 124 | 125 | LOGGER.info(String.format("LRA id '%s' was compensated", lraId)); 126 | return Response.status(responseCode).build(); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/NoLRAResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; 23 | import static org.eclipse.microprofile.lra.tck.participant.api.LraResource.LRA_RESOURCE_PATH; 24 | 25 | import java.net.URI; 26 | 27 | import jakarta.enterprise.context.ApplicationScoped; 28 | import jakarta.ws.rs.HeaderParam; 29 | import jakarta.ws.rs.PUT; 30 | import jakarta.ws.rs.Path; 31 | import jakarta.ws.rs.WebApplicationException; 32 | import jakarta.ws.rs.client.ClientBuilder; 33 | import jakarta.ws.rs.client.Entity; 34 | import jakarta.ws.rs.client.WebTarget; 35 | import jakarta.ws.rs.core.Context; 36 | import jakarta.ws.rs.core.Response; 37 | import jakarta.ws.rs.core.UriInfo; 38 | 39 | @ApplicationScoped 40 | @Path(NoLRAResource.NO_LRA_RESOURCE_PATH) 41 | public class NoLRAResource { 42 | public static final String NO_LRA_RESOURCE_PATH = "nolraresource"; 43 | public static final String NON_TRANSACTIONAL_WORK_PATH = "work"; 44 | 45 | @Context 46 | private UriInfo context; 47 | 48 | @PUT 49 | @Path(NON_TRANSACTIONAL_WORK_PATH) 50 | public Response work2(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 51 | 52 | if (lraId != null) { 53 | return Response.status(Response.Status.PRECONDITION_FAILED).entity("Unexpected LRA context").build(); 54 | } 55 | 56 | WebTarget resourcePath = ClientBuilder.newClient().target(context.getBaseUri()) 57 | .path(LRA_RESOURCE_PATH) 58 | .path(LraResource.MANDATORY_LRA_RESOURCE_PATH); 59 | 60 | Response response = resourcePath.request().put(Entity.text("")); 61 | 62 | String id = checkStatusAndClose(response, Response.Status.OK.getStatusCode(), true, resourcePath); 63 | 64 | if (id == null) { 65 | return Response.status(Response.Status.PRECONDITION_FAILED).entity("LRA context was not propagated") 66 | .build(); 67 | } 68 | 69 | return Response.ok(id).build(); 70 | } 71 | 72 | private String checkStatusAndClose(Response response, int expected, boolean readEntity, WebTarget webTarget) { 73 | try { 74 | if (expected != -1 && response.getStatus() != expected) { 75 | if (webTarget != null) { 76 | throw new WebApplicationException( 77 | String.format("%s: expected status %d got %d", 78 | webTarget.getUri().toString(), expected, response.getStatus()), 79 | response); 80 | } 81 | 82 | throw new WebApplicationException(response); 83 | } 84 | 85 | if (readEntity) { 86 | return response.readEntity(String.class); 87 | } 88 | } finally { 89 | response.close(); 90 | } 91 | 92 | return null; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/NonParticipatingTckResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; 23 | 24 | import java.net.URI; 25 | 26 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 27 | import org.eclipse.microprofile.lra.tck.LRAClientOps; 28 | 29 | import jakarta.enterprise.context.ApplicationScoped; 30 | import jakarta.ws.rs.DefaultValue; 31 | import jakarta.ws.rs.HeaderParam; 32 | import jakarta.ws.rs.PUT; 33 | import jakarta.ws.rs.Path; 34 | import jakarta.ws.rs.QueryParam; 35 | import jakarta.ws.rs.client.Client; 36 | import jakarta.ws.rs.client.ClientBuilder; 37 | import jakarta.ws.rs.client.WebTarget; 38 | import jakarta.ws.rs.core.Context; 39 | import jakarta.ws.rs.core.Response; 40 | import jakarta.ws.rs.core.UriInfo; 41 | 42 | @ApplicationScoped 43 | @Path(NonParticipatingTckResource.TCK_NON_PARTICIPANT_RESOURCE_PATH) 44 | @LRA(value = LRA.Type.SUPPORTS, end = false) 45 | public class NonParticipatingTckResource extends ResourceParent { 46 | public static final String TCK_NON_PARTICIPANT_RESOURCE_PATH = "non-participating-tck-resource"; 47 | 48 | public static final String START_AND_END_PATH = "/start-and-end"; 49 | public static final String START_BUT_DONT_END_PATH = "/start-dont-end"; 50 | public static final String START_AND_END_NESTED_PATH = "/start-nested-and-end"; 51 | 52 | public static final String START_BUT_DONT_END_NESTED_PATH = "/start-nested-and-dont-end"; 53 | public static final String NEVER_PATH = "/never"; 54 | public static final String END_PATH = "/end"; 55 | public static final String SUPPORTS_PATH = "/supports"; 56 | 57 | public static final String STATUS_CODE_QUERY_NAME = "Coerce-Status"; 58 | public static final String START_LRA_VIA_REMOTE_INVOCATION = "/start-via-remote-invocation"; 59 | 60 | @Context 61 | private UriInfo context; 62 | 63 | @PUT 64 | @Path(NonParticipatingTckResource.NEVER_PATH) 65 | @LRA(value = LRA.Type.NEVER) 66 | public Response neverRunWithLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 67 | return Response.ok(lraId).build(); 68 | } 69 | 70 | @PUT 71 | @Path(SUPPORTS_PATH) 72 | @LRA(value = LRA.Type.SUPPORTS, end = false) 73 | public Response supports(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 74 | return Response.ok(lraId).build(); 75 | } 76 | 77 | @PUT 78 | @Path(NonParticipatingTckResource.START_AND_END_PATH) 79 | @LRA(value = LRA.Type.REQUIRES_NEW, cancelOnFamily = Response.Status.Family.SERVER_ERROR) // default is to end the 80 | // LRA 81 | public Response startAndEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId, 82 | @DefaultValue("200") @QueryParam(STATUS_CODE_QUERY_NAME) int coerceStatus) { 83 | return Response.status(coerceStatus).entity(checkLRANotNull(lraId)).build(); 84 | } 85 | 86 | @PUT 87 | @Path(NonParticipatingTckResource.START_BUT_DONT_END_PATH) 88 | @LRA(value = LRA.Type.REQUIRES_NEW, end = false, cancelOnFamily = Response.Status.Family.SERVER_ERROR) 89 | public Response startDontEndLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId, 90 | @DefaultValue("200") @QueryParam(STATUS_CODE_QUERY_NAME) int coerceStatus) { 91 | return Response.status(coerceStatus).entity(checkLRANotNull(lraId)).build(); 92 | } 93 | 94 | @PUT 95 | @Path(NonParticipatingTckResource.END_PATH) 96 | @LRA(value = LRA.Type.MANDATORY, cancelOnFamily = Response.Status.Family.SERVER_ERROR) // default is to end the LRA 97 | public Response endLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId, 98 | @DefaultValue("200") @QueryParam(STATUS_CODE_QUERY_NAME) int coerceStatus) { 99 | return Response.status(coerceStatus).entity(checkLRANotNull(lraId)).build(); 100 | } 101 | 102 | @PUT 103 | @Path(NonParticipatingTckResource.START_AND_END_NESTED_PATH) 104 | @LRA(value = LRA.Type.NESTED, cancelOnFamily = Response.Status.Family.SERVER_ERROR) // default is to end the LRA 105 | public Response startAndEndNestedLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 106 | return Response.ok(lraId).build(); 107 | } 108 | 109 | @PUT 110 | @Path(NonParticipatingTckResource.START_BUT_DONT_END_NESTED_PATH) 111 | @LRA(value = LRA.Type.NESTED, end = false, cancelOnFamily = Response.Status.Family.SERVER_ERROR) 112 | public Response startAndDontEndNestedLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 113 | return Response.ok(lraId).build(); 114 | } 115 | 116 | @PUT 117 | @Path(NonParticipatingTckResource.START_LRA_VIA_REMOTE_INVOCATION) 118 | @LRA(value = LRA.Type.SUPPORTS, end = false, cancelOnFamily = Response.Status.Family.SERVER_ERROR) 119 | public Response notSupportedButCallServiceWhichStartsButDoesntEndAnLRA( 120 | @HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 121 | return Response.ok(invokeRestEndpoint(lraId, TCK_NON_PARTICIPANT_RESOURCE_PATH, START_BUT_DONT_END_PATH, 122 | 200)).build(); 123 | } 124 | 125 | private String invokeRestEndpoint(URI lra, String basePath, String path, int coerceResponse) { 126 | Client client = ClientBuilder.newClient(); 127 | 128 | try { 129 | WebTarget target = client.target(context.getBaseUri()); 130 | return new LRAClientOps(target).invokeRestEndpointAndReturnLRA(lra, basePath, path, coerceResponse); 131 | } finally { 132 | client.close(); 133 | } 134 | } 135 | 136 | private URI checkLRANotNull(URI lraId) { 137 | if (lraId == null) { 138 | throw new WrongHeaderException( 139 | String.format("%s: missing '%s' header", context.getPath(), LRA_HTTP_CONTEXT_HEADER)); 140 | } 141 | 142 | return lraId; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/ParticipatingTckResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; 23 | 24 | import java.net.URI; 25 | import java.util.logging.Logger; 26 | 27 | import org.eclipse.microprofile.lra.annotation.Compensate; 28 | import org.eclipse.microprofile.lra.annotation.Complete; 29 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 30 | import org.eclipse.microprofile.lra.annotation.ws.rs.Leave; 31 | import org.eclipse.microprofile.lra.tck.service.LRAMetricService; 32 | import org.eclipse.microprofile.lra.tck.service.LRAMetricType; 33 | 34 | import jakarta.enterprise.context.ApplicationScoped; 35 | import jakarta.inject.Inject; 36 | import jakarta.ws.rs.DefaultValue; 37 | import jakarta.ws.rs.GET; 38 | import jakarta.ws.rs.HeaderParam; 39 | import jakarta.ws.rs.PUT; 40 | import jakarta.ws.rs.Path; 41 | import jakarta.ws.rs.QueryParam; 42 | import jakarta.ws.rs.core.Response; 43 | 44 | @ApplicationScoped 45 | @Path(ParticipatingTckResource.TCK_PARTICIPANT_RESOURCE_PATH) 46 | public class ParticipatingTckResource { 47 | private static final Logger LOGGER = Logger.getLogger(ParticipatingTckResource.class.getName()); 48 | 49 | public static final String TCK_PARTICIPANT_RESOURCE_PATH = "participating-tck-resource"; 50 | public static final String JOIN_WITH_EXISTING_LRA_PATH = "/join-with-existing-lra"; 51 | public static final String JOIN_WITH_EXISTING_LRA_PATH2 = "/join-with-existing-lra2"; 52 | public static final String JOIN_WITH_NEW_LRA_PATH = "/join-with-new-LRA"; 53 | public static final String LEAVE_PATH = "/leave"; 54 | public static final String ACCEPT_PATH = "/accept"; 55 | 56 | public static final String RECOVERY_PARAM = "recoveryCount"; 57 | 58 | private int recoveryPasses = 0; 59 | 60 | @Inject 61 | private LRAMetricService lraMetricService; 62 | 63 | @PUT 64 | @Path("/compensate") 65 | @Compensate 66 | public Response compensateWork(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 67 | if (lraId == null) { 68 | throw new NullPointerException("lraId can't be null as it should be invoked with the context"); 69 | } 70 | 71 | LOGGER.info(String.format("LRA id '%s' was told to compensate", lraId)); 72 | 73 | return getEndPhaseResponse(false, lraId); 74 | } 75 | 76 | @PUT 77 | @Path("/complete") 78 | @Complete 79 | public Response completeWork(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 80 | if (lraId == null) { 81 | throw new NullPointerException("lraId can't be null as it should be invoked with the context"); 82 | } 83 | 84 | LOGGER.info(String.format("LRA id '%s' was told to complete", lraId)); 85 | 86 | return getEndPhaseResponse(true, lraId); 87 | } 88 | 89 | private Response getEndPhaseResponse(boolean complete, URI lraId) { 90 | if (--recoveryPasses > 0) { 91 | return Response.accepted().build(); 92 | } 93 | 94 | if (complete) { 95 | lraMetricService.incrementMetric(LRAMetricType.Completed, lraId, ParticipatingTckResource.class); 96 | } else { 97 | lraMetricService.incrementMetric(LRAMetricType.Compensated, lraId, ParticipatingTckResource.class); 98 | } 99 | 100 | return Response.ok().build(); 101 | } 102 | 103 | @PUT 104 | @Path(ACCEPT_PATH) 105 | @LRA(value = LRA.Type.REQUIRES_NEW) 106 | public Response acceptLRA(@QueryParam(RECOVERY_PARAM) @DefaultValue("0") Integer recoveryPasses) { 107 | this.recoveryPasses = recoveryPasses; 108 | 109 | return Response.ok().build(); 110 | } 111 | 112 | @GET 113 | @Path(ACCEPT_PATH) 114 | public Response getAcceptLRA() { 115 | return Response.ok(this.recoveryPasses).build(); 116 | } 117 | 118 | @PUT 119 | @Path(LEAVE_PATH) 120 | @LRA(value = LRA.Type.SUPPORTS, end = false) 121 | @Leave 122 | public Response leaveLRA() { 123 | return Response.ok().build(); 124 | } 125 | 126 | // if this resource path is invoked outside of a LRA then, since this JAX-RS resoruce is annotated 127 | // as a participant, the implementation MUST report a PRECONDITION_FAILED status 128 | @PUT 129 | @Path(ParticipatingTckResource.JOIN_WITH_EXISTING_LRA_PATH) 130 | @LRA(value = LRA.Type.MANDATORY, end = false, cancelOnFamily = {}) 131 | public Response joinWithExistingLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 132 | return Response.ok().build(); 133 | } 134 | 135 | @PUT 136 | @Path(ParticipatingTckResource.JOIN_WITH_EXISTING_LRA_PATH2) 137 | @LRA(value = LRA.Type.MANDATORY, end = false) 138 | public Response joinWithExistingLRA2(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 139 | return Response.ok().build(); 140 | } 141 | 142 | @PUT 143 | @Path(ParticipatingTckResource.JOIN_WITH_NEW_LRA_PATH) 144 | @LRA(value = LRA.Type.REQUIRES_NEW, end = false) 145 | public Response joinWithNewLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 146 | return Response.ok().build(); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/RecoveryResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_CONTEXT_HEADER; 23 | 24 | import java.net.URI; 25 | import java.time.temporal.ChronoUnit; 26 | 27 | import org.eclipse.microprofile.lra.annotation.AfterLRA; 28 | import org.eclipse.microprofile.lra.annotation.Compensate; 29 | import org.eclipse.microprofile.lra.annotation.LRAStatus; 30 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 31 | import org.eclipse.microprofile.lra.tck.service.LRAMetricService; 32 | import org.eclipse.microprofile.lra.tck.service.LRAMetricType; 33 | 34 | import jakarta.enterprise.context.ApplicationScoped; 35 | import jakarta.inject.Inject; 36 | import jakarta.ws.rs.HeaderParam; 37 | import jakarta.ws.rs.PUT; 38 | import jakarta.ws.rs.Path; 39 | import jakarta.ws.rs.core.Response; 40 | 41 | @Path(RecoveryResource.RECOVERY_RESOURCE_PATH) 42 | @ApplicationScoped 43 | public class RecoveryResource { 44 | 45 | public static final String RECOVERY_RESOURCE_PATH = "recovery-resource"; 46 | public static final String REQUIRED_PATH = "required"; 47 | public static final String REQUIRED_TIMEOUT_PATH = "required-timeout"; 48 | public static final long LRA_TIMEOUT = 500; 49 | 50 | @Inject 51 | LRAMetricService lraMetricService; 52 | 53 | @PUT 54 | @Path(REQUIRED_PATH) 55 | @LRA(value = LRA.Type.REQUIRED, end = false) 56 | public Response requiredLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 57 | return Response.ok(lraId).build(); 58 | } 59 | 60 | @PUT 61 | @Path(REQUIRED_TIMEOUT_PATH) 62 | @LRA(value = LRA.Type.REQUIRED, end = false, timeLimit = LRA_TIMEOUT, timeUnit = ChronoUnit.MILLIS) 63 | public Response requiredTimeoutLRA(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 64 | return Response.ok(lraId).build(); 65 | } 66 | 67 | @PUT 68 | @Path("/compensate") 69 | @Compensate 70 | public Response compensate(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) URI lraId) { 71 | lraMetricService.incrementMetric(LRAMetricType.Compensated, lraId, RecoveryResource.class); 72 | 73 | return Response.ok().build(); 74 | } 75 | 76 | @PUT 77 | @Path("/after") 78 | @AfterLRA 79 | public Response afterLRA(@HeaderParam(LRA.LRA_HTTP_ENDED_CONTEXT_HEADER) URI lraId, LRAStatus lraStatus) { 80 | lraMetricService.incrementMetric(LRAMetricType.valueOf(lraStatus.name()), lraId, RecoveryResource.class); 81 | 82 | return Response.ok().build(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/ResourceParent.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_ENDED_CONTEXT_HEADER; 23 | 24 | import java.net.URI; 25 | 26 | import org.eclipse.microprofile.lra.annotation.AfterLRA; 27 | import org.eclipse.microprofile.lra.annotation.LRAStatus; 28 | import org.eclipse.microprofile.lra.tck.service.LRAMetricService; 29 | import org.eclipse.microprofile.lra.tck.service.LRAMetricType; 30 | import org.eclipse.microprofile.lra.tck.service.LRATestService; 31 | 32 | import jakarta.enterprise.context.ApplicationScoped; 33 | import jakarta.inject.Inject; 34 | import jakarta.ws.rs.HeaderParam; 35 | import jakarta.ws.rs.PUT; 36 | import jakarta.ws.rs.Path; 37 | import jakarta.ws.rs.core.Context; 38 | import jakarta.ws.rs.core.Response; 39 | import jakarta.ws.rs.core.UriInfo; 40 | 41 | @ApplicationScoped 42 | public class ResourceParent { 43 | 44 | @Inject 45 | private LRATestService lraTestService; 46 | 47 | @Inject 48 | private LRAMetricService lraMetricService; 49 | 50 | @Context 51 | private UriInfo context; 52 | 53 | @PUT 54 | @Path("/after") 55 | @AfterLRA 56 | public Response afterLRA(@HeaderParam(LRA_HTTP_ENDED_CONTEXT_HEADER) URI endedLRAId, LRAStatus status) { 57 | Response response = lraTestService.processAfterLRAInfo(endedLRAId, status, this.getClass(), context.getPath()); 58 | lraMetricService.incrementMetric(LRAMetricType.AfterLRA, endedLRAId, this.getClass()); 59 | return response; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/Scenario.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | public enum Scenario { 23 | COMPENSATE_IMMEDIATE(500), COMPENSATE_RETRY(500), COMPLETE_IMMEDIATE(200), COMPLETE_RETRY(200); 24 | 25 | private int pathResponseCode; 26 | 27 | Scenario(int pathResponseCode) { 28 | this.pathResponseCode = pathResponseCode; 29 | } 30 | 31 | public int getPathResponseCode() { 32 | return pathResponseCode; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/UriMessageBodyWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import java.io.IOException; 23 | import java.io.OutputStream; 24 | import java.lang.annotation.Annotation; 25 | import java.lang.reflect.Type; 26 | import java.net.URI; 27 | 28 | import jakarta.ws.rs.Produces; 29 | import jakarta.ws.rs.WebApplicationException; 30 | import jakarta.ws.rs.core.MediaType; 31 | import jakarta.ws.rs.core.MultivaluedMap; 32 | import jakarta.ws.rs.ext.MessageBodyWriter; 33 | import jakarta.ws.rs.ext.Provider; 34 | 35 | @Provider 36 | @Produces(MediaType.TEXT_PLAIN) 37 | public class UriMessageBodyWriter implements MessageBodyWriter { 38 | @Override 39 | public boolean isWriteable(Class aClass, Type type, Annotation[] annotations, MediaType mediaType) { 40 | return type == URI.class; 41 | } 42 | 43 | @Override 44 | public long getSize(URI uri, Class aClass, Type type, Annotation[] annotations, MediaType mediaType) { 45 | return -1; 46 | } 47 | 48 | @Override 49 | public void writeTo(URI uri, Class aClass, Type type, Annotation[] annotations, MediaType mediaType, 50 | MultivaluedMap multivaluedMap, OutputStream outputStream) 51 | throws IOException, WebApplicationException { 52 | outputStream.write(uri.toASCIIString().getBytes()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/api/WrongHeaderException.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.api; 21 | 22 | import jakarta.ws.rs.WebApplicationException; 23 | 24 | public class WrongHeaderException extends WebApplicationException { 25 | 26 | /** 27 | * Wrong header exception. 28 | * 29 | * @param message 30 | * error message of this exception 31 | */ 32 | public WrongHeaderException(String message) { 33 | super(message); 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/invalid/LRAResourceWithoutCompensateOrAfteRLRA.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.invalid; 21 | 22 | import java.net.URI; 23 | 24 | import org.eclipse.microprofile.lra.annotation.Complete; 25 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 26 | 27 | import jakarta.ws.rs.GET; 28 | import jakarta.ws.rs.HeaderParam; 29 | import jakarta.ws.rs.PUT; 30 | import jakarta.ws.rs.Path; 31 | import jakarta.ws.rs.WebApplicationException; 32 | import jakarta.ws.rs.core.Response; 33 | 34 | @Path(LRAResourceWithoutCompensateOrAfteRLRA.INVALID_LRA_RESOURCE_PATH) 35 | public class LRAResourceWithoutCompensateOrAfteRLRA { 36 | 37 | public static final String INVALID_LRA_RESOURCE_PATH = "/invalid-lra-resource-path"; 38 | 39 | @GET 40 | @Path("/lra") 41 | @LRA(value = LRA.Type.REQUIRES_NEW) 42 | public Response doInLRA(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) URI lraId) { 43 | return Response.ok(lraId).build(); 44 | } 45 | 46 | // intentionally don't include any of Compensate or AfterLRA methods which should fail the deployment 47 | 48 | @PUT 49 | @Path("/complete") 50 | @Complete 51 | public Response complete() { 52 | throw new WebApplicationException(500); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/nonjaxrs/InvalidAfterLRASignatureListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.nonjaxrs; 21 | 22 | import org.eclipse.microprofile.lra.annotation.AfterLRA; 23 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 24 | import org.eclipse.microprofile.lra.tck.TckInvalidSignaturesTests; 25 | 26 | import jakarta.ws.rs.GET; 27 | import jakarta.ws.rs.Path; 28 | import jakarta.ws.rs.core.Response; 29 | 30 | /** 31 | * TCK invalid LRA resource containing invalid signature for @AfterLRA method. It's used for 32 | * verification of deployment time invalid signature detection and error report in {@link TckInvalidSignaturesTests}. 33 | */ 34 | @Path(InvalidAfterLRASignatureListener.RESOURCE_PATH) 35 | public class InvalidAfterLRASignatureListener { 36 | 37 | public static final String RESOURCE_PATH = "invalid-after-lra"; 38 | public static final String START_LRA = "start-lra"; 39 | 40 | @GET 41 | @Path(START_LRA) 42 | @LRA(LRA.Type.REQUIRED) 43 | public Response doInLRA() { 44 | return Response.ok().build(); 45 | } 46 | 47 | @AfterLRA 48 | public void onLRAEnd(String lraId, String lraStatus) { 49 | // intentionally empty 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/nonjaxrs/InvalidArgumentTypesParticipant.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.nonjaxrs; 21 | 22 | import java.net.URI; 23 | 24 | import org.eclipse.microprofile.lra.annotation.Compensate; 25 | import org.eclipse.microprofile.lra.annotation.Forget; 26 | import org.eclipse.microprofile.lra.annotation.ParticipantStatus; 27 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 28 | import org.eclipse.microprofile.lra.tck.TckInvalidSignaturesTests; 29 | 30 | import jakarta.ws.rs.GET; 31 | import jakarta.ws.rs.Path; 32 | import jakarta.ws.rs.core.Response; 33 | 34 | /** 35 | * TCK invalid LRA participant containing invalid type of arguments in the participant method signature used for 36 | * verification of deployment time invalid signature detection and error report in {@link TckInvalidSignaturesTests}. 37 | */ 38 | @Path("nonjaxrs-argument-type-nonjaxrs") 39 | public class InvalidArgumentTypesParticipant { 40 | 41 | @GET 42 | @Path("enlist") 43 | @LRA(LRA.Type.REQUIRED) 44 | public Response doInLRA() { 45 | return Response.ok().build(); 46 | } 47 | 48 | @Compensate 49 | public ParticipantStatus compensate(URI lraId) { 50 | return ParticipantStatus.Compensated; 51 | } 52 | 53 | @Forget 54 | public void forget(int lraId, URI parentId) { 55 | // intentionally empty 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/nonjaxrs/InvalidReturnTypeParticipant.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.nonjaxrs; 21 | 22 | import org.eclipse.microprofile.lra.annotation.Compensate; 23 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 24 | import org.eclipse.microprofile.lra.tck.TckInvalidSignaturesTests; 25 | 26 | import jakarta.ws.rs.GET; 27 | import jakarta.ws.rs.Path; 28 | import jakarta.ws.rs.core.Response; 29 | 30 | /** 31 | * TCK invalid LRA participant containing invalid return type in the participant method signature used for verification 32 | * of deployment time invalid signature detection and error report in {@link TckInvalidSignaturesTests}. 33 | */ 34 | @Path("nonjaxrs-return-type") 35 | public class InvalidReturnTypeParticipant { 36 | 37 | @GET 38 | @Path("enlist") 39 | @LRA(LRA.Type.REQUIRED) 40 | public Response doInLRA() { 41 | return Response.ok().build(); 42 | } 43 | 44 | @Compensate 45 | public String compensate() { 46 | return "compensated"; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/nonjaxrs/TooManyArgsParticipant.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.nonjaxrs; 21 | 22 | import java.net.URI; 23 | 24 | import org.eclipse.microprofile.lra.annotation.Compensate; 25 | import org.eclipse.microprofile.lra.annotation.Complete; 26 | import org.eclipse.microprofile.lra.annotation.ParticipantStatus; 27 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 28 | import org.eclipse.microprofile.lra.tck.TckInvalidSignaturesTests; 29 | 30 | import jakarta.ws.rs.GET; 31 | import jakarta.ws.rs.Path; 32 | import jakarta.ws.rs.core.Response; 33 | 34 | /** 35 | * TCK invalid LRA participant containing too many arguments in the participant method signature used for verification 36 | * of deployment time invalid signature detection and error report in {@link TckInvalidSignaturesTests}. 37 | */ 38 | @Path("too-many-args-nonjaxrs") 39 | public class TooManyArgsParticipant { 40 | 41 | @GET 42 | @Path("enlist") 43 | @LRA(LRA.Type.REQUIRED) 44 | public Response doInLRA() { 45 | return Response.ok().build(); 46 | } 47 | 48 | @Compensate 49 | public ParticipantStatus compensate(URI lraId) { 50 | return ParticipantStatus.Compensated; 51 | } 52 | 53 | @Complete 54 | public ParticipantStatus complete(URI lraId, URI parentId, Object additional) { 55 | return ParticipantStatus.Completed; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/nonjaxrs/valid/LongBusinessMethodParticipant.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.nonjaxrs.valid; 21 | 22 | import java.net.URI; 23 | import java.util.concurrent.CountDownLatch; 24 | import java.util.logging.Logger; 25 | 26 | import org.eclipse.microprofile.lra.annotation.Compensate; 27 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 28 | import org.eclipse.microprofile.lra.tck.service.LRAMetricService; 29 | import org.eclipse.microprofile.lra.tck.service.LRAMetricType; 30 | 31 | import jakarta.enterprise.context.ApplicationScoped; 32 | import jakarta.inject.Inject; 33 | import jakarta.ws.rs.HeaderParam; 34 | import jakarta.ws.rs.PUT; 35 | import jakarta.ws.rs.Path; 36 | import jakarta.ws.rs.core.Response; 37 | 38 | @ApplicationScoped 39 | @Path(LongBusinessMethodParticipant.ROOT_PATH) 40 | public class LongBusinessMethodParticipant { 41 | 42 | public static final String ROOT_PATH = "long-business-participant"; 43 | public static final String BUSINESS_METHOD = "business-method"; 44 | public static final String SYNC_METHOD = "sync-method"; 45 | 46 | private static final Logger LOGGER = Logger.getLogger(LongBusinessMethodParticipant.class.getName()); 47 | 48 | private CountDownLatch businessLatch = new CountDownLatch(1); 49 | private CountDownLatch syncLatch = new CountDownLatch(1); 50 | 51 | @Inject 52 | private LRAMetricService lraMetricService; 53 | 54 | @Compensate 55 | public void compensate(URI lraId) { 56 | assert lraId != null; 57 | if (businessLatch.getCount() > 0) { 58 | businessLatch.countDown(); 59 | } 60 | lraMetricService.incrementMetric(LRAMetricType.Compensated, lraId, LongBusinessMethodParticipant.class); 61 | } 62 | 63 | @PUT 64 | @Path(BUSINESS_METHOD) 65 | @LRA(value = LRA.Type.MANDATORY, end = false) 66 | public Response enlistWithLongLatency(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) URI lraId) { 67 | LOGGER.info("call of enlistWithLongLatency"); 68 | try { 69 | syncLatch.countDown(); 70 | // await for compensation 71 | businessLatch.await(); 72 | return Response.ok(lraId).build(); 73 | } catch (InterruptedException ex) { 74 | return Response.serverError().build(); 75 | } 76 | } 77 | 78 | @PUT 79 | @Path(SYNC_METHOD) 80 | public Response sync() { 81 | LOGGER.info("call of sync method"); 82 | try { 83 | syncLatch.await(); 84 | } catch (Exception e) { 85 | throw new IllegalStateException( 86 | "Expecting the latch will be succesfully released on long latency LRA is in progress"); 87 | } 88 | return Response.ok().build(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/nonjaxrs/valid/ValidLRACSParticipant.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.nonjaxrs.valid; 21 | 22 | import static org.eclipse.microprofile.lra.tck.participant.api.ParticipatingTckResource.ACCEPT_PATH; 23 | import static org.eclipse.microprofile.lra.tck.participant.api.ParticipatingTckResource.RECOVERY_PARAM; 24 | 25 | import java.net.URI; 26 | import java.util.concurrent.CompletableFuture; 27 | import java.util.concurrent.CompletionStage; 28 | 29 | import org.eclipse.microprofile.lra.annotation.Compensate; 30 | import org.eclipse.microprofile.lra.annotation.Complete; 31 | import org.eclipse.microprofile.lra.annotation.ParticipantStatus; 32 | import org.eclipse.microprofile.lra.annotation.Status; 33 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 34 | import org.eclipse.microprofile.lra.tck.service.LRAMetricService; 35 | import org.eclipse.microprofile.lra.tck.service.LRAMetricType; 36 | 37 | import jakarta.enterprise.context.ApplicationScoped; 38 | import jakarta.inject.Inject; 39 | import jakarta.ws.rs.DefaultValue; 40 | import jakarta.ws.rs.GET; 41 | import jakarta.ws.rs.HeaderParam; 42 | import jakarta.ws.rs.PUT; 43 | import jakarta.ws.rs.Path; 44 | import jakarta.ws.rs.QueryParam; 45 | import jakarta.ws.rs.core.Response; 46 | 47 | /** 48 | * Valid participant resource containing async non-JAX-RS participant methods with {@link CompletionStage} return types 49 | */ 50 | @ApplicationScoped 51 | @Path(ValidLRACSParticipant.ROOT_PATH) 52 | public class ValidLRACSParticipant { 53 | 54 | public static final String ROOT_PATH = "valid-cs-participant1"; 55 | public static final String ENLIST_WITH_COMPLETE = "enlist-complete"; 56 | public static final String ENLIST_WITH_COMPENSATE = "enlist-compensate"; 57 | 58 | private int recoveryPasses; 59 | 60 | @Inject 61 | private LRAMetricService lraMetricService; 62 | 63 | @GET 64 | @Path(ENLIST_WITH_COMPLETE) 65 | @LRA(value = LRA.Type.REQUIRED) 66 | public Response enlistWithComplete(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) URI lraId) { 67 | return Response.ok(lraId).build(); 68 | } 69 | 70 | @GET 71 | @Path(ENLIST_WITH_COMPENSATE) 72 | @LRA(value = LRA.Type.REQUIRED, cancelOn = Response.Status.INTERNAL_SERVER_ERROR) 73 | public Response enlistWithCompensate(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) URI lraId) { 74 | return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(lraId).build(); 75 | } 76 | 77 | @Compensate 78 | public CompletionStage compensate(URI lraId) { 79 | assert lraId != null; 80 | 81 | return CompletableFuture.runAsync( 82 | () -> lraMetricService.incrementMetric(LRAMetricType.Compensated, lraId, ValidLRACSParticipant.class)); 83 | } 84 | 85 | @Complete 86 | public CompletionStage complete(URI lraId) { 87 | assert lraId != null; 88 | 89 | return CompletableFuture.supplyAsync(() -> { 90 | lraMetricService.incrementMetric(LRAMetricType.Completed, lraId, ValidLRACSParticipant.class); 91 | 92 | return Response.accepted().build(); // Completing 93 | }); 94 | } 95 | 96 | @Status 97 | public CompletionStage status(URI lraId) { 98 | assert lraId != null; 99 | 100 | return CompletableFuture.supplyAsync(() -> { 101 | lraMetricService.incrementMetric(LRAMetricType.Status, lraId, ValidLRACSParticipant.class); 102 | 103 | return ParticipantStatus.Completed; 104 | }); 105 | } 106 | 107 | @PUT 108 | @Path(ACCEPT_PATH) 109 | @LRA(value = LRA.Type.REQUIRES_NEW) 110 | public Response acceptLRA(@QueryParam(RECOVERY_PARAM) @DefaultValue("0") Integer recoveryPasses) { 111 | this.recoveryPasses = recoveryPasses; 112 | 113 | return Response.ok().build(); 114 | } 115 | 116 | @GET 117 | @Path(ACCEPT_PATH) 118 | public Response getAcceptLRA() { 119 | return Response.ok(this.recoveryPasses).build(); 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/participant/nonjaxrs/valid/ValidLRAParticipant.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.participant.nonjaxrs.valid; 21 | 22 | import static org.eclipse.microprofile.lra.tck.participant.api.ParticipatingTckResource.ACCEPT_PATH; 23 | import static org.eclipse.microprofile.lra.tck.participant.api.ParticipatingTckResource.RECOVERY_PARAM; 24 | 25 | import java.net.URI; 26 | import java.util.logging.Logger; 27 | 28 | import org.eclipse.microprofile.lra.annotation.AfterLRA; 29 | import org.eclipse.microprofile.lra.annotation.Compensate; 30 | import org.eclipse.microprofile.lra.annotation.Complete; 31 | import org.eclipse.microprofile.lra.annotation.Forget; 32 | import org.eclipse.microprofile.lra.annotation.LRAStatus; 33 | import org.eclipse.microprofile.lra.annotation.ParticipantStatus; 34 | import org.eclipse.microprofile.lra.annotation.Status; 35 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA; 36 | import org.eclipse.microprofile.lra.annotation.ws.rs.LRA.Type; 37 | import org.eclipse.microprofile.lra.tck.service.LRAMetricService; 38 | import org.eclipse.microprofile.lra.tck.service.LRAMetricType; 39 | 40 | import jakarta.enterprise.context.ApplicationScoped; 41 | import jakarta.inject.Inject; 42 | import jakarta.ws.rs.DefaultValue; 43 | import jakarta.ws.rs.GET; 44 | import jakarta.ws.rs.HeaderParam; 45 | import jakarta.ws.rs.PUT; 46 | import jakarta.ws.rs.Path; 47 | import jakarta.ws.rs.QueryParam; 48 | import jakarta.ws.rs.WebApplicationException; 49 | import jakarta.ws.rs.core.Response; 50 | 51 | /** 52 | * TCK valid LRA participant containing a combination of valid participant method signatures 53 | */ 54 | @ApplicationScoped 55 | @Path(ValidLRAParticipant.RESOURCE_PATH) 56 | public class ValidLRAParticipant { 57 | private static final Logger LOGGER = Logger.getLogger(ValidLRAParticipant.class.getName()); 58 | 59 | public static final String RESOURCE_PATH = "valid-nonjaxrs"; 60 | public static final String ENLIST_WITH_COMPLETE = "nonjaxrs-enlist-complete"; 61 | 62 | private int recoveryPasses; 63 | 64 | @Inject 65 | private LRAMetricService lraMetricService; 66 | 67 | @GET 68 | @Path(ENLIST_WITH_COMPLETE) 69 | @LRA(value = Type.REQUIRED) 70 | public Response enlistWithComplete(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) URI lraId) { 71 | return Response.ok(lraId).build(); 72 | } 73 | 74 | public static final String ENLIST_WITH_COMPENSATE = "nonjaxrs-enlist-compensate"; 75 | 76 | @GET 77 | @Path(ENLIST_WITH_COMPENSATE) 78 | @LRA(value = Type.REQUIRED, cancelOn = Response.Status.INTERNAL_SERVER_ERROR) 79 | public Response enlistWithCompensate(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) URI lraId) { 80 | return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(lraId).build(); 81 | } 82 | 83 | @AfterLRA 84 | public void onLRAEnd(URI lraId, LRAStatus status) { 85 | verifyLRAId(lraId); 86 | 87 | lraMetricService.incrementMetric(LRAMetricType.AfterLRA, lraId, ValidLRAParticipant.class); 88 | 89 | LOGGER.fine(String.format("LRA id '%s' was finished with status %s", 90 | lraId.toASCIIString(), status.name())); 91 | } 92 | 93 | @Complete 94 | public void completeWithException(URI lraId, URI parentId) { 95 | verifyLRAId(lraId); 96 | 97 | lraMetricService.incrementMetric(LRAMetricType.Completed, lraId, ValidLRAParticipant.class); 98 | 99 | LOGGER.fine(String.format("LRA id '%s' was completed", lraId.toASCIIString())); 100 | throw new WebApplicationException(Response.ok().build()); 101 | } 102 | 103 | @Compensate 104 | public ParticipantStatus compensate(URI lraId) { 105 | verifyLRAId(lraId); 106 | 107 | lraMetricService.incrementMetric(LRAMetricType.Compensated, lraId, ValidLRAParticipant.class); 108 | 109 | LOGGER.fine(String.format("LRA id '%s' was compensated", lraId.toASCIIString())); 110 | return ParticipantStatus.Compensating; 111 | } 112 | 113 | @Status 114 | public Response status(URI lraId) { 115 | verifyLRAId(lraId); 116 | 117 | lraMetricService.incrementMetric(LRAMetricType.Status, lraId, ValidLRAParticipant.class); 118 | 119 | LOGGER.fine(String.format("LRA id '%s' status called, return FailedToCompensate to get @Forget called", 120 | lraId.toASCIIString())); 121 | return Response.ok(ParticipantStatus.FailedToCompensate).build(); 122 | } 123 | 124 | @Forget 125 | public void forget(URI lraId) { 126 | verifyLRAId(lraId); 127 | 128 | lraMetricService.incrementMetric(LRAMetricType.Forget, lraId, ValidLRAParticipant.class); 129 | 130 | LOGGER.fine(String.format("LRA id '%s' forget called", lraId.toASCIIString())); 131 | } 132 | 133 | private void verifyLRAId(URI lraId) { 134 | if (lraId == null) { 135 | throw new NullPointerException("lraId cannot be null"); 136 | } 137 | } 138 | 139 | @PUT 140 | @Path(ACCEPT_PATH) 141 | @LRA(value = LRA.Type.REQUIRES_NEW) 142 | public Response acceptLRA(@QueryParam(RECOVERY_PARAM) @DefaultValue("0") Integer recoveryPasses) { 143 | this.recoveryPasses = recoveryPasses; 144 | 145 | return Response.ok().build(); 146 | } 147 | 148 | @GET 149 | @Path(ACCEPT_PATH) 150 | public Response getAcceptLRA() { 151 | return Response.ok(this.recoveryPasses).build(); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/service/LRAMetricRest.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.service; 21 | 22 | import java.net.URI; 23 | 24 | import jakarta.inject.Inject; 25 | import jakarta.ws.rs.GET; 26 | import jakarta.ws.rs.Path; 27 | import jakarta.ws.rs.Produces; 28 | import jakarta.ws.rs.QueryParam; 29 | import jakarta.ws.rs.core.MediaType; 30 | 31 | /** 32 | * JAX-RS endpoints for the {@link LRAMetricService}. 33 | */ 34 | @Path(LRAMetricRest.LRA_TCK_METRIC_RESOURCE_PATH) 35 | public class LRAMetricRest { 36 | public static final String LRA_TCK_METRIC_RESOURCE_PATH = "lra-tck-metric"; 37 | public static final String METRIC_PATH = "metric"; 38 | 39 | public static final String METRIC_TYPE_PARAM = "metricType"; 40 | public static final String LRA_ID_PARAM = "lraId"; 41 | public static final String PARTICIPANT_NAME_PARAM = "participantName"; 42 | 43 | @Inject 44 | private LRAMetricService lraMetricService; 45 | 46 | @Path(METRIC_PATH) 47 | @GET 48 | @Produces(MediaType.TEXT_PLAIN) 49 | public int getMetric(@QueryParam(METRIC_TYPE_PARAM) LRAMetricType metricType, @QueryParam(LRA_ID_PARAM) URI lra, 50 | @QueryParam(PARTICIPANT_NAME_PARAM) String participantName) { 51 | if (metricType == null) { 52 | throw new NullPointerException("metricType"); 53 | } 54 | if (lra == null) { 55 | throw new NullPointerException("lraId"); 56 | } 57 | if (participantName == null) { 58 | throw new NullPointerException("participantName"); 59 | } 60 | return lraMetricService.getMetric(metricType, lra, participantName); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/service/LRAMetricType.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.service; 21 | 22 | public enum LRAMetricType { 23 | // LRA statistics 24 | Closed, // an LRA that closed 25 | FailedToClose, // an LRA that failed to close 26 | Cancelled, // an LRA that was cancelled 27 | FailedToCancel, // an LRA that failed to cancel 28 | 29 | // Participant statistics 30 | Compensated, // a participant that was asked to compensate 31 | Completed, // a participant that was asked to complete 32 | Status, // a participant that was asked for its status 33 | Forget, // a participant that was told to forget 34 | Nested, // a participant callback that was invoked in the context of a parent LRA 35 | 36 | // Other statistics 37 | AfterLRA // a listener that has received a notification that an LRA finished 38 | } 39 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/service/LRATestService.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.service; 21 | 22 | import static org.eclipse.microprofile.lra.annotation.ws.rs.LRA.LRA_HTTP_ENDED_CONTEXT_HEADER; 23 | 24 | import java.net.URI; 25 | import java.net.URL; 26 | import java.util.Iterator; 27 | import java.util.ServiceLoader; 28 | import java.util.logging.Level; 29 | import java.util.logging.Logger; 30 | 31 | import org.eclipse.microprofile.lra.annotation.LRAStatus; 32 | import org.eclipse.microprofile.lra.tck.LRAClientOps; 33 | import org.eclipse.microprofile.lra.tck.participant.api.WrongHeaderException; 34 | import org.eclipse.microprofile.lra.tck.service.spi.LRACallbackException; 35 | import org.eclipse.microprofile.lra.tck.service.spi.LRARecoveryService; 36 | import org.junit.Assert; 37 | 38 | import jakarta.enterprise.context.ApplicationScoped; 39 | import jakarta.inject.Inject; 40 | import jakarta.ws.rs.client.Client; 41 | import jakarta.ws.rs.client.ClientBuilder; 42 | import jakarta.ws.rs.client.WebTarget; 43 | import jakarta.ws.rs.core.Response; 44 | 45 | @ApplicationScoped 46 | public class LRATestService { 47 | private static final Logger LOG = Logger.getLogger(LRATestService.class.getName()); 48 | 49 | private LRAClientOps lraClient; 50 | 51 | private static Client tckSuiteClient; 52 | 53 | private WebTarget tckSuiteTarget; 54 | 55 | private LRARecoveryService lraRecoveryService = loadService(LRARecoveryService.class); 56 | 57 | @Inject 58 | private LRAMetricService lraMetricService; 59 | 60 | public void start(URL deploymentURL) { 61 | tckSuiteClient = ClientBuilder.newClient(); 62 | tckSuiteTarget = tckSuiteClient.target(URI.create(deploymentURL.toExternalForm())); 63 | lraClient = new LRAClientOps(tckSuiteTarget); 64 | } 65 | 66 | public void stop() { 67 | if (tckSuiteClient != null) { 68 | tckSuiteClient.close(); 69 | } 70 | } 71 | 72 | public LRAClientOps getLRAClient() { 73 | return lraClient; 74 | } 75 | 76 | public WebTarget getTCKSuiteTarget() { 77 | return tckSuiteTarget; 78 | } 79 | 80 | public void waitForCallbacks(URI lraId) { 81 | try { 82 | lraRecoveryService.waitForCallbacks(lraId); 83 | } catch (LRACallbackException e) { 84 | LOG.log(Level.SEVERE, "Fail to 'waitForCallbacks' for LRA " + lraId, e); 85 | Assert.fail(e.getMessage()); 86 | } 87 | } 88 | 89 | public void waitForRecovery(URI lraId) { 90 | try { 91 | lraRecoveryService.waitForRecovery(lraId); 92 | } catch (LRACallbackException e) { 93 | LOG.log(Level.SEVERE, "Fail to 'waitForRecovery' for LRA " + lraId, e); 94 | Assert.fail(e.getMessage()); 95 | } 96 | } 97 | 98 | public void waitForEndPhaseReplay(URI lraId) { 99 | try { 100 | lraRecoveryService.waitForEndPhaseReplay(lraId); 101 | } catch (LRACallbackException e) { 102 | LOG.log(Level.SEVERE, "Fail to 'waitForEndPhaseReplay' for LRA " + lraId, e); 103 | Assert.fail(e.getMessage()); 104 | } 105 | } 106 | 107 | public static T loadService(Class type) { 108 | ServiceLoader serviceLoader = ServiceLoader.load(type); 109 | Iterator iterator = serviceLoader.iterator(); 110 | 111 | if (!iterator.hasNext()) { 112 | throw new IllegalStateException(String.format("No implementation of %s which is required for the " + 113 | "TCK run was found with the service loader", type.getName())); 114 | } 115 | 116 | return iterator.next(); 117 | } 118 | 119 | public void assertHeaderPresent(URI lraId, String path, String headerName) { 120 | if (lraId == null) { 121 | throw new WrongHeaderException(String.format("%s: missing '%s' header", path, headerName)); 122 | } 123 | } 124 | 125 | public Response processAfterLRAInfo(URI endedLRAId, LRAStatus status, Class resourceClass, String path) { 126 | assertHeaderPresent(endedLRAId, path, LRA_HTTP_ENDED_CONTEXT_HEADER); 127 | 128 | switch (status) { 129 | case Closed : 130 | // FALLTHRU 131 | case Cancelled : 132 | // FALLTHRU 133 | case FailedToCancel : 134 | // FALLTHRU 135 | case FailedToClose : 136 | lraMetricService.incrementMetric( 137 | LRAMetricType.valueOf(status.name()), 138 | endedLRAId, 139 | resourceClass); 140 | return Response.ok().build(); 141 | default : 142 | return Response.status(Response.Status.BAD_REQUEST).build(); 143 | } 144 | 145 | } 146 | 147 | /** 148 | * Returns whether the passed LRA and resource are in finished state. 149 | * 150 | * @param lra 151 | * the LRA to test 152 | * @param resourceName 153 | * name of the resource that the metrics parameter applies to 154 | * @return whether or not an LRA has finished 155 | */ 156 | public boolean isLRAFinished(URI lra, String resourceName) { 157 | return lraMetricService.getMetric(LRAMetricType.Closed, lra, resourceName) > 0 || 158 | lraMetricService.getMetric(LRAMetricType.FailedToClose, lra, resourceName) > 0 || 159 | lraMetricService.getMetric(LRAMetricType.Cancelled, lra, resourceName) > 0 || 160 | lraMetricService.getMetric(LRAMetricType.FailedToCancel, lra, resourceName) > 0; 161 | } 162 | 163 | /** 164 | * Returns whether the passed LRA is in finished state. 165 | * 166 | * @param lra 167 | * the LRA to test 168 | * @return whether or not an LRA has finished 169 | */ 170 | public boolean isLRAFinished(URI lra) { 171 | return lraMetricService.getMetric(LRAMetricType.Closed, lra) > 0 || 172 | lraMetricService.getMetric(LRAMetricType.FailedToClose, lra) > 0 || 173 | lraMetricService.getMetric(LRAMetricType.Cancelled, lra) > 0 || 174 | lraMetricService.getMetric(LRAMetricType.FailedToCancel, lra) > 0; 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/service/spi/LRACallbackException.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.service.spi; 21 | 22 | /** 23 | * Generic exception for any failures that occures during the invocations of methods in {@link LRARecoveryService}. 24 | */ 25 | public class LRACallbackException extends Exception { 26 | 27 | public LRACallbackException() { 28 | super(); 29 | } 30 | 31 | public LRACallbackException(String message) { 32 | super(message); 33 | } 34 | 35 | public LRACallbackException(String message, Throwable cause) { 36 | super(message, cause); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tck/src/main/java/org/eclipse/microprofile/lra/tck/service/spi/LRARecoveryService.java: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************************************* 3 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * You may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | *******************************************************************************/ 20 | package org.eclipse.microprofile.lra.tck.service.spi; 21 | 22 | import java.net.URI; 23 | import java.util.logging.Logger; 24 | 25 | /** 26 | * The LRA model guarantees eventual consistency but does not say when participants will be brought into a consistent 27 | * state. When a request to close/cancel an LRA is received, the implementation is allowed to delay sending out the 28 | * complete/compensate callbacks (the specification only requires that an implementation must eventually send them). 29 | * 30 | * This SPI provides a mechanism for an implementation to indicate when it knows that callbacks have been sent and 31 | * responses received or when callbacks have been issued, all participants have reached an end state, and when all 32 | * listener notifications have been successfully delivered. 33 | * 34 | */ 35 | public interface LRARecoveryService { 36 | 37 | /** 38 | * Wait for the delivery of Complete and Compensate participant callbacks. When this method returns the caller can 39 | * be certain that the callbacks were sent and responses received (including error responses). 40 | * 41 | * @param lraId 42 | * the LRA context 43 | * @throws LRACallbackException 44 | * the implementation was unable to determine whether or not the callbacks were received by all 45 | * participants 46 | */ 47 | void waitForCallbacks(URI lraId) throws LRACallbackException; 48 | 49 | /** 50 | * Wait for all participants to reach an end state and for all 51 | * {@link org.eclipse.microprofile.lra.annotation.AfterLRA} notifications to be successfully delivered (AfterLRA 52 | * methods return HTTP 200). 53 | * 54 | * The default implementation iterates {@link LRARecoveryService#waitForEndPhaseReplay(URI)} until all participants 55 | * reach a final state and all AfterLRA listeners notifications are successfully delivered. 56 | * 57 | * @param lraId 58 | * the LRA context 59 | * @throws LRACallbackException 60 | * the implementation was unable to determine whether or not all participants have reached an end state 61 | * and whether or not all listeners have been successfully notified 62 | */ 63 | default void waitForRecovery(URI lraId) throws LRACallbackException { 64 | Logger log = Logger.getLogger(LRARecoveryService.class.getName()); 65 | int counter = 0; 66 | 67 | do { 68 | log.info("Recovery attempt #" + ++counter); 69 | } while (!waitForEndPhaseReplay(lraId)); 70 | log.info("LRA " + lraId + "has finished the recovery"); 71 | } 72 | 73 | /** 74 | * Wait for one replay of the end phase of the LRA (the callback calls to Status, Complete, Compensate, and Forget 75 | * methods of all Compensating/Completing participants. If the LRA is finished as a result of this call all 76 | * listeners must also be successfully notified before this method returns. The callback calls must be attempted but 77 | * do not have to be successful (e.g. implementation tries to call Compensate which returns connection refused is a 78 | * valid invocation of this method). 79 | * 80 | * @param lraId 81 | * the LRA context 82 | * @return true if the implementation successfully issued callback requests and received responses that indicate 83 | * that final state was achieved and all AfterLRA listeners were successfully notified (AfterLRA methods 84 | * returned HTTP 200), or false if the implementation successfully issued callback requests but it did not 85 | * receive all responses or the received responses indicate that the final state is not reached yet 86 | * @throws LRACallbackException 87 | * the implementation has no knowledge of this LRA or it was unable to retry the requests to all 88 | * participants so it does not make sense to trigger this method with the same argument again 89 | */ 90 | boolean waitForEndPhaseReplay(URI lraId) throws LRACallbackException; 91 | } 92 | -------------------------------------------------------------------------------- /tck/src/main/resources/META-INF/NOTICE: -------------------------------------------------------------------------------- 1 | ========================================================================= 2 | == NOTICE file corresponding to section 4(d) of the Apache License, == 3 | == Version 2.0, in this case for Microprofile LRA == 4 | ========================================================================= 5 | 6 | This product includes software developed at 7 | The Apache Software Foundation (http://www.apache.org/). 8 | 9 | SPDXVersion: SPDX-2.1 10 | PackageName: Eclipse Microprofile 11 | PackageHomePage: http://www.eclipse.org/microprofile 12 | PackageLicenseDeclared: Apache-2.0 13 | 14 | PackageCopyrightText: 15 | Michael Musgrove mmusgrov@redhat.com 16 | Nicola Ferraro ni.ferraro@gmail.com 17 | Ondra Chaloupka ochaloup@redhat.com 18 | Tom Jenkinson tom.jenkinson@redhat.com 19 | Martin Stefanko mstefank@redhat.com 20 | Rudy De Busscher rdebusscher@gmail.com 21 | 22 | -------------------------------------------------------------------------------- /tck/src/main/resources/META-INF/tck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microprofile/microprofile-lra/486dbe9207620177de791157cae8949d9e3e89f4/tck/src/main/resources/META-INF/tck --------------------------------------------------------------------------------