Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 89 additions & 88 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,88 +1,89 @@
# ending with / = directory, starting with / = absolute (from .gitignore location)
# e.g. target/ is target directory ignored anywhere in the tree, /.idea/ is only in the root
# to override generic rule, use !, e.g. !/some/module/build/ would not be ignored

# Java/Maven build tool files
target/
build/
test-output/
dependency-reduced-pom.xml
apache-maven-3.9.9/
apache-maven-3.9.9-bin.zip
.claude

# Node modules
node_modules/

# IDEA files
/.idea/
/.run/
*.iml

# Eclipse files
.project
.classpath
.settings
.settings/

# Other IDE files
.c9/
*.launch
*.sublime-workspace

# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*

# JRebel files
rebel.xml

# jenv related
.java-version

# NetBeans files
/nb-configuration.xml
/nbactions.xml

# Backup, log and other files
*~
*.log
*.versionsBackup
.DS_Store
Thumbs.db
_mess
.checkstyle

# midPoint Studio temporary files
/scratches/

# Angular / Frontend
frontend/node_modules/
frontend/dist/
frontend/.angular/
frontend/package-lock.json
angular-frontend/node_modules/
angular-frontend/dist/
angular-frontend/tmp/
angular-frontend/out-tsc/
angular-frontend/bazel-out/
angular-frontend/.angular/
angular-frontend/.sass-cache/
angular-frontend/connect.lock
angular-frontend/coverage/
angular-frontend/libpeerconnection.log
angular-frontend/testem.log
angular-frontend/typings/
angular-frontend/__screenshots__/

# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Docker secrets
docker/secrets/
# ending with / = directory, starting with / = absolute (from .gitignore location)
# e.g. target/ is target directory ignored anywhere in the tree, /.idea/ is only in the root
# to override generic rule, use !, e.g. !/some/module/build/ would not be ignored

# Java/Maven build tool files
target/
build/
test-output/
dependency-reduced-pom.xml
apache-maven-3.9.9/
apache-maven-3.9.9-bin.zip
.claude

# Node modules
node_modules/

# IDEA files
/.idea/
/.run/
*.iml

# Eclipse files
.project
.classpath
.settings
.settings/

# Other IDE files
.c9/
*.launch
*.sublime-workspace

# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*

# JRebel files
rebel.xml

# jenv related
.java-version

# NetBeans files
/nb-configuration.xml
/nbactions.xml

# Backup, log and other files
*~
*.log
logs/
*.versionsBackup
.DS_Store
Thumbs.db
_mess
.checkstyle

# midPoint Studio temporary files
/scratches/

# Angular / Frontend
frontend/node_modules/
frontend/dist/
frontend/.angular/
frontend/package-lock.json
angular-frontend/node_modules/
angular-frontend/dist/
angular-frontend/tmp/
angular-frontend/out-tsc/
angular-frontend/bazel-out/
angular-frontend/.angular/
angular-frontend/.sass-cache/
angular-frontend/connect.lock
angular-frontend/coverage/
angular-frontend/libpeerconnection.log
angular-frontend/testem.log
angular-frontend/typings/
angular-frontend/__screenshots__/

# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Docker secrets
docker/secrets/
49 changes: 49 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
<tag/>
<url/>
</scm>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/Evolveum/integration-catalog/issues</url>
</issueManagement>
<properties>
<java.version>21</java.version>
</properties>
Expand Down Expand Up @@ -109,11 +113,56 @@
</dependencies>

<build>
<!--
Filter only banner.txt so Maven substitutes @project.version@,
@project.issueManagement.url@ and the git.* properties (provided by the
git-commit-id plugin below). Everything else is copied verbatim, so
application.properties' own ${...} placeholders are left untouched.
-->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>banner.txt</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<excludes>
<exclude>banner.txt</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--
Exposes git.branch and git.commit.id.describe as build properties (and a
git.properties file) so the banner can show the real branch and build.
Requires a Maven build to run; see note below about IntelliJ.
-->
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
<version>9.0.1</version>
<executions>
<execution>
<id>get-git-info</id>
<phase>initialize</phase>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
</configuration>
</plugin>
</plugins>
</build>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public class IntegrationCatalogApplication {
= (Logger) LoggerFactory.getLogger(IntegrationCatalogApplication.class);

public static void main(String[] args) {
// Guarantee the banner is the first thing logged. Spring Boot's background
// pre-initializer warms up classes (e.g. Hibernate Validator) on a separate
// thread and can log before the banner is printed; disabling it keeps the
// banner on top. Must be set before SpringApplication.run(...).
System.setProperty("spring.backgroundpreinitializer.ignore", "true");
SpringApplication.run(IntegrationCatalogApplication.class, args);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2010-2025 Evolveum and contributors
*
* Licensed under the EUPL-1.2 or later.
*/

package com.evolveum.midpoint.integration.catalog.configuration;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.filter.ThresholdFilter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

/**
* Keeps the terminal quiet once the application is running, without losing warnings/errors.
* <p>
* During startup the console ("stdout") appender has no level filter, so all initialization
* logs are visible in the terminal (and saved to file). Once the application is fully
* initialized ({@link ApplicationReadyEvent}), a {@link ThresholdFilter} set to {@code WARN}
* is added to the console appender, so from then on only {@code WARN}/{@code ERROR} flash in
* the terminal while {@code INFO}/{@code DEBUG} keep going to the file only. The file appender
* is never touched, so the log file continues to capture everything.
*/
@Component
public class ConsoleLoggingToggle {

private static final Logger LOG = (Logger) LoggerFactory.getLogger(ConsoleLoggingToggle.class);

/** Must match the appender name in log4j.xml. */
private static final String CONSOLE_APPENDER_NAME = "stdout";

/** Minimum level allowed to reach the terminal after startup. */
private static final String RUNTIME_CONSOLE_THRESHOLD = "WARN";

@EventListener(ApplicationReadyEvent.class)
public void raiseConsoleThresholdAfterStartup() {
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger rootLogger = context.getLogger(Logger.ROOT_LOGGER_NAME);
Appender<ILoggingEvent> consoleAppender = rootLogger.getAppender(CONSOLE_APPENDER_NAME);

if (consoleAppender == null) {
LOG.warn("Console appender '{}' was not found on the root logger; terminal output was not changed.",
CONSOLE_APPENDER_NAME);
return;
}

// Log the hand-off while the console still shows INFO, so this is the last
// informational line the user sees in the terminal.
LOG.info("Application fully initialized. Terminal now shows {}+ only; all logs continue to the file.",
RUNTIME_CONSOLE_THRESHOLD);

ThresholdFilter filter = new ThresholdFilter();
filter.setLevel(RUNTIME_CONSOLE_THRESHOLD);
filter.setContext(context);
filter.start();
consoleAppender.addFilter(filter);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2010-2025 Evolveum and contributors
*
* Licensed under the EUPL-1.2 or later.
*/

package com.evolveum.midpoint.integration.catalog.configuration;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
* Logs one line per REST request: HTTP method, URI, resulting status and duration.
* Covers every {@code /api/**} endpoint uniformly, so individual controller methods
* don't have to repeat request/response boilerplate logging.
*/
@Slf4j
@Component
public class RequestLoggingFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
long start = System.currentTimeMillis();
String method = request.getMethod();
String uri = request.getRequestURI();
String query = request.getQueryString();
String fullUri = query == null ? uri : uri + "?" + query;

log.debug("--> {} {}", method, fullUri);
try {
filterChain.doFilter(request, response);
} finally {
long duration = System.currentTimeMillis() - start;
int status = response.getStatus();
if (status >= 500) {
log.error("<-- {} {} {} ({} ms)", method, fullUri, status, duration);
} else if (status >= 400) {
log.warn("<-- {} {} {} ({} ms)", method, fullUri, status, duration);
} else {
log.info("<-- {} {} {} ({} ms)", method, fullUri, status, duration);
}
}
}

@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
// Only log REST API traffic, not SPA static-resource forwarding.
return !request.getRequestURI().startsWith("/api/");
}
}
Loading