001// Generated by delombok at Mon Oct 12 22:59:35 BST 2020
002/*
003 *  Licensed to the Apache Software Foundation (ASF) under one
004 *  or more contributor license agreements.  See the NOTICE file
005 *  distributed with this work for additional information
006 *  regarding copyright ownership.  The ASF licenses this file
007 *  to you under the Apache License, Version 2.0 (the
008 *  "License"); you may not use this file except in compliance
009 *  with the License.  You may obtain a copy of the License at
010 *
011 *        http://www.apache.org/licenses/LICENSE-2.0
012 *
013 *  Unless required by applicable law or agreed to in writing,
014 *  software distributed under the License is distributed on an
015 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 *  KIND, either express or implied.  See the License for the
017 *  specific language governing permissions and limitations
018 *  under the License.
019 */
020package org.apache.isis.extensions.commandreplay.secondary.fetch;
021
022import java.net.URI;
023import java.util.Collections;
024import java.util.List;
025import java.util.Optional;
026import java.util.UUID;
027import javax.annotation.Nullable;
028import javax.inject.Inject;
029import javax.inject.Named;
030import javax.ws.rs.core.Response;
031import javax.ws.rs.core.UriBuilder;
032import org.springframework.core.annotation.Order;
033import org.springframework.stereotype.Service;
034import org.apache.isis.applib.annotation.OrderPrecedence;
035import org.apache.isis.applib.services.jaxb.JaxbService;
036import org.apache.isis.extensions.commandlog.impl.jdo.CommandJdo;
037import org.apache.isis.extensions.commandreplay.secondary.SecondaryStatus;
038import org.apache.isis.extensions.commandreplay.secondary.StatusException;
039import org.apache.isis.extensions.commandreplay.secondary.config.SecondaryConfig;
040import org.apache.isis.extensions.jaxrsclient.applib.client.JaxRsClient;
041import org.apache.isis.extensions.jaxrsclient.applib.client.JaxRsResponse;
042import org.apache.isis.extensions.jaxrsclient.impl.client.JaxRsClientDefault;
043import org.apache.isis.schema.cmd.v2.CommandDto;
044import org.apache.isis.schema.cmd.v2.CommandsDto;
045
046@Service
047@Named("isisExtensionsCommandReplaySecondary.CommandFetcher")
048@Order(OrderPrecedence.MIDPOINT)
049public class CommandFetcher {
050    @java.lang.SuppressWarnings("all")
051    private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(CommandFetcher.class);
052    static final String URL_SUFFIX = "services/isisExtensionsCommandReplayPrimary.CommandRetrievalService/actions/findCommandsOnPrimaryFrom/invoke";
053
054    /**
055     * Replicates a single command.
056
057     *
058
059     * @param previousHwmIfAny
060
061     * @return
062
063     * @throws StatusException
064     */
065    public List<CommandDto> fetchCommand(@Nullable final CommandJdo previousHwmIfAny) throws StatusException {
066        log.debug("finding command on primary ...");
067        final CommandsDto commandsDto = fetchCommands(previousHwmIfAny);
068        return commandsDto != null ? commandsDto.getCommandDto() : Collections.emptyList();
069    }
070
071    /**
072     * @return - the commands, or <tt>null</tt> if none were found
073
074     * @throws StatusException
075
076     * @param previousHwmIfAny
077     */
078    private CommandsDto fetchCommands(final CommandJdo previousHwmIfAny) throws StatusException {
079        final UUID transactionId = previousHwmIfAny != null ? previousHwmIfAny.getUniqueId() : null;
080        log.debug("finding commands on primary ...");
081        final URI uri = buildUri(transactionId);
082        final JaxRsResponse response = callPrimary(uri);
083        final CommandsDto commandsDto = unmarshal(response, uri);
084        final int size = commandsDto.getCommandDto().size();
085        if (size == 0) {
086            return null;
087        }
088        return commandsDto;
089    }
090
091    private URI buildUri(final UUID uniqueId) {
092        final UriBuilder uriBuilder = UriBuilder.fromUri(uniqueId != null ? String.format("%s%s?uniqueId=%s&batchSize=%d", secondaryConfig.getPrimaryBaseUrlRestful(), URL_SUFFIX, uniqueId, secondaryConfig.getBatchSize()) : String.format("%s%s?batchSize=%d", secondaryConfig.getPrimaryBaseUrlRestful(), URL_SUFFIX, secondaryConfig.getBatchSize()));
093        final URI uri = uriBuilder.build();
094        log.info("uri = {}", uri);
095        return uri;
096    }
097
098    private JaxRsResponse callPrimary(final URI uri) throws StatusException {
099        final JaxRsResponse response;
100        final JaxRsClient jaxRsClient = new JaxRsClientDefault();
101        try {
102            final String user = secondaryConfig.getPrimaryUser();
103            final String password = secondaryConfig.getPrimaryPassword();
104            response = jaxRsClient.get(uri, CommandsDto.class, JaxRsClient.ReprType.ACTION_RESULT, user, password);
105            int status = response.getStatus();
106            if (status != Response.Status.OK.getStatusCode()) {
107                final String entity = readEntityFrom(response);
108                if (entity != null) {
109                    log.warn("status: {}, entity: \n{}", status, entity);
110                } else {
111                    log.warn("status: {}, unable to read entity from response", status);
112                }
113                throw new StatusException(SecondaryStatus.REST_CALL_FAILING);
114            }
115        } catch (Exception ex) {
116            log.warn("rest call failed", ex);
117            throw new StatusException(SecondaryStatus.REST_CALL_FAILING, ex);
118        }
119        return response;
120    }
121
122    private CommandsDto unmarshal(final JaxRsResponse response, final URI uri) throws StatusException {
123        CommandsDto commandsDto;
124        String entity = "<unable to read from response entity>";
125        try {
126            entity = readEntityFrom(response);
127            final JaxbService jaxbService = new JaxbService.Simple();
128            commandsDto = jaxbService.fromXml(CommandsDto.class, entity);
129            log.debug("commands:\n{}", entity);
130        } catch (Exception ex) {
131            log.warn("unable to unmarshal entity from {} to CommandsDto.class; was:\n{}", uri, entity);
132            throw new StatusException(SecondaryStatus.FAILED_TO_UNMARSHALL_RESPONSE, ex);
133        }
134        return commandsDto;
135    }
136
137    private static String readEntityFrom(final JaxRsResponse response) {
138        try {
139            return response.readEntity(String.class);
140        } catch (Exception e) {
141            return null;
142        }
143    }
144
145    @Inject
146    SecondaryConfig secondaryConfig;
147}