Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* JBoss, Home of Professional Open Source.
* Copyright 2017, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package io.narayana.lra.client.internal.proxy;
import io.narayana.lra.client.NarayanaLRAClient;
import io.narayana.lra.proxy.logging.LRAProxyLogger;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriBuilder;
import org.eclipse.microprofile.lra.annotation.ParticipantStatus;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.Future;
import static io.narayana.lra.client.internal.proxy.ParticipantProxyResource.LRA_PROXY_PATH;
import static jakarta.ws.rs.core.Response.Status.NOT_FOUND;
@ApplicationScoped
public class ProxyService {
private static List participants; // TODO figure out why ProxyService is constructed twice
@Inject
private NarayanaLRAClient narayanaLRAClient;
private UriBuilder uriBuilder;
@PostConstruct
void init() {
if (participants == null) { // TODO figure out why ProxyService is constructed twice
participants = new ArrayList<>();
}
int httpPort = Integer.getInteger("lra.http.port", 8081);
String httpHost = System.getProperty("lra.http.host", "localhost");
// TODO if the proxy is restarted on a different endpoint it should notify the recovery coordinator
uriBuilder = UriBuilder.fromPath(LRA_PROXY_PATH + "/{lra}/{pid}");
uriBuilder.scheme("http")
.host(httpHost)
.port(httpPort);
}
private ParticipantProxy getProxy(URI lraId, String participantId) {
int i = participants.indexOf(new ParticipantProxy(lraId, participantId));
return (i == -1 ? null : participants.get(i));
}
private ParticipantProxy recreateProxy(URI lraId, String participantId) {
return new ParticipantProxy(lraId, participantId);
}
Response notifyParticipant(URI lraId, String participantId, String participantData, boolean compensate) {
ParticipantProxy proxy = getProxy(lraId, participantId);
if (proxy == null) {
/*
* must be in a recovery scenario so recreate the proxy from the registered data
*/
proxy = recreateProxy(lraId, participantId);
}
LRAProxyParticipant participant = proxy.getParticipant();
if (participant == null && participantData != null && participantData.length() > 0) {
participant = deserializeParticipant(lraId, participantData).orElse(null);
}
if (participant != null) {
Future future = null;
try {
if (compensate) {
// let any NotFoundException propagate back to the coordinator
future = participant.compensateWork(lraId);
} else {
// let any NotFoundException propagate back to the coordinator
future = participant.completeWork(lraId);
}
} catch (Exception e) {
return Response.ok().entity(compensate ? ParticipantStatus.FailedToCompensate
: ParticipantStatus.FailedToComplete).build();
} finally {
if (future == null) {
participants.remove(proxy); // we definitively know the outcome
} else {
proxy.setFuture(future, compensate); // remember the future so that we can report its progress
}
}
if (future != null) {
return Response.accepted().build();
}
return Response.ok().build();
} else {
LRAProxyLogger.logger.errorf("TODO recovery: null participant for callback %s", lraId.toASCIIString());
}
return Response.status(NOT_FOUND).build();
}
void notifyForget(URI lraId, String participantId) {
ParticipantProxy proxy = getProxy(lraId, participantId);
if (proxy != null) {
participants.remove(proxy);
}
}
ParticipantStatus getStatus(URI lraId, String participantId) throws InvalidLRAStateException {
ParticipantProxy proxy = getProxy(lraId, participantId);
if (proxy == null) {
String errorMsg = String.format("Cannot find participant proxy for LRA id %s, participant id %%s",
lraId, participantId);
throw new NotFoundException(errorMsg,
Response.status(NOT_FOUND).entity(errorMsg).build());
}
Optional status = proxy.getStatus();
// null status implies that the participant is still active
return status.orElseThrow(InvalidLRAStateException::new);
}
public URI joinLRA(LRAProxyParticipant participant, URI lraId) {
return joinLRA(participant, lraId, 0L, ChronoUnit.SECONDS);
}
public URI joinLRA(LRAProxyParticipant participant, URI lraId, Long timeLimit, ChronoUnit unit) {
// TODO if lraId == null then register a join all new LRAs
ParticipantProxy proxy = new ParticipantProxy(lraId, UUID.randomUUID().toString(), participant);
try {
String pId = proxy.getParticipantId();
String lra = URLEncoder.encode(lraId.toASCIIString(), StandardCharsets.UTF_8.name());
participants.add(proxy);
Optional compensatorData = serializeParticipant(participant);
URI participantUri = uriBuilder.build(lra, pId);
long timeLimitInSeconds = Duration.of(timeLimit, unit).getSeconds();
StringBuilder sb = new StringBuilder(compensatorData.orElse(""));
URI participantRecoveryUrl = narayanaLRAClient.joinLRA(lraId, timeLimitInSeconds, participantUri, sb);
return participantRecoveryUrl;
} catch (Exception e) {
throw new WebApplicationException(e, Response.status(0)
.entity(lraId + ": Exception whilst joining with this LRA").build());
}
}
private static Optional serializeParticipant(final Serializable object) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(object);
return Optional.of(Base64.getEncoder().encodeToString(baos.toByteArray()));
} catch (final IOException e) {
LRAProxyLogger.i18NLogger.error_cannotSerializeParticipant(e.toString(), e);
return Optional.empty();
}
}
private static Optional deserializeParticipant(URI lraId, final String objectAsString) {
return Optional.empty(); // TODO
/* final byte[] data = Base64.getDecoder().decode(objectAsString);
try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data))) {
return Optional.of((LRAParticipant) ois.readObject());
} catch (final IOException | ClassNotFoundException e) {
for (LRAParticipantDeserializer ds : deserializers) {
LRAParticipant participant = ds.deserialize(lraId, data);
if (participant != null) {
return Optional.of(participant);
}
}
LRAProxyLogger.i18NLogger.warn_cannotDeserializeParticipant(lraId.toExternalForm(),
deserializers.size() == 0 ? "null" : deserializers.get(0).getClass().getCanonicalName(),
e.getMessage());
return Optional.empty();
}*/
}
}