All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fi.evolver.basics.spring.messaging.MessageController Maven / Gradle / Ivy

package fi.evolver.basics.spring.messaging;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.zip.GZIPInputStream;

import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springdoc.api.annotations.ParameterObject;
import org.springdoc.core.converters.models.PageableAsQueryParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import fi.evolver.basics.spring.common.ConfigurationRepository;
import fi.evolver.basics.spring.http.MessageType;
import fi.evolver.basics.spring.http.exception.HttpBadRequestException;
import fi.evolver.basics.spring.http.exception.HttpInternalServerErrorException;
import fi.evolver.basics.spring.http.exception.HttpNotFoundException;
import fi.evolver.basics.spring.log.LogPolicy;
import fi.evolver.basics.spring.log.LogPolicy.Policy;
import fi.evolver.basics.spring.messaging.entity.Message;
import fi.evolver.basics.spring.messaging.entity.Message.MessageState;
import fi.evolver.basics.spring.messaging.entity.MessageLite;
import fi.evolver.basics.spring.messaging.model.MessageQuery;
import fi.evolver.utils.format.FormatUtils;
import fi.evolver.utils.format.PrettyPrintUtils;
import fi.evolver.utils.format.PrettyPrintUtils.Format;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.servlet.http.HttpServletResponse;


@RestController
@RequestMapping("/message")
public class MessageController {

	private final ConfigurationRepository configurationRepository;
	private final MessageLiteRepository messageLiteRepository;
	private final MessageRepository messageRepository;


	@Autowired
	public MessageController(MessageLiteRepository messageLiteRepository, MessageRepository messageRepository, ConfigurationRepository configurationRepository) {
		this.messageLiteRepository = messageLiteRepository;
		this.messageRepository = messageRepository;
		this.configurationRepository = configurationRepository;
	}


	@Operation(summary = "Fetch a page of messages")
	@ApiResponses(value = {
			@ApiResponse(responseCode = "200", description = "A page of messages"),
			@ApiResponse(responseCode = "400", description = "Invalid request parameters", content = @Content),
			@ApiResponse(responseCode = "500", description = "Internal server error", content = @Content)
	})
	@PageableAsQueryParam
	@GetMapping
	@LogPolicy(Policy.NONE)
	public Page list(
			@ParameterObject MessageQuery parameters,
			@ParameterObject @PageableDefault(size = 100, direction = Direction.DESC, sort = "creationTime") Pageable page) {

		return messageLiteRepository.search(parameters, page);
	}


	@Operation(summary = "Fetch a single entity by id")
	@ApiResponses(value = {
			@ApiResponse(responseCode = "200", description = "The requested message"),
			@ApiResponse(responseCode = "404", description = "The message was not found", content = @Content),
			@ApiResponse(responseCode = "500", description = "Internal server error", content = @Content)
	})
	@GetMapping("/{id}")
	@LogPolicy(Policy.NONE)
	public MessageLite show(@PathVariable long id) {
		return messageLiteRepository.findById(id).orElseThrow(HttpNotFoundException::new);
	}


	@Operation(summary = "Mark a message ready for sending")
	@ApiResponses(value = {
			@ApiResponse(responseCode = "200", description = "Message marked ready for sending"),
			@ApiResponse(responseCode = "404", description = "The message was not found", content = @Content),
			@ApiResponse(responseCode = "500", description = "Internal server error")
	})
	@PostMapping("/{id}/resend")
	@MessageType("Message/resend")
	@ResponseStatus(value = HttpStatus.NO_CONTENT)
	public void resendMessage(@PathVariable long id) {
		MessageLite message = messageLiteRepository.findById(id).orElseThrow(HttpNotFoundException::new);
		message.setState(MessageState.PENDING);
		messageLiteRepository.saveAndFlush(message);
	}


	@Operation(summary = "Mark messages ready for sending")
	@ApiResponses(value = {
			@ApiResponse(responseCode = "200", description = "Messages marked ready for sending", content = @Content),
			@ApiResponse(responseCode = "400", description = "Invalid request parameters", content = @Content),
			@ApiResponse(responseCode = "500", description = "Internal server error", content = @Content)
	})
	@PostMapping("/resend")
	@MessageType("Message/resend")
	@ResponseStatus(value = HttpStatus.NO_CONTENT)
	public int resendMessages(@ParameterObject MessageQuery parameters) {
		List messages = messageLiteRepository.search(parameters);

		if (!messages.isEmpty()) {
			Integer maxCount = configurationRepository.getInteger("MessageResendMaxCount").orElse(1000);
			if (messages.size() > maxCount)
				throw new HttpBadRequestException("Too many messages (%d) match given filter. Max amount of messages to resend is %d", messages.size(), maxCount);

			for (MessageLite message: messages)
				message.setState(MessageState.PENDING);

			messageLiteRepository.saveAll(messages);
			messageLiteRepository.flush();
		}

		return messages.size();
	}


	@Operation(summary = "Fetch message contents")
	@ApiResponses(value = {
			@ApiResponse(responseCode = "200", description = "Message data"),
			@ApiResponse(responseCode = "404", description = "Not found"),
			@ApiResponse(responseCode = "500", description = "Failed handling request", content = @Content)
	})
	@LogPolicy(Policy.NONE)
	@GetMapping(path = "/{id}/data")
	public void data(HttpServletResponse response, @PathVariable long id, @RequestParam(defaultValue = "false") boolean pretty) {
		Message message = messageRepository.findById(id).orElseThrow(HttpNotFoundException::new);

		try (Reader reader = new BufferedReader(new InputStreamReader(message.getDataStream(), StandardCharsets.UTF_8))) {
			Format format = PrettyPrintUtils.inferFormat(reader);
			response.addHeader("Content-disposition", FormatUtils.format("attachment; filename=message-%s%s.%s", id, pretty ? "-pretty" : "", format.name().toLowerCase()));

			if (pretty && format != Format.UNKNOWN)
				writePretty(response.getWriter(), message.getCompressedData(), format);
			else
				IOUtils.copy(message.getDataStream(), response.getOutputStream());
		}
		catch (IOException e) {
			throw new HttpInternalServerErrorException(e);
		}
	}


	private static void writePretty(Writer writer, byte[] data, Format format) throws IOException {
		Reader reader = new InputStreamReader(new GZIPInputStream(new ByteArrayInputStream(data)), StandardCharsets.UTF_8);
		PrettyPrintUtils.prettyPrint(reader, writer, format);
		writer.flush();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy