├── .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 | * JAX-RS Response Codes For Forget Methods
85 | *
86 | * Code |
87 | * Response Body |
88 | * Meaning |
89 | *
90 | *
91 | * 200 |
92 | * Empty |
93 | * The participant may have removed all knowledge of the LRA |
94 | *
95 | *
96 | * 410 |
97 | * Empty |
98 | * The method does not know about the LRA |
99 | *
100 | *
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 | * JAX-RS Response Codes For Status Methods
86 | *
87 | * Code |
88 | * Response Body |
89 | * Meaning |
90 | *
91 | *
92 | * 200 |
93 | * {@link ParticipantStatus} enum value |
94 | * The current status of the participant |
95 | *
96 | *
97 | * 202 |
98 | * Empty |
99 | * The resource is attempting to determine the status and the caller should retry later |
100 | *
101 | *
102 | * 410 |
103 | * Empty |
104 | * The method does not know about the LRA |
105 | *
106 | *
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
--------------------------------------------------------------------------------