You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dp...@apache.org on 2026/05/08 21:20:40 UTC

(ignite-teamcity-bot) branch master updated: IGNITE-28658 [TCBot] Code cleanup, part 0 (#213)

This is an automated email from the ASF dual-hosted git repository.

dspavlov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git


The following commit(s) were added to refs/heads/master by this push:
     new bd69c92e IGNITE-28658 [TCBot] Code cleanup, part 0 (#213)
bd69c92e is described below

commit bd69c92e86d0c30966f87db7465c3dd73da71192
Author: ignitetcbot <43...@users.noreply.github.com>
AuthorDate: Sat May 9 00:20:35 2026 +0300

    IGNITE-28658 [TCBot] Code cleanup, part 0 (#213)
    
    Prepare TCBot DI lifecycle
    
    Introduce a neutral application context abstraction and move Guice wiring into
    a dedicated tcbot-app-guice module. This keeps the web layer independent from
    Guice and allows another runtime implementation, such as Spring Boot, to be
    added later.
    
    Also clean up common dependencies, move Guice/AOP interceptors out of common,
    make application startup/shutdown explicit, and avoid provisioning services
    before Ignite is ready.
    
    Codex co-authored-by: Dmitriy Pavlov <dp...@apache.org>
---
 build.gradle                                       |   4 +
 docs/install.md                                    |   2 -
 ignite-tc-helper-web/build.gradle                  |  41 +-
 .../java/org/apache/ignite/ci/db/Ignite1Init.java  |   3 +-
 .../org/apache/ignite/ci/db/Ignite2Configurer.java |   8 +-
 .../java/org/apache/ignite/ci/db/TcHelperDb.java   |   3 +-
 .../apache/ignite/ci/runners/ClientTmpHelper.java  | 111 -----
 .../runners/IgniteTeamcityHelperRunnerExample.java | 132 ------
 .../ignite/ci/runners/RemoteClientTmpHelper.java   | 464 ---------------------
 .../apache/ignite/ci/tcbot/TcBotBgAuthImpl.java    |   2 +-
 .../ignite/ci/tcbot/issue/IssueDetector.java       |   2 +-
 .../apache/ignite/ci/tcbot/issue/Notification.java |  16 +-
 .../tcbot/visa/TcBotTriggerAndSignOffService.java  |   7 +-
 .../java/org/apache/ignite/ci/web/CtxListener.java | 104 +----
 .../java/org/apache/ignite/ci/web/Launcher.java    |   1 +
 .../ignite/ci/web/auth/AuthenticationFilter.java   |  52 +--
 .../ignite/ci/web/model/trends/BuildsHistory.java  |   1 -
 .../org/apache/ignite/ci/web/rest/GetBuildLog.java |   6 +-
 .../ignite/ci/web/rest/GetTrackedBranches.java     |  31 +-
 .../ignite/ci/web/rest/ServerIntegrationLinks.java |  43 --
 .../apache/ignite/ci/web/rest/TriggerBuilds.java   |  47 +--
 .../ignite/ci/web/rest/board/BoardRestService.java |  10 +-
 .../ci/web/rest/board/DefectRestService.java       |   2 +-
 .../ignite/ci/web/rest/build/CompareBuilds.java    |   8 +-
 .../rest/build/GetSingleBuildTestFailuresRest.java |  28 +-
 .../web/rest/buildtime/BuildTimeRestService.java   |   2 +-
 .../apache/ignite/ci/web/rest/issues/TcIssues.java |  17 +-
 .../org/apache/ignite/ci/web/rest/login/Login.java |  20 +-
 .../ignite/ci/web/rest/login/UserService.java      |  45 +-
 .../long_running/BuildsLongRunningTestsReport.java |   2 +-
 .../ci/web/rest/monitoring/MonitoringService.java  |  34 +-
 .../ignite/ci/web/rest/pr/GetPrTestFailures.java   |  54 +--
 .../rest/tracked/GetTrackedBranchTestResults.java  |  90 +---
 .../ignite/ci/web/rest/visa/TcBotVisaService.java  |  24 +-
 ignite-tc-helper-web/src/main/webapp/all.html      | 186 ---------
 ignite-tc-helper-web/src/main/webapp/build.html    |   2 -
 ignite-tc-helper-web/src/main/webapp/chart.html    |   5 -
 .../src/main/webapp/comparison.html                |   5 -
 ignite-tc-helper-web/src/main/webapp/current.html  |   3 -
 .../src/main/webapp/img/browser.png                | Bin 518 -> 0 bytes
 ignite-tc-helper-web/src/main/webapp/index0.html   |   8 +-
 .../src/main/webapp/js/testfails-2.3.js            |   5 -
 ignite-tc-helper-web/src/main/webapp/prs.html      |  12 +-
 .../src/main/webapp/restpretty.html                |  72 ----
 ignite-tc-helper-web/src/main/webapp/services.html |   5 -
 .../src/main/webapp/statistics.html                |   5 -
 .../org/apache/ignite/ci/di/DiContextTest.java     |   3 +-
 .../ci/tcbot/chain/BuildChainProcessorTest.java    |   4 +-
 .../ci/tcbot/chain/MockBasedTcBotModule.java       |   6 +-
 .../ci/tcbot/chain/PrChainsProcessorTest.java      |   2 -
 .../ignite/ci/tcbot/issue/IssueDetectorTest.java   |   6 -
 .../tcbot/engine/board/BoardServiceTest.java       |   4 +-
 .../tcbot/engine/board/TeamcityIgnitedModule.java  |  44 +-
 .../ignite/tcbot/engine/cleaner/CleanerTest.java   |   4 +-
 .../engine/cleaner/TeamcityIgnitedModule.java      |  44 +-
 .../IgnitedTcInMemoryIntegrationTest.java          |  10 +-
 jetty-launcher/build.gradle                        |  14 +-
 migrator/build.gradle                              |   4 +-
 settings.gradle                                    |   2 +-
 {tcbot-engine => tcbot-app-guice}/build.gradle     |  23 +-
 .../ignite/githubignited/GitHubIgnitedModule.java  |   4 +-
 .../githubservice/GitHubIntegrationModule.java     |  18 +-
 .../ignite/jiraignited/JiraIgnitedModule.java      |   6 +-
 .../ignite/jiraservice/JiraIntegrationModule.java  |   4 +-
 .../app/guice/GuiceTcBotApplicationContext.java    | 240 +++++++++++
 .../guice/GuiceTcBotApplicationContextFactory.java |  14 +-
 .../ignite/tcbot/app/guice}/TcBotWebAppModule.java |  49 ++-
 .../ignite/tcbot/common/TcBotCommonModule.java     |   0
 .../interceptor/AutoProfilingInterceptor.java      |   5 +-
 .../AutoProfilingInterceptorModule.java            |   2 +
 .../common/interceptor/GuavaCachedInterceptor.java |  70 ++--
 .../common/interceptor/GuavaCachedModule.java      |   0
 .../interceptor/MonitoredTaskInterceptor.java      |  35 +-
 .../MonitoredTaskInterceptorModule.java            |   2 +
 .../ignite/tcbot/engine/TcBotEngineModule.java     |  20 +-
 .../tcbot/notify/TcBotNotificationsModule.java     |   6 +-
 .../tcbot/persistence/TcBotPersistenceModule.java  |  15 +-
 .../persistence/scheduler/SchedulerModule.java     |   4 +-
 .../ignite/tcignited/TeamcityIgnitedModule.java    |  40 +-
 .../buildlog/BuildLogProcessorModule.java          |   4 +-
 .../ignite/tcservice/TcRealConnectionModule.java   |   6 +-
 ...mmon.application.TcBotApplicationContextFactory |   1 +
 tcbot-common/build.gradle                          |  23 +-
 .../application/TcBotApplicationContext.java       |  12 +-
 .../TcBotApplicationContextFactory.java            |   8 +-
 .../application/TcBotApplicationContexts.java      |  20 +-
 .../tcbot/common/monitoring/MonitoredTasks.java    |  34 +-
 .../tcbot/common/monitoring/ProfilingMonitor.java  |  24 +-
 .../apache/ignite/tcbot/common/util/CryptUtil.java |   8 +-
 .../apache/ignite/tcbot/common/util/HttpUtil.java  |  90 ++--
 .../ignite/tcbot/common/util/ObjectInterner.java   |  10 +-
 tcbot-engine/build.gradle                          |   7 +-
 .../ignite/tcbot/engine/board/BoardService.java    |   8 -
 .../ignite/tcbot/engine/chain/MultBuildRunCtx.java |  31 +-
 .../ignite/tcbot/engine/pr/PrChainsProcessor.java  |   2 -
 .../tcbot/engine/ui/BoardDefectSummaryUi.java      |  43 +-
 .../apache/ignite/tcbot/engine/ui/DsChainUi.java   |   2 +-
 .../apache/ignite/tcbot/engine/ui/DsSuiteUi.java   | 128 +++---
 .../ignite/tcbot/engine/ui/DsTestFailureUi.java    |   3 +-
 tcbot-github-ignited/build.gradle                  |   2 +
 .../githubignited/GitHubConnIgnitedImpl.java       |   5 -
 .../githubignited/GitHubIgnitedProvImpl.java       |   5 +-
 .../ignite/githubignited/IGitHubConnIgnited.java   |   8 -
 tcbot-github/build.gradle                          |   8 +-
 .../githubservice/GitHubCachingProvider.java       |  14 +-
 .../ignite/githubservice/GitHubConnectionImpl.java |  40 +-
 .../ignite/githubservice/IGitHubConnection.java    |   9 -
 tcbot-jira-ignited/build.gradle                    |   2 +
 .../ignite/jiraignited/JiraIgnitedProvider.java    |   7 +-
 tcbot-jira/build.gradle                            |   9 +-
 .../jiraservice/JiraIntegrationProvider.java       |   7 +-
 .../ignite/jiraservice/adapters/TypeFactory.java   |  15 +-
 .../apache/ignite/jiraservice/package-info.java    |   3 +-
 tcbot-notify/build.gradle                          |   4 +-
 tcbot-persistence/build.gradle                     |   5 +-
 .../tcbot/persistence/IgniteStringCompactor.java   |  10 +-
 tcbot-server-node/README.md                        |   4 -
 tcbot-server-node/build.gradle                     |  66 ---
 .../ignite/ci/TcBotIgniteServerLauncher.java       |  70 ----
 tcbot-teamcity-ignited/build.gradle                |   8 +-
 .../ignite/tcignited/TcIgnitedCachingProvider.java |   4 +-
 .../ignite/tcignited/TeamcityIgnitedImpl.java      |   2 +-
 .../tcignited/build/ProactiveFatBuildSync.java     |   3 -
 .../tcignited/buildlog/BuildLogProcessor.java      |   4 +-
 .../ignite/tcignited/buildlog/LogMsgToWarn.java    |  11 +-
 .../ignite/tcignited/buildref/BuildRefDao.java     |  11 +-
 .../ignite/tcignited/history/AbstractRunHist.java  |   2 -
 .../ignite/tcignited/history/HistoryCollector.java |   5 +-
 .../history/SuiteInvocationHistoryDao.java         |   1 +
 tcbot-teamcity/build.gradle                        |   9 +-
 .../tcservice/http/FileRecordingInputStream.java   |   6 +-
 .../ignite/tcservice/http/TeamcityRecorder.java    |   4 +-
 .../tcservice/util/TcConnectionStaticLinker.java   |   2 +-
 .../org/apache/ignite/tcservice/util/XmlUtil.java  |   3 +-
 134 files changed, 996 insertions(+), 2264 deletions(-)

diff --git a/build.gradle b/build.gradle
index fc0ee17f..3bec9bdf 100644
--- a/build.gradle
+++ b/build.gradle
@@ -108,6 +108,10 @@ allprojects {
     tasks.withType(JavaExec).configureEach {
         jvmArgs igniteJava17JvmArgs
     }
+
+    tasks.withType(JavaCompile).configureEach {
+        options.compilerArgs += ['-Xlint:deprecation', '-Xlint:unchecked']
+    }
 }
 
 /*
diff --git a/docs/install.md b/docs/install.md
index 690a2f3a..55571128 100644
--- a/docs/install.md
+++ b/docs/install.md
@@ -5,7 +5,6 @@ Use Java 17. Build everything through the Gradle wrapper:
 ```
 ./gradlew clean build --no-daemon
 ./gradlew :jetty-launcher:clean :jetty-launcher:distZip --no-daemon
-./gradlew :tcbot-server-node:clean :tcbot-server-node:distZip --no-daemon
 ```
 
 On Windows use the same commands with `gradlew.bat`:
@@ -13,7 +12,6 @@ On Windows use the same commands with `gradlew.bat`:
 ```
 gradlew.bat clean build --no-daemon
 gradlew.bat :jetty-launcher:clean :jetty-launcher:distZip --no-daemon
-gradlew.bat :tcbot-server-node:clean :tcbot-server-node:distZip --no-daemon
 ```
 
 The web distribution is `jetty-launcher/build/distributions/jetty-launcher.zip`. It contains `bin`, `lib`, and
diff --git a/ignite-tc-helper-web/build.gradle b/ignite-tc-helper-web/build.gradle
index 5a0fd934..224e28db 100644
--- a/ignite-tc-helper-web/build.gradle
+++ b/ignite-tc-helper-web/build.gradle
@@ -22,32 +22,39 @@ apply plugin: 'war'
 dependencies {
     implementation project(":tcbot-engine")
     implementation project(':migrator')
+    runtimeOnly project(":tcbot-app-guice")
 
-    implementation group: 'org.apache.ignite', name: 'ignite-core', version: ignVer
-    implementation group: 'org.apache.ignite', name: 'ignite-slf4j', version: ignVer
-    implementation group: 'org.apache.ignite', name: 'ignite-direct-io', version: ignVer
+    implementation "org.apache.ignite:ignite-core:$ignVer"
+    implementation "org.apache.ignite:ignite-slf4j:$ignVer"
+    implementation "org.apache.ignite:ignite-direct-io:$ignVer"
 
-    implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVer
-    implementation group: 'org.slf4j', name: 'jul-to-slf4j', version: slf4jVer
+    implementation 'javax.inject:javax.inject:1'
 
-    implementation group: 'ch.qos.logback', name: 'logback-core', version: logbackVer
-    implementation group: 'ch.qos.logback', name: 'logback-classic', version: logbackVer
+    implementation "com.google.code.gson:gson:$gsonVer"
 
-    implementation group: 'org.eclipse.jetty', name: 'jetty-util', version: jettyVer
-    implementation group: 'org.eclipse.jetty', name: 'jetty-server', version: jettyVer
-    implementation group: 'org.eclipse.jetty.ee8', name: 'jetty-ee8-webapp', version: jettyVer
+    implementation "org.slf4j:slf4j-api:$slf4jVer"
+    implementation "org.slf4j:jul-to-slf4j:$slf4jVer"
 
-    implementation group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet-core', version: jerseyVer
+    implementation "ch.qos.logback:logback-core:$logbackVer"
+    implementation "ch.qos.logback:logback-classic:$logbackVer"
 
-    implementation group: 'org.glassfish.jersey.core', name: 'jersey-client', version: jerseyVer
+    implementation "org.eclipse.jetty:jetty-util:$jettyVer"
+    implementation "org.eclipse.jetty:jetty-server:$jettyVer"
+    implementation "org.eclipse.jetty.ee8:jetty-ee8-webapp:$jettyVer"
+
+    implementation "org.glassfish.jersey.containers:jersey-container-servlet-core:$jerseyVer"
+
+    implementation "org.glassfish.jersey.core:jersey-client:$jerseyVer"
     //
-    implementation group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version:  jerseyVer
+    implementation "org.glassfish.jersey.inject:jersey-hk2:$jerseyVer"
 
-    implementation group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: jerseyVer
-    implementation group: 'org.glassfish.jersey.media', name: 'jersey-media-multipart', version: jerseyVer
+    implementation "org.glassfish.jersey.media:jersey-media-json-jackson:$jerseyVer"
+    implementation "org.glassfish.jersey.media:jersey-media-multipart:$jerseyVer"
 
-    testImplementation group: 'junit', name: 'junit', version: junitVer
-    testImplementation group: 'org.mockito', name: 'mockito-core', version: mockitoVer
+    testImplementation "junit:junit:$junitVer"
+    testImplementation "org.mockito:mockito-core:$mockitoVer"
+    testImplementation project(":tcbot-app-guice")
+    testImplementation "com.google.inject:guice:$guiceVer"
 }
 
 processResources {
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite1Init.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite1Init.java
index 47e31857..46919270 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite1Init.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite1Init.java
@@ -31,6 +31,7 @@ import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
 import org.apache.ignite.tcbot.common.interceptor.MonitoredTask;
 import org.apache.ignite.ci.web.model.Version;
 import org.apache.ignite.cluster.BaselineNode;
+import org.apache.ignite.cluster.ClusterState;
 import org.apache.ignite.configuration.DataRegionConfiguration;
 import org.apache.ignite.configuration.DataStorageConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
@@ -94,7 +95,7 @@ public class Ignite1Init {
     protected String activate() {
         System.out.println("Activating Ignite Server Node, " + Version.VERSION);
 
-        ignite.cluster().active(true);
+        ignite.cluster().state(ClusterState.ACTIVE);
 
         System.out.println("Activate Completed");
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite2Configurer.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite2Configurer.java
index abe609be..0610750b 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite2Configurer.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/Ignite2Configurer.java
@@ -20,6 +20,7 @@ import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
+import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.rolling.RollingFileAppender;
 import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
 import java.io.File;
@@ -43,7 +44,7 @@ public class Ignite2Configurer {
         logEncoder.setPattern("%-12date{YYYY-MM-dd HH:mm:ss.SSS} %-5level [%t] - %msg%n");
         logEncoder.start();
 
-        RollingFileAppender rollingFa = new RollingFileAppender();
+        RollingFileAppender<ILoggingEvent> rollingFa = new RollingFileAppender<>();
         rollingFa.setContext(logCtx);
         rollingFa.setName("logFile");
         rollingFa.setEncoder(logEncoder);
@@ -52,7 +53,7 @@ public class Ignite2Configurer {
         final File logs = new File(workDir, subdir);
         TcBotWorkDir.ensureDirExist(logs);
 
-        TimeBasedRollingPolicy logFilePolicy = new TimeBasedRollingPolicy();
+        TimeBasedRollingPolicy<ILoggingEvent> logFilePolicy = new TimeBasedRollingPolicy<>();
         logFilePolicy.setContext(logCtx);
         logFilePolicy.setParent(rollingFa);
         logFilePolicy.setFileNamePattern(new File(logs, "logfile-%d{yyyy-MM-dd_HH}.log").getAbsolutePath());
@@ -123,7 +124,8 @@ public class Ignite2Configurer {
         return regConf;
     }
 
-     public static DataStorageConfiguration getDataStorageConfiguration(DataRegionConfiguration regConf) {
+    @SuppressWarnings("deprecation")
+    public static DataStorageConfiguration getDataStorageConfiguration(DataRegionConfiguration regConf) {
         return new DataStorageConfiguration()
             // .setWalCompactionEnabled(true)
             .setWalMode(WALMode.LOG_ONLY)
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/TcHelperDb.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/TcHelperDb.java
index 6850194b..8533a6f8 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/TcHelperDb.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/TcHelperDb.java
@@ -25,6 +25,7 @@ import org.apache.ignite.Ignition;
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
 import org.apache.ignite.ci.web.model.Version;
+import org.apache.ignite.cluster.ClusterState;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.logger.slf4j.Slf4jLogger;
@@ -73,7 +74,7 @@ public class TcHelperDb {
         cfg.setClientMode(true);
 
         final Ignite ignite = Ignition.start(cfg);
-        ignite.cluster().active(true);
+        ignite.cluster().state(ClusterState.ACTIVE);
         return ignite;
     }
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/ClientTmpHelper.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/ClientTmpHelper.java
deleted file mode 100644
index cf3cbd79..00000000
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/ClientTmpHelper.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.ci.runners;
-
-import org.apache.ignite.Ignite;
-import org.apache.ignite.IgniteCache;
-import org.apache.ignite.ci.db.TcHelperDb;
-import org.apache.ignite.ci.user.TcHelperUser;
-import org.apache.ignite.githubignited.IGitHubConnIgnited;
-import org.apache.ignite.ci.issue.Issue;
-import org.apache.ignite.tcbot.engine.issue.IssuesStorage;
-import org.apache.ignite.jiraignited.JiraTicketDao;
-import org.apache.ignite.tcbot.engine.user.UserAndSessionsStorage;
-
-/**
- * Utility class for local connection to TC helper DB (server) and any manipulations with data needed.
- */
-public class ClientTmpHelper {
-    public static void main(String[] args) {
-        //select some main option here.
-        //mainDropIssHist(args);
-
-        mainSetUserAsAdmin(args);
-    }
-
-    /**
-     * @param args Args.
-     */
-    public static void mainSetUserAsAdmin(String[] args) {
-        try (Ignite ignite = TcHelperDb.startClient()) {
-            IgniteCache<String, TcHelperUser> users = ignite.cache(UserAndSessionsStorage.USERS);
-            TcHelperUser user = users.get("dpavlov");
-            user.setAdmin(true);
-            users.put(user.username, user);
-        }
-    }
-
-
-    /**
-     * @param args Args.
-     */
-    public static void mainConsistCheck(String[] args) {
-        int inconsistent;
-        try (Ignite ignite = TcHelperDb.startClient()) {
-            RemoteClientTmpHelper.DUMPS = "dumpsLocal";
-
-            inconsistent = RemoteClientTmpHelper.validateBuildIdConsistency(ignite);
-        }
-
-        System.err.println("Inconsistent builds in queue found [" +
-            +inconsistent + "]");
-    }
-
-    /**
-     * @param args Args.
-     */
-    public static void mainDropIssHist(String[] args) {
-        Ignite ignite = TcHelperDb.startClient();
-
-        IgniteCache<Object, Object> cache = ignite.cache(IssuesStorage.BOT_DETECTED_ISSUES);
-
-        cache.forEach(
-            issue -> {
-                Object key = issue.getKey();
-                Issue val = (Issue)issue.getValue();
-
-                if(val.issueKey.testOrBuildName.contains(
-                    "GridCachePartitionEvictionDuringReadThroughSelfTest.testPartitionRent"))
-                    val.addressNotified.clear();
-
-                cache.put(key, val);
-            }
-        );
-
-        ignite.close();
-    }
-
-    public static void mainDeletePRs(String[] args) {
-        Ignite ignite = TcHelperDb.startClient();
-
-        IgniteCache<Object, Object> cache = ignite.cache(IGitHubConnIgnited.GIT_HUB_PR);
-
-        cache.clear();
-        ignite.close();
-    }
-
-
-    public static void mainDeleteTickets(String[] args) {
-        Ignite ignite = TcHelperDb.startClient();
-
-        IgniteCache<Object, Object> cache = ignite.cache(JiraTicketDao.TEAMCITY_JIRA_TICKET_CACHE_NAME);
-
-        cache.clear();
-        ignite.close();
-    }
-}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/IgniteTeamcityHelperRunnerExample.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/IgniteTeamcityHelperRunnerExample.java
deleted file mode 100644
index 5dbe18c2..00000000
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/IgniteTeamcityHelperRunnerExample.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.ci.runners;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import org.apache.ignite.tcservice.TeamcityServiceConnection;
-import org.apache.ignite.tcservice.model.conf.BuildType;
-import org.apache.ignite.tcservice.model.conf.bt.BuildTypeFull;
-import org.apache.ignite.tcservice.model.conf.bt.SnapshotDependency;
-import org.apache.ignite.tcservice.util.TcConnectionStaticLinker;
-
-/**
- * Local class for running specific checks
- *
- * https://confluence.jetbrains.com/display/TCD10/REST+API
- */
-public class IgniteTeamcityHelperRunnerExample {
-    public static void main(String[] args) throws Exception {
-        String serverIdPriv = "private";
-        String serverIdPub = "apache";
-
-        final TeamcityServiceConnection helper = TcConnectionStaticLinker.create(serverIdPub);
-
-        int k = 0;
-        if (k > 0) {
-            //branch example: "pull/2335/head"
-            List<BuildType> buildTypes = helper.getBuildTypes("Ignite20Tests");
-
-        }
-
-        int b = 0;
-        if (b > 0)
-            checkBuildTypes(helper);
-
-        for (int i = 0; i < 0; i++) {
-            //branch example:
-            final String branchName = "<default>";
-            // String branchName = "refs/heads/master";
-            //  final String branchName = "pull/4750/head";
-            String buildTypeIdAll = "IgniteTests24Java8_RunAll";
-            String buildTypeIdAllP = "id8xIgniteGridGainTestsJava8_RunAll";
-            //  buildTypeIdAll="IgniteTests24Java8_Queries1";
-
-            helper.triggerBuild(buildTypeIdAll, branchName, true, false, Collections.emptyMap(), null);
-        }
-    }
-
-    private static void checkBuildTypes(TeamcityServiceConnection helper) {
-        Map<String, Set<String>> duplicates = new TreeMap<>();
-        Map<String, String> suiteToBt = new TreeMap<>();
-        List<BuildType> buildTypes = helper.getBuildTypes("Ignite20Tests");
-        for (BuildType bt : buildTypes) {
-            final BuildTypeFull type = helper.getBuildType(bt.getId());
-            if ("Ignite20Tests_RunAll".equals(type.getId())
-                || "IgniteTests_RunAllPds".equals(type.getId())
-                || "Ignite20Tests_RunBasicTests".equals(type.getId())) {
-                checkRunAll(type);
-                continue;
-            }
-            checkSuite(duplicates, suiteToBt, bt, type);
-        }
-
-        suiteToBt.forEach((key, v) -> {
-            System.out.println(key + "\t" + v);
-        });
-
-        if (!duplicates.isEmpty()) {
-            System.err.println("********************* Duplicates **************************");
-            duplicates.forEach((k, v) -> {
-                System.err.println(k + "\t" + v);
-            });
-        }
-    }
-
-    private static void checkSuite(Map<String, Set<String>> duplicates, Map<String, String> suiteToBt, BuildType bt,
-        BuildTypeFull type) {
-        final String suite = type.getParameter("TEST_SUITE");
-
-        if (suite == null)
-            return;
-
-        for (StringTokenizer strTokenizer = new StringTokenizer(suite, ",;"); strTokenizer.hasMoreTokens(); ) {
-            String s = strTokenizer.nextToken();
-            final String suiteJava = s.trim();
-
-            final String btName = bt.getName();
-            final String oldBtName = suiteToBt.put(suiteJava, btName);
-            if (oldBtName != null) {
-                System.err.println(suite + " for " + btName
-                    + " and for " + oldBtName);
-
-                final Set<String> duplicatesSet = duplicates.computeIfAbsent(suiteJava, k -> new TreeSet<>());
-                duplicatesSet.add(btName);
-                duplicatesSet.add(oldBtName);
-            }
-        }
-    }
-
-    private static void checkRunAll(BuildTypeFull type) {
-        System.err.println(type);
-
-        final List<SnapshotDependency> dependencies = type.dependencies();
-
-        for (SnapshotDependency next : dependencies) {
-            final String runBuild = next.getProperty("run-build-if-dependency-failed");
-
-            if (!"RUN_ADD_PROBLEM".equals(runBuild))
-                System.err.println("Incorrect configuration for dependency from [" + next.bt().getName() + "]");
-        }
-    }
-}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/RemoteClientTmpHelper.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/RemoteClientTmpHelper.java
deleted file mode 100644
index d01e3baf..00000000
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/RemoteClientTmpHelper.java
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.ci.runners;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.time.Duration;
-import java.util.Iterator;
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicInteger;
-import javax.cache.Cache;
-import javax.xml.bind.JAXBException;
-import org.apache.ignite.Ignite;
-import org.apache.ignite.IgniteCache;
-import org.apache.ignite.Ignition;
-import org.apache.ignite.ci.db.TcHelperDb;
-import org.apache.ignite.ci.issue.Issue;
-import org.apache.ignite.ci.issue.IssueKey;
-import org.apache.ignite.tcbot.engine.issue.IssueType;
-import org.apache.ignite.tcbot.engine.issue.IssuesStorage;
-import org.apache.ignite.tcbot.engine.user.UserAndSessionsStorage;
-import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
-import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
-import org.apache.ignite.ci.user.TcHelperUser;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.logger.slf4j.Slf4jLogger;
-import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
-import org.apache.ignite.tcbot.persistence.IgniteStringCompactor;
-import org.apache.ignite.tcignited.ITeamcityIgnited;
-import org.apache.ignite.tcignited.build.FatBuildDao;
-import org.apache.ignite.tcignited.buildref.BuildRefDao;
-import org.apache.ignite.tcservice.model.hist.BuildRef;
-import org.apache.ignite.tcservice.model.result.Build;
-import org.apache.ignite.tcservice.util.XmlUtil;
-import org.jetbrains.annotations.NotNull;
-
-import static org.apache.ignite.tcignited.history.BuildStartTimeStorage.BUILD_START_TIME_CACHE_NAME;
-
-/**
- * Utility class for connecting to a remote server.
- */
-public class RemoteClientTmpHelper {
-    public static String DUMPS = "dumps";
-    private static boolean dumpDict = false;
-
-
-    /**
-     * @param args Args.
-     */
-    public static void main(String[] args) {
-        mainSetUserAsAdmin(args);
-
-        //mainDumpAllUsers(args);
-        // mainExport(args);
-        // mainDropInvalidIssues(args);
-        System.err.println("Please insert option of main");
-    }
-
-
-    /**
-     * @param args Args.
-     */
-    public static void mainSetUserAsAdmin(String[] args) {
-        try (Ignite ignite = tcbotServerConnectedClient()) {
-            IgniteCache<String, TcHelperUser> users = ignite.cache(UserAndSessionsStorage.USERS);
-            TcHelperUser user = users.get("dpavlov");
-            user.setAdmin(true);
-            users.put(user.username, user);
-        }
-    }
-
-
-    public static void mainDropInvalidIssues(String[] args) {
-        try (Ignite ignite = tcbotServerConnectedClient()) {
-            IgniteCache<IssueKey, Issue>  bst = ignite.cache(IssuesStorage.BOT_DETECTED_ISSUES);
-            Iterator<Cache.Entry<IssueKey, Issue>> iter = bst.iterator();
-            try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(dumpsDir(),
-                "Issues_dropped.txt")))) {
-                while (iter.hasNext()) {
-                    Cache.Entry<IssueKey, Issue> next = iter.next();
-
-                    boolean rmv = false;
-                    Issue val = next.getValue();
-                    if (val.type == null)
-                        rmv = true;
-
-                    //don't touch it
-                    if (Objects.equals(val.type, IssueType.newContributedTestFailure.code()))
-                        continue;
-
-                    long ageDays = -1;
-                    if (val != null && val.buildStartTs == null) {
-                        if (val.detectedTs == null)
-                            rmv = true;
-                        else
-                            ageDays = Duration.ofMillis(System.currentTimeMillis() - val.detectedTs).toDays();
-
-
-                        rmv = true;
-                    }
-
-                    if(rmv) {
-                        bst.remove(next.getKey());
-
-                        String str = "Removing issue " + next.getKey() + " " + val.type + " detected " +
-                            ageDays + " days ago\n";
-                        writer.write(str);
-                        System.err.println(str);
-                    }
-                }
-
-                writer.flush();
-            }
-            catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
-
-            dumpDictionary(ignite);
-        }
-    }
-
-
-    public static void mainDumpIssues(String[] args) {
-        try (Ignite ignite = tcbotServerConnectedClient()) {
-            IgniteCache<IssueKey, Issue>  bst = ignite.cache(IssuesStorage.BOT_DETECTED_ISSUES);
-            Iterator<Cache.Entry<IssueKey, Issue>> iter = bst.iterator();
-            try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(dumpsDir(),
-                "Issues.txt")))) {
-                while (iter.hasNext()) {
-                    Cache.Entry<IssueKey, Issue> next = iter.next();
-
-                    Issue val = next.getValue();
-                    long ageDays = -1;
-                    if (val != null && val.buildStartTs != null)
-                        ageDays = Duration.ofMillis(System.currentTimeMillis() - val.buildStartTs).toDays();
-
-                    writer.write(next.getKey() + " " + val + " " +
-                        ageDays + "\n");
-                }
-
-                writer.flush();
-            }
-            catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
-
-            dumpDictionary(ignite);
-        }
-    }
-
-
-    public static void mainDumpFatBuildStartTime(String[] args) {
-        try (Ignite ignite = tcbotServerConnectedClient()) {
-            IgniteCache<Long, FatBuildCompacted> bst = ignite.cache(FatBuildDao.TEAMCITY_FAT_BUILD_CACHE_NAME);
-            Iterator<Cache.Entry<Long, FatBuildCompacted>> iterator = bst.iterator();
-            try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(dumpsDir(),
-                    "fatBuildStartTime.txt")))) {
-                while (iterator.hasNext()) {
-                    Cache.Entry<Long, FatBuildCompacted> next = iterator.next();
-
-                    FatBuildCompacted val = next.getValue();
-                    long ageDays = -1;
-                    long startDateTs = -2;
-
-                    if (val != null) {
-                        startDateTs = val.getStartDateTs();
-                        ageDays = Duration.ofMillis(System.currentTimeMillis() - startDateTs).toDays();
-                    }
-
-                    writer.write(next.getKey() + " " + startDateTs + " " +
-                            ageDays + "\n");
-                }
-
-            }
-            catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
-        }
-    }
-
-
-    public static void mainDumpBuildStartTime(String[] args) {
-        try (Ignite ignite = tcbotServerConnectedClient()) {
-            IgniteCache<Long, Long> bst = ignite.cache(BUILD_START_TIME_CACHE_NAME);
-            Iterator<Cache.Entry<Long, Long>> iterator = bst.iterator();
-            try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(dumpsDir(),
-                    "BuildStartTime.txt")))) {
-            while (iterator.hasNext()) {
-                Cache.Entry<Long, Long> next = iterator.next();
-
-                Long val = next.getValue();
-                long ageDays = -1;
-                if(val!=null)
-                ageDays = Duration.ofMillis(System.currentTimeMillis() - val).toDays();
-
-                writer.write(next.getKey() + " " + val + " " +
-                    ageDays +"\n");
-            }
-
-            }
-            catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
-        }
-    }
-
-
-    /**
-     * @param args Args.
-     */
-    public static void mainResetUser(String[] args) {
-        try (Ignite ignite = tcbotServerConnectedClient()) {
-            IgniteCache<String, TcHelperUser> users = ignite.cache(UserAndSessionsStorage.USERS);
-            TcHelperUser user = users.get("user");
-            user.resetCredentials();
-            users.put(user.username, user);
-        }
-    }
-
-    /**
-     * @param args Args.
-     */
-    public static void mainDestroyAllFatBuilds(String[] args) {
-        int fatBuildsCnt;
-        try (Ignite ignite = tcbotServerConnectedClient()) {
-            IgniteCache<Object, Object> cacheHistEntries = ignite.cache(    FatBuildDao.TEAMCITY_FAT_BUILD_CACHE_NAME);
-            fatBuildsCnt = cacheHistEntries.size();
-
-            System.err.println("Start destroy() operation for fat builds: " + fatBuildsCnt);
-            cacheHistEntries.destroy();
-            System.err.println("Finish destroy() operation");
-
-        }
-
-        System.err.println("Test hist entries destroyed: [" + fatBuildsCnt + "] builds");
-    }
-
-
-    public static void mainDestroyTestHist(String[] args) {
-        int buildStartTimes;
-
-        try (Ignite ignite = tcbotServerConnectedClient()) {
-
-            IgniteCache<Object, Object> cacheStartTimes = ignite.cache(BUILD_START_TIME_CACHE_NAME);
-
-            buildStartTimes = cacheStartTimes.size();
-
-            System.err.println("Start destroy operation for build start times flag");
-            cacheStartTimes.destroy();
-            System.err.println("Finish destroy operation");
-        }
-
-        System.err.println("Test build start times destroyed [" + buildStartTimes + "] builds");
-    }
-
-    /**
-     * @param args Args.
-     */
-    public static void main2(String[] args) {
-        int inconsistent;
-
-        try (Ignite ignite = tcbotServerConnectedClient()) {
-            inconsistent = validateBuildIdConsistency(ignite);
-        }
-
-        System.err.println("Inconsistent builds in queue found [" + inconsistent + "]");
-    }
-
-    public static int validateBuildIdConsistency(Ignite ignite) {
-        AtomicInteger inconsistent = new AtomicInteger();
-        String apacheSrvName = "apache";
-        int apache = ITeamcityIgnited.serverIdToInt(apacheSrvName);
-
-        IgniteCache<String, org.apache.ignite.ci.teamcity.ignited.IgniteStringCompactor.CompactorEntity> strings = ignite.cache(IgniteStringCompactor.STRINGS_CACHE);
-        org.apache.ignite.ci.teamcity.ignited.IgniteStringCompactor.CompactorEntity queuedEnt = strings.get(BuildRef.STATE_QUEUED);
-        int stateQ = queuedEnt.id();
-        IgniteCache<Long, BuildRefCompacted> cacheRef = ignite.cache(BuildRefDao.TEAMCITY_BUILD_CACHE_NAME);
-        IgniteCache<Long, FatBuildCompacted> cacheFat = ignite.cache(FatBuildDao.TEAMCITY_FAT_BUILD_CACHE_NAME);
-
-        cacheRef.forEach(
-            entry -> {
-                BuildRefCompacted buildRef = entry.getValue();
-
-                int buildId = BuildRefDao.cacheKeyToBuildId(entry.getKey());
-
-                if (buildRef.state() == stateQ && BuildRefDao.isKeyForServer(entry.getKey(), apache)) {
-
-                    FatBuildCompacted fat = cacheFat.get(FatBuildDao.buildIdToCacheKey(apache, buildId));
-                    if (fat != null && fat.getId() != buildId) {
-                        dumpBuildRef(buildId, buildRef);
-                        dumpFatBuild(cacheFat, apache, buildId);
-
-                        inconsistent.incrementAndGet();
-
-                        if (!fat.isOutdatedEntityVersion())
-                            Preconditions.checkState(false);
-                    }
-                }
-            }
-        );
-
-        return inconsistent.get();
-    }
-
-    public static void dumpOldBuild(int buildId, String href, Build fatBuild) {
-        try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(dumpsDir(), "BuildOld" + buildId + ".txt")))) {
-            writer.write("<!--" + href + "-->\n");
-            writer.write(XmlUtil.save(fatBuild));
-        }
-        catch (IOException e) {
-            throw new UncheckedIOException(e);
-        }
-        catch (JAXBException e) {
-            e.printStackTrace();
-        }
-    }
-
-    private static void setupDisco(IgniteConfiguration cfg) {
-        final TcpDiscoverySpi spi = new TcpDiscoverySpi();
-        final int locPort = 54433;
-        spi.setLocalPort(locPort);
-        spi.setLocalPortRange(1);
-        TcpDiscoveryVmIpFinder finder = new TcpDiscoveryVmIpFinder();
-        finder.setAddresses(Lists.newArrayList("172.25.5.21:" + locPort));
-
-        spi.setIpFinder(finder);
-
-        cfg.setDiscoverySpi(spi);
-    }
-
-    public static void mainExport(String[] args) {
-        final Ignite ignite = tcbotServerConnectedClient();
-
-        if (dumpDict)
-            dumpDictionary(ignite);
-
-        if (true) {
-            IgniteCache<Long, FatBuildCompacted> cache1 = ignite.cache(FatBuildDao.TEAMCITY_FAT_BUILD_CACHE_NAME);
-
-            int apache = ITeamcityIgnited.serverIdToInt("apache");
-
-            int id = 4466392;
-            int id1 = 4465532;
-            dumpFatBuild(cache1, apache, id);
-            dumpFatBuild(cache1, apache, id1);
-
-            IgniteCache<Long, BuildRefCompacted> cache2 = ignite.cache(BuildRefDao.TEAMCITY_BUILD_CACHE_NAME);
-            dumpBuildRef(cache2, apache, id);
-            dumpBuildRef(cache2, apache, id1);
-        }
-
-        ignite.close();
-    }
-
-    public static void dumpDictionary(Ignite ignite) {
-        IgniteCache<String, Object> strings = ignite.cache(IgniteStringCompactor.STRINGS_CACHE);
-        try {
-            try (FileWriter writer = new FileWriter(new File(dumpsDir(), "Dictionary.txt"))) {
-                for (Cache.Entry<String, Object> next1 : strings) {
-                    writer.write(next1.getValue().toString()
-                        + "\n");
-                }
-            }
-        }
-        catch (IOException e) {
-            throw new UncheckedIOException(e);
-        }
-    }
-
-    public static Ignite tcbotServerConnectedClient() {
-        final IgniteConfiguration cfg = new IgniteConfiguration();
-
-        setupDisco(cfg);
-
-        cfg.setGridLogger(new Slf4jLogger());
-
-        cfg.setClientMode(true);
-
-        return Ignition.start(cfg);
-    }
-
-    public static void dumpBuildRef(IgniteCache<Long, BuildRefCompacted> cache, int apache, int id) {
-        long l = BuildRefDao.buildIdToCacheKey(apache, id);
-        BuildRefCompacted compacted = cache.get(l);
-        dumpBuildRef(id, compacted);
-    }
-
-    public static void dumpBuildRef(int id, BuildRefCompacted compacted) {
-        Preconditions.checkNotNull(compacted, "Can't find build by ID " + id);
-
-        File dumps = dumpsDir();
-
-        try (FileWriter writer = new FileWriter(new File(dumps, "BuildRef " + id + ".txt"))) {
-            writer.write(compacted.toString());
-        }
-        catch (IOException e) {
-            throw new UncheckedIOException(e);
-        }
-    }
-
-
-    public static void mainDumpAllUsers(String[] args) {
-        try (Ignite ignite = tcbotServerConnectedClient()) {
-            IgniteCache<String, TcHelperUser>users = ignite.cache(UserAndSessionsStorage.USERS);
-
-            Iterator<Cache.Entry<String, TcHelperUser>> iterator = users.iterator();
-            while (iterator.hasNext()) {
-                Cache.Entry<String, TcHelperUser> next = iterator.next();
-                dumpUser(next.getValue());
-            }
-        }
-    }
-
-    private static void dumpUser(TcHelperUser value) {
-        try (FileWriter writer = new FileWriter(new File(dumpsDir(), "Build " + value.username() + ".txt"))) {
-            writer.write(value.toString());
-        }
-        catch (IOException e) {
-            throw new UncheckedIOException(e);
-        }
-    }
-
-    @NotNull public static File dumpsDir() {
-        File dumps = new File(DUMPS);
-        if (!dumps.exists())
-            Preconditions.checkState(dumps.mkdirs());
-        return dumps;
-    }
-
-    public static FatBuildCompacted dumpFatBuild(IgniteCache<Long, FatBuildCompacted> cache, int apache, int id) {
-        long l = FatBuildDao.buildIdToCacheKey(apache, id);
-        FatBuildCompacted compacted = cache.get(l);
-        Preconditions.checkNotNull(compacted, "Can't find build by ID " + id);
-
-        try (FileWriter writer = new FileWriter(new File(dumpsDir(), "Build " + id + ".txt"))) {
-            writer.write(compacted.toString());
-        }
-        catch (IOException e) {
-            throw new UncheckedIOException(e);
-        }
-        return compacted;
-    }
-}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/TcBotBgAuthImpl.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/TcBotBgAuthImpl.java
index bb065cd0..124e9e8a 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/TcBotBgAuthImpl.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/TcBotBgAuthImpl.java
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.Nullable;
 /**
  *
  */
-class TcBotBgAuthImpl implements ITcBotBgAuth {
+public class TcBotBgAuthImpl implements ITcBotBgAuth {
     /** Server authorizer credentials. */
     private ITcBotUserCreds srvAuthorizerCreds;
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/IssueDetector.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/IssueDetector.java
index 2c85de87..eb775bf1 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/IssueDetector.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/IssueDetector.java
@@ -90,7 +90,7 @@ public class IssueDetector {
 
     private final AtomicBoolean init = new AtomicBoolean();
     private ITcBotUserCreds backgroundOpsCreds;
-    @Deprecated //todo use scheduler
+    @Deprecated
     private ScheduledExecutorService executorService;
 
     @Inject private Provider<CheckQueueJob> checkQueueJobProv;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/Notification.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/Notification.java
index 87fba013..7c4100e9 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/Notification.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/Notification.java
@@ -17,13 +17,18 @@
 
 package org.apache.ignite.ci.tcbot.issue;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
 import java.util.stream.Stream;
 import org.apache.ignite.ci.issue.Issue;
 import org.apache.ignite.ci.web.model.Version;
 import org.apache.ignite.tcbot.common.util.TimeUtil;
 
-import java.util.*;
-
 import static org.apache.ignite.ci.web.model.Version.GITHUB_REF;
 
 public class Notification {
@@ -164,17 +169,14 @@ public class Notification {
     }
 
     public String countIssues() {
-        return "";
+        return String.valueOf(allIssues().count());
     }
 
     public List<String> toSlackMarkup() {
         List<String> res = new ArrayList<>();
 
-        for (Map.Entry<Integer, List<Issue>> nextEntry : buildIdToIssue.entrySet()) {
-            List<Issue> issues = nextEntry.getValue();
-
+        for (List<Issue> issues : buildIdToIssue.values())
             res.add(toSlackMarkup(issues));
-        }
 
         return res;
     }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
index 021069fa..f496db07 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
@@ -20,7 +20,6 @@ package org.apache.ignite.ci.tcbot.visa;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
-import com.google.inject.Provider;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -41,6 +40,7 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import javax.annotation.Nonnull;
 import javax.inject.Inject;
+import javax.inject.Provider;
 import org.apache.ignite.ci.github.GitHubBranch;
 import org.apache.ignite.ci.github.GitHubUser;
 import org.apache.ignite.ci.github.PullRequest;
@@ -311,8 +311,6 @@ public class TcBotTriggerAndSignOffService {
         }
 
         String[] suiteIds = Objects.requireNonNull(suiteIdList).split(",");
-
-        //todo consult if there are change differences here https://ci.ignite.apache.org/app/rest/changes?locator=buildType:(id:IgniteTests24Java8_Cache7),pending:true,branch:pull%2F6224%2Fhead
         Build[] builds = new Build[suiteIds.length];
         Set<Integer> buildidsToSync = new HashSet<>();
 
@@ -599,7 +597,7 @@ public class TcBotTriggerAndSignOffService {
             contribution.prTitle = ticket.fields.summary();
             contribution.prHtmlUrl = "";
             contribution.prHeadCommit = "";
-            contribution.prTimeUpdate = ""; //todo ticket updateTime
+            contribution.prTimeUpdate = "";
 
             contribution.prAuthor = "";
             contribution.prAuthorAvatarUrl = "";
@@ -904,7 +902,6 @@ public class TcBotTriggerAndSignOffService {
 
         if (status.branchWithFinishedSuite != null)
             status.resolvedBranch = status.branchWithFinishedSuite;
-            //todo take into account running/queued
         else
             status.resolvedBranch = !builds.isEmpty() ? builds.get(0).branchName(compactor) : branchForTcDefault(prId, ghConn);
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/CtxListener.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/CtxListener.java
index b1d0cc59..ee531952 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/CtxListener.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/CtxListener.java
@@ -17,56 +17,44 @@
 
 package org.apache.ignite.ci.web;
 
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import java.io.IOException;
 import java.util.logging.Handler;
 import javax.annotation.Nullable;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
-import org.apache.ignite.Ignite;
-import org.apache.ignite.ci.db.TcHelperDb;
-import org.apache.ignite.ci.observer.BuildObserver;
-import org.apache.ignite.ci.tcbot.TcBotWebAppModule;
-import org.apache.ignite.ci.tcbot.issue.IssueDetector;
-import org.apache.ignite.tcbot.common.interceptor.MonitoredTaskInterceptor;
-import org.apache.ignite.tcbot.engine.cleaner.Cleaner;
-import org.apache.ignite.tcbot.engine.conf.INotificationChannel;
-import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
-import org.apache.ignite.tcbot.engine.conf.NotificationsConfig;
-import org.apache.ignite.tcbot.engine.pool.TcUpdatePool;
-import org.apache.ignite.tcbot.notify.ISlackSender;
-import org.apache.ignite.tcbot.persistence.scheduler.IScheduler;
-import org.apache.ignite.tcservice.http.TeamcityRecorder;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContexts;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  */
 public class CtxListener implements ServletContextListener {
-    /** Javax.Injector property code for servlet context. */
-    private static final String INJECTOR = "injector";
+    /** TC Bot application context servlet attribute. */
+    private static final String APPLICATION_CONTEXT = "tcBotApplicationContext";
 
     @Nullable private static volatile Logger logger;
 
-    public static Injector getInjector(ServletContext ctx) {
-        return (Injector)ctx.getAttribute(INJECTOR);
+    public static TcBotApplicationContext getApplicationContext(ServletContext ctx) {
+        return (TcBotApplicationContext)ctx.getAttribute(APPLICATION_CONTEXT);
     }
 
     /** {@inheritDoc} */
     @Override public void contextInitialized(ServletContextEvent sctxEvt) {
         initLoggerBridge();
-        TcBotWebAppModule igniteTcBotModule = new TcBotWebAppModule();
-        Injector injectorPreCreated = Guice.createInjector(igniteTcBotModule);
 
-        Injector injector = igniteTcBotModule.startIgniteInit(injectorPreCreated);
+        TcBotApplicationContext appCtx = TcBotApplicationContexts.create();
 
-        final ServletContext ctx = sctxEvt.getServletContext();
+        try {
+            appCtx.start();
 
-        ctx.setAttribute(INJECTOR, injector);
+            sctxEvt.getServletContext().setAttribute(APPLICATION_CONTEXT, appCtx);
+        }
+        catch (RuntimeException | Error e) {
+            closeFailedContext(appCtx, e);
 
-        sendMessageToSlackChannel("TeamCity Bot is started!", ctx);
+            throw e;
+        }
     }
 
     /**
@@ -86,72 +74,26 @@ public class CtxListener implements ServletContextListener {
 
     /** {@inheritDoc} */
     @Override public void contextDestroyed(ServletContextEvent sctxEvt) {
-        final ServletContext ctx = sctxEvt.getServletContext();
-
-        sendMessageToSlackChannel("TeamCity Bot is stopped!", ctx);
-
-        Injector injector = getInjector(ctx);
-
         try {
-            injector.getInstance(IssueDetector.class).stop();
-            injector.getInstance(TcUpdatePool.class).stop();
-            injector.getInstance(BuildObserver.class).stop();
-            injector.getInstance(IScheduler.class).stop();
-            injector.getInstance(Cleaner.class).stop();
-        }
-        catch (Exception e) {
-            e.printStackTrace();
+            TcBotApplicationContext appCtx = getApplicationContext(sctxEvt.getServletContext());
 
-            if (logger != null)
-                logger.error("Exception during shutdown: " + e.getMessage(), e);
-        }
-
-        try {
-            injector.getInstance(TeamcityRecorder.class).stop();
-        }
-        catch (IOException e) {
-            e.printStackTrace();
-
-            if (logger != null)
-                logger.error("Exception during shutdown: " + e.getMessage(), e);
-        }
-
-        try {
-            injector.getInstance(MonitoredTaskInterceptor.class).close();
-        }
-        catch (Exception e) {
-            e.printStackTrace();
-        }
-
-        try {
-            TcHelperDb.stop(injector.getInstance(Ignite.class));
+            if (appCtx != null)
+                appCtx.close();
         }
         catch (Exception e) {
             e.printStackTrace();
 
             if (logger != null)
-                logger.error("Exception during shutdown: " + e.getMessage(), e);
+                logger.error("Exception during TC Bot application context close: " + e.getMessage(), e);
         }
     }
 
-    private void sendMessageToSlackChannel(String msg, ServletContext ctx) {
+    private void closeFailedContext(TcBotApplicationContext appCtx, Throwable startFailure) {
         try {
-            ISlackSender slackSender = CtxListener.getInjector(ctx).getInstance(ISlackSender.class);
-
-            ITcBotConfig tcBotConfig = CtxListener.getInjector(ctx).getInstance(ITcBotConfig.class);
-
-            NotificationsConfig notifications = tcBotConfig.notifications();
-
-            for (INotificationChannel channel : notifications.channels()) {
-                if (channel.slack() != null && channel.slack().startsWith("#"))
-                    slackSender.sendMessage(channel.slack(), msg, notifications);
-            }
+            appCtx.close();
         }
-        catch (Exception e) {
-            e.printStackTrace();
-
-            if (logger != null)
-                logger.error("Exception during sending message to the slack channel: " + e.getMessage(), e);
+        catch (Throwable closeFailure) {
+            startFailure.addSuppressed(closeFailure);
         }
     }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/Launcher.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/Launcher.java
index bd86fcfd..b80aa420 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/Launcher.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/Launcher.java
@@ -41,6 +41,7 @@ public class Launcher {
     /**
      * @param dev Dev mode.
      */
+    @SuppressWarnings("deprecation")
     public static void runServer(boolean dev) throws Exception {
         if(dev)
             System.setProperty(TcBotSystemProperties.DEV_MODE, "true");
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/auth/AuthenticationFilter.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/auth/AuthenticationFilter.java
index b81b834f..f92b81d7 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/auth/AuthenticationFilter.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/auth/AuthenticationFilter.java
@@ -18,16 +18,13 @@
 package org.apache.ignite.ci.web.auth;
 
 import com.google.common.base.Throwables;
-import com.google.inject.Injector;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
 import java.lang.reflect.Method;
 import java.util.Arrays;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 import java.util.StringTokenizer;
 import javax.annotation.security.DenyAll;
 import javax.annotation.security.PermitAll;
-import javax.annotation.security.RolesAllowed;
 import javax.crypto.BadPaddingException;
 import javax.servlet.ServletContext;
 import javax.ws.rs.container.ContainerRequestContext;
@@ -66,7 +63,6 @@ public class AuthenticationFilter implements ContainerRequestFilter {
     private ServletContext context;
 
     private static final String AUTHORIZATION_PROPERTY = "Authorization";
-    private static final String AUTHENTICATION_SCHEME = "Basic";
     private static final String TOKEN_SCHEME = "Token";
 
     private static Response rspUnathorized() {
@@ -81,8 +77,6 @@ public class AuthenticationFilter implements ContainerRequestFilter {
 
     @Override public void filter(ContainerRequestContext reqCtx) {
         Method mtd = resourceInfo.getResourceMethod();
-
-        //todo uncomment for development
         //if(method!=null)
         //    return;
 
@@ -110,9 +104,8 @@ public class AuthenticationFilter implements ContainerRequestFilter {
             return;
         }
 
-        //Get encoded username and encodedPassword
         String authStr = authorization.get(0);
-        if(!authStr.startsWith(TOKEN_SCHEME)) {
+        if (!authStr.startsWith(TOKEN_SCHEME)) {
             reqCtx.abortWith(rspForbidden());
 
             return;
@@ -120,11 +113,11 @@ public class AuthenticationFilter implements ContainerRequestFilter {
 
         String tokFull = authStr.substring(TOKEN_SCHEME.length()).trim();
 
-        Injector injector = CtxListener.getInjector(context);
-        final IUserStorage users = injector.getInstance(IUserStorage.class);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(context);
+        final IUserStorage users = appCtx.getInstance(IUserStorage.class);
 
         try {
-            injector.getInstance(Ignite.class);
+            appCtx.getInstance(Ignite.class);
         } catch (Exception e) {
             ExceptionUtil.throwIfRest(e);
 
@@ -135,21 +128,6 @@ public class AuthenticationFilter implements ContainerRequestFilter {
 
         if (!authenticate(reqCtx, tokFull, users)) {
             reqCtx.abortWith(rspUnathorized());
-
-            return;
-        }
-
-        //Verify user access
-        if (mtd.isAnnotationPresent(RolesAllowed.class)) {
-            RolesAllowed rolesAnnotation = mtd.getAnnotation(RolesAllowed.class);
-            Set<String> rolesSet = new HashSet<String>(Arrays.asList(rolesAnnotation.value()));
-
-            //Is user valid?
-            if (!isUserAllowed("", "", rolesSet)) {
-                reqCtx.abortWith(rspForbidden());
-
-                return;
-            }
         }
     }
 
@@ -193,7 +171,7 @@ public class AuthenticationFilter implements ContainerRequestFilter {
             userKey = CryptUtil.aesDecrypt(Base64Util.decodeString(tok), ses.userKeyUnderToken);
             byte[] userKeyKcv = CryptUtil.aesKcv(userKey);
 
-            if(!Arrays.equals(userKeyKcv, user.userKeyKcv)) {
+            if (!Arrays.equals(userKeyKcv, user.userKeyKcv)) {
                 logger.error("User provided " + ses.username + " invalid token ,failed at " + sessId + " enforcing login");
 
                 return false;
@@ -259,22 +237,4 @@ public class AuthenticationFilter implements ContainerRequestFilter {
             }
         };
     }
-
-    private boolean isUserAllowed(final String username, final String pwd, final Set<String> rolesSet) {
-        boolean isAllowed = false;
-
-        //Step 1. Fetch encodedPassword from database and match with encodedPassword in argument
-        //If both match then get the defined role for user from database and continue; else return isAllowed [false]
-        //Access the database and do this part yourself
-        //String userRole = userMgr.getUserRole(username);
-
-        if (username.equals("howtodoinjava") && pwd.equals("encodedPassword")) {
-            String userRole = "ADMIN";
-
-            //Step 2. Verify user role
-            if (rolesSet.contains(userRole))
-                isAllowed = true;
-        }
-        return isAllowed;
-    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/trends/BuildsHistory.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/trends/BuildsHistory.java
index 3fa1f956..5fc21d93 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/trends/BuildsHistory.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/trends/BuildsHistory.java
@@ -135,7 +135,6 @@ import static com.google.common.base.Strings.isNullOrEmpty;
         private DateFormat dateFormat = new SimpleDateFormat("ddMMyyyyHHmmss");
 
         public Builder(ITcBotConfig cfg) {
-            // todo may find findDefaultBuildType() from cfg.getTeamcityConfig(srvCode).defaultTrackedBranch()
         }
 
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetBuildLog.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetBuildLog.java
index 09524166..61736f3c 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetBuildLog.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetBuildLog.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.ci.web.rest;
 
-import com.google.inject.Injector;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
 import org.apache.ignite.ci.web.CtxListener;
 import org.apache.ignite.tcbot.engine.ui.BotUrls;
 import org.apache.ignite.tcignited.buildlog.IBuildLogProcessor;
@@ -58,9 +58,9 @@ public class GetBuildLog {
     public Response getThreadDump(
         @QueryParam(BotUrls.GetBuildLog.SERVER_ID) String srvCode,
         @QueryParam(BotUrls.GetBuildLog.BUILD_NO) Integer buildId) {
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
-        IBuildLogProcessor instance = injector.getInstance(IBuildLogProcessor.class);
+        IBuildLogProcessor instance = appCtx.getInstance(IBuildLogProcessor.class);
 
         String cached = instance.getThreadDumpCached(srvCode, buildId);
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetTrackedBranches.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetTrackedBranches.java
index cdb687f5..c885cc88 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetTrackedBranches.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetTrackedBranches.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.ci.web.rest;
 
 import com.google.common.base.Strings;
-import com.google.inject.Injector;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -65,7 +65,14 @@ public class GetTrackedBranches {
     @Path("version")
     @PermitAll
     public Version version() {
-        return CtxListener.getInjector(ctx).getInstance(TcBotGeneralService.class).version();
+        return CtxListener.getApplicationContext(ctx).getInstance(TcBotGeneralService.class).version();
+    }
+
+    @GET
+    @Path("ready")
+    @PermitAll
+    public boolean ready() {
+        return CtxListener.getApplicationContext(ctx).isReady();
     }
 
     @GET
@@ -79,9 +86,9 @@ public class GetTrackedBranches {
 
     @NotNull public Stream<ITrackedBranch> accessibleTrackedBranches() {
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
-        Injector injector = CtxListener.getInjector(ctx);
-        ITcBotConfig cfg = injector.getInstance(ITcBotConfig.class);
-        ITeamcityIgnitedProvider tcProv = injector.getInstance(ITeamcityIgnitedProvider.class);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
+        ITcBotConfig cfg = appCtx.getInstance(ITcBotConfig.class);
+        ITeamcityIgnitedProvider tcProv = appCtx.getInstance(ITeamcityIgnitedProvider.class);
 
         return cfg.getTrackedBranches().branchesStream()
             .filter(bt ->
@@ -108,9 +115,9 @@ public class GetTrackedBranches {
     @Path("suites")
     public Set<ChainAtServer> getSuites(@Nullable @QueryParam("server") String srvId) {
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
-        Injector injector = CtxListener.getInjector(ctx);
-        ITcBotConfig cfg = injector.getInstance(ITcBotConfig.class);
-        ITeamcityIgnitedProvider tcProv = injector.getInstance(ITeamcityIgnitedProvider.class);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
+        ITcBotConfig cfg = appCtx.getInstance(ITcBotConfig.class);
+        ITeamcityIgnitedProvider tcProv = appCtx.getInstance(ITeamcityIgnitedProvider.class);
 
         return getSuitesUnique(cfg.getTrackedBranches())
             .stream()
@@ -128,9 +135,9 @@ public class GetTrackedBranches {
     @Path("getServerIds")
     public Set<String> getServerIds() {
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
-        Injector injector = CtxListener.getInjector(ctx);
-        ITcBotConfig cfg = injector.getInstance(ITcBotConfig.class);
-        ITeamcityIgnitedProvider tcProv = injector.getInstance(ITeamcityIgnitedProvider.class);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
+        ITcBotConfig cfg = appCtx.getInstance(ITcBotConfig.class);
+        ITeamcityIgnitedProvider tcProv = appCtx.getInstance(ITeamcityIgnitedProvider.class);
 
         return cfg.getServerIds()
             .stream()
@@ -146,7 +153,7 @@ public class GetTrackedBranches {
     @GET
     @Path("tcBranches")
     public Set<String> tcBranches(@Nullable @QueryParam("srvCode") String srvCodeOrAlias) {
-        ITeamcityIgnited srv = CtxListener.getInjector(ctx)
+        ITeamcityIgnited srv = CtxListener.getApplicationContext(ctx)
             .getInstance(ITeamcityIgnitedProvider.class)
             .server(srvCodeOrAlias, ITcBotUserCreds.get(req));
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/ServerIntegrationLinks.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/ServerIntegrationLinks.java
deleted file mode 100644
index fa58ecba..00000000
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/ServerIntegrationLinks.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.ci.web.rest;
-
-/**
- *
- */
-public class ServerIntegrationLinks {
-    /** Server ID. */
-    public final String srvId;
-
-    /** URL for git integration. */
-    public final String gitApiUrl;
-
-    /** URL for JIRA integration. */
-    public final String jiraApiUrl;
-
-    /**
-     * @param srvId Server ID.
-     * @param gitApiUrl URL for git integration.
-     * @param jiraApiUrl URL for JIRA integration.
-     */
-    public ServerIntegrationLinks(String srvId, String gitApiUrl, String jiraApiUrl) {
-        this.srvId = srvId;
-        this.gitApiUrl = gitApiUrl;
-        this.jiraApiUrl = jiraApiUrl;
-    }
-}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuilds.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuilds.java
index afb8a685..3d1d6356 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuilds.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuilds.java
@@ -17,11 +17,7 @@
 
 package org.apache.ignite.ci.web.rest;
 
-import com.google.inject.Injector;
-import java.util.Arrays;
-import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Collectors;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
 import javax.annotation.Nonnull;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -32,17 +28,12 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 
-import org.apache.ignite.githubservice.IGitHubConnection;
-import org.apache.ignite.githubservice.IGitHubConnectionProvider;
-import org.apache.ignite.tcbot.common.conf.IJiraServerConfig;
-import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
 import org.apache.ignite.ci.tcbot.trigger.TriggerResult;
 import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.ci.user.ITcBotUserCreds;
 import org.apache.ignite.ci.tcbot.visa.TcBotTriggerAndSignOffService;
 import org.apache.ignite.ci.web.CtxListener;
 import org.apache.ignite.ci.web.model.SimpleResult;
-import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import static com.google.common.base.Strings.isNullOrEmpty;
@@ -87,14 +78,14 @@ public class TriggerBuilds {
         @Nonnull @QueryParam("cleanRebuild") Boolean cleanRebuild
     ) {
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
-        injector.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCodeOrAlias, prov);
+        appCtx.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCodeOrAlias, prov);
 
         if (isNullOrEmpty(suiteIdList))
             return new TriggerResult("Error: nothing to run.");
 
-        String jiraRes = injector
+        String jiraRes = appCtx
             .getInstance(TcBotTriggerAndSignOffService.class)
             .triggerBuildsAndObserve(srvCodeOrAlias, branchForTc, parentSuiteId, suiteIdList, top, observe, ticketId, prNum, baseBranchForTc, cleanRebuild, prov);
 
@@ -118,36 +109,12 @@ public class TriggerBuilds {
     ) {
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
 
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
-        injector.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, prov);
+        appCtx.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, prov);
 
-        return injector
+        return appCtx
             .getInstance(TcBotTriggerAndSignOffService.class)
             .commentJiraEx(srvCode, branchForTc, suiteId, ticketId, baseBranchForTc, prov);
     }
-
-    @GET
-    @Path("integrationUrls")
-    public Set<ServerIntegrationLinks> getIntegrationUrls(@NotNull @QueryParam("serverIds") String srvCodes) {
-        ITcBotUserCreds prov = ITcBotUserCreds.get(req);
-
-        Injector injector = CtxListener.getInjector(ctx);
-
-        ITcBotConfig cfg = injector.getInstance(ITcBotConfig.class);
-        ITeamcityIgnitedProvider tcIgnProv = injector.getInstance(ITeamcityIgnitedProvider.class);
-
-        String[] srvCodesArr = srvCodes.split(",");
-
-        return Arrays.stream(srvCodesArr).map(srvCode -> {
-            if (!tcIgnProv.hasAccess(srvCode, prov))
-                return null;
-
-            IGitHubConnection gh = injector.getInstance(IGitHubConnectionProvider.class).server(srvCode);
-
-            IJiraServerConfig jiraCfg = cfg.getJiraConfig(srvCode);
-
-            return new ServerIntegrationLinks(srvCode, gh.config().gitApiUrl(), jiraCfg.restApiUrl());
-        }).filter(Objects::nonNull).collect(Collectors.toSet());
-    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/board/BoardRestService.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/board/BoardRestService.java
index 58a5650e..78c7d974 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/board/BoardRestService.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/board/BoardRestService.java
@@ -58,7 +58,7 @@ public class BoardRestService {
     public BoardSummaryUi getSummary(@QueryParam("baseBranch") String baseBranch) {
         ITcBotUserCreds creds = ITcBotUserCreds.get(req);
 
-        return CtxListener.getInjector(ctx).getInstance(BoardService.class).summary(creds, baseBranch);
+        return CtxListener.getApplicationContext(ctx).getInstance(BoardService.class).summary(creds, baseBranch);
     }
 
     @PUT
@@ -73,7 +73,7 @@ public class BoardRestService {
         @FormParam("comment") String comment,
         @FormParam("userName") String userName,
         @FormParam("webUrl") String webUrl) {
-        CtxListener.getInjector(ctx).getInstance(BoardService.class)
+        CtxListener.getApplicationContext(ctx).getInstance(BoardService.class)
             .muteIssue(tcSrvId, nameId, branch, trackedBranch, issueType, jiraTicket, comment, userName, webUrl);
     }
 
@@ -86,7 +86,7 @@ public class BoardRestService {
         @FormParam("issueType") String issueType,
         @FormParam("jiraTicket") String jiraTicket,
         @FormParam("comment") String comment) {
-        CtxListener.getInjector(ctx).getInstance(BoardService.class)
+        CtxListener.getApplicationContext(ctx).getInstance(BoardService.class)
             .updateIssue(tcSrvId, nameId, branch, issueType, jiraTicket, comment);
     }
 
@@ -97,13 +97,13 @@ public class BoardRestService {
         @FormParam("nameId") int nameId,
         @FormParam("branch") String branch,
         @FormParam("issueType") String issueType) {
-        CtxListener.getInjector(ctx).getInstance(BoardService.class)
+        CtxListener.getApplicationContext(ctx).getInstance(BoardService.class)
             .unmuteIssue(tcSrvId, nameId, branch, issueType);
     }
 
     @GET
     @Path("mutedIssues")
     public Collection<MutedIssueUi> getMutedIssues(@QueryParam("baseBranch") String baseBranch) {
-        return CtxListener.getInjector(ctx).getInstance(BoardService.class).getAllMutedIssues(baseBranch);
+        return CtxListener.getApplicationContext(ctx).getInstance(BoardService.class).getAllMutedIssues(baseBranch);
     }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/board/DefectRestService.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/board/DefectRestService.java
index 1fbba74e..1c66c4e2 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/board/DefectRestService.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/board/DefectRestService.java
@@ -47,7 +47,7 @@ public class DefectRestService {
     public void resolveDefect(@FormParam("id") Integer defectId, @FormParam("forceResolve") Boolean forceResolve) {
         ITcBotUserCreds creds = ITcBotUserCreds.get(req);
 
-        CtxListener.getInjector(ctx)
+        CtxListener.getApplicationContext(ctx)
                 .getInstance(BoardService.class)
                 .resolveDefect(defectId, creds, forceResolve);
     }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/CompareBuilds.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/CompareBuilds.java
index f1cd42a0..2fd4bf8b 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/CompareBuilds.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/CompareBuilds.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.ci.web.rest.build;
 
-import com.google.inject.Injector;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -118,12 +118,12 @@ public class CompareBuilds {
 
     /** */
     private List<String> tests(String srvCode, Integer buildId) {
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
 
-        injector.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, prov);
+        appCtx.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, prov);
 
-        return injector.getInstance(CompareBuildsService.class).tests0(srvCode, buildId, prov);
+        return appCtx.getInstance(CompareBuildsService.class).tests0(srvCode, buildId, prov);
     }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/GetSingleBuildTestFailuresRest.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/GetSingleBuildTestFailuresRest.java
index 6dcb9ff3..b8487e66 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/GetSingleBuildTestFailuresRest.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/GetSingleBuildTestFailuresRest.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.ci.web.rest.build;
 
 import com.google.common.collect.BiMap;
-import com.google.inject.Injector;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
 import java.text.ParseException;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -68,23 +68,13 @@ public class GetSingleBuildTestFailuresRest {
         @Nullable @QueryParam("checkAllLogs") Boolean checkAllLogs) throws ServiceUnauthorizedException {
         UpdateInfo res = new UpdateInfo();
 
-        res.initCounters(CtxListener.getInjector(ctx)
+        res.initCounters(CtxListener.getApplicationContext(ctx)
             .getInstance(SingleBuildResultsService.class)
             .getBranchCntrs(srvCodeOrAlias, buildId, ITcBotUserCreds.get(req)));
 
         return res;
     }
 
-    @GET
-    @Path("failures/txt")
-    @Produces(MediaType.TEXT_PLAIN)
-    public String getTestFailsText(
-        @QueryParam("serverId") String srvCodeOrAlias,
-        @QueryParam("buildId") Integer buildId,
-        @Nullable @QueryParam("checkAllLogs") Boolean checkAllLogs) throws ServiceUnauthorizedException {
-        return getBuildTestFails(srvCodeOrAlias, buildId, checkAllLogs).toString();
-    }
-
     @GET
     @Path("failures/aiPrompt")
     @Produces(MediaType.TEXT_PLAIN)
@@ -92,7 +82,7 @@ public class GetSingleBuildTestFailuresRest {
         @QueryParam("serverId") String srvCodeOrAlias,
         @QueryParam("buildId") Integer buildId,
         @Nullable @QueryParam("maxDetailsChars") Integer maxDetailsChars) throws ServiceUnauthorizedException {
-        return CtxListener.getInjector(ctx)
+        return CtxListener.getApplicationContext(ctx)
             .getInstance(SingleBuildResultsService.class)
             .getSingleBuildFailuresAiPrompt(srvCodeOrAlias, buildId, maxDetailsChars, SyncMode.RELOAD_QUEUED,
                 ITcBotUserCreds.get(req));
@@ -120,7 +110,7 @@ public class GetSingleBuildTestFailuresRest {
         Integer buildId,
         @Nullable Boolean checkAllLogs,
         SyncMode syncMode) {
-        return CtxListener.getInjector(ctx)
+        return CtxListener.getApplicationContext(ctx)
             .getInstance(SingleBuildResultsService.class)
             .getSingleBuildResults(srvCodeOrAlias, buildId, checkAllLogs, syncMode,
                 ITcBotUserCreds.get(req));
@@ -142,16 +132,16 @@ public class GetSingleBuildTestFailuresRest {
         @QueryParam("isValid") Boolean isValid,
         @QueryParam("field") String field,
         @QueryParam("serverId") String srvIdOpt) {
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
         String srvCode = isNullOrEmpty(srvIdOpt)
-            ? injector.getInstance(ITcBotConfig.class).primaryServerCode()
+            ? appCtx.getInstance(ITcBotConfig.class).primaryServerCode()
             : srvIdOpt;
 
         if (buildId == null || isValid == null)
             return null;
 
-        ITeamcityIgnitedProvider tcIgnitedProv = injector.getInstance(ITeamcityIgnitedProvider.class);
+        ITeamcityIgnitedProvider tcIgnitedProv = appCtx.getInstance(ITeamcityIgnitedProvider.class);
 
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
 
@@ -185,8 +175,8 @@ public class GetSingleBuildTestFailuresRest {
         @Nullable @QueryParam("untilDate") String untilDate,
         @Nullable @QueryParam("skipTests") String skipTests)  throws ParseException {
 
-        Injector injector = CtxListener.getInjector(ctx);
-        MasterTrendsService instance = injector.getInstance(MasterTrendsService.class);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
+        MasterTrendsService instance = appCtx.getInstance(MasterTrendsService.class);
 
 
         BuildsHistory buildsHist =
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/buildtime/BuildTimeRestService.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/buildtime/BuildTimeRestService.java
index 43c39def..4e27b497 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/buildtime/BuildTimeRestService.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/buildtime/BuildTimeRestService.java
@@ -50,7 +50,7 @@ public class BuildTimeRestService {
     public BuildTimeResultUi loadAnalytics(@Nullable @QueryParam("branch") String branchOrNull) {
         final ITcBotUserCreds creds = ITcBotUserCreds.get(req);
 
-        final BuildTimeService tbProc = CtxListener.getInjector(ctx).getInstance(BuildTimeService.class);
+        final BuildTimeService tbProc = CtxListener.getApplicationContext(ctx).getInstance(BuildTimeService.class);
 
         return tbProc.analytics(creds);
     }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/issues/TcIssues.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/issues/TcIssues.java
index 4ed7b791..d9dd5b25 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/issues/TcIssues.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/issues/TcIssues.java
@@ -17,10 +17,9 @@
 
 package org.apache.ignite.ci.web.rest.issues;
 
-import com.google.inject.Injector;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
 import java.util.stream.Collectors;
 import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
@@ -30,7 +29,6 @@ import javax.ws.rs.core.MediaType;
 import org.apache.ignite.tcbot.engine.ui.IssueListUi;
 import org.apache.ignite.tcbot.engine.issue.IIssuesStorage;
 import org.apache.ignite.ci.web.CtxListener;
-import org.apache.ignite.ci.web.model.SimpleResult;
 import org.apache.ignite.tcbot.engine.ui.UpdateInfo;
 import org.jetbrains.annotations.Nullable;
 
@@ -44,9 +42,6 @@ public class TcIssues {
     @Context
     private ServletContext ctx;
 
-    @Context
-    private HttpServletRequest req;
-
     @GET
     @Path("updates")
     public UpdateInfo getAllTestFailsUpdates(@Nullable @QueryParam("branch") String branchOrNull,
@@ -61,11 +56,11 @@ public class TcIssues {
     public IssueListUi listIssues(@Nullable @QueryParam("branch") String branchOpt,
                                 @Nullable @QueryParam("count") Integer count,
                                 @Nullable @QueryParam("checkAllLogs") Boolean checkAllLogs) {
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
         final String branch = isNullOrEmpty(branchOpt) ? "master" : branchOpt;
 
-        IIssuesStorage issues = injector.getInstance(IIssuesStorage.class);
+        IIssuesStorage issues = appCtx.getInstance(IIssuesStorage.class);
 
         IssueListUi issueList = new IssueListUi(issues.allIssues().collect(Collectors.toList()));
 
@@ -74,10 +69,4 @@ public class TcIssues {
         return issueList;
     }
 
-    @GET
-    @Path("clear")
-    public SimpleResult clear(@Nullable @QueryParam("branch") String branchOpt) {
-        return new SimpleResult("Ok");
-    }
-
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/login/Login.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/login/Login.java
index 8a238278..52dfd742 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/login/Login.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/login/Login.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.ci.web.rest.login;
 
 import com.google.common.base.Preconditions;
-import com.google.inject.Injector;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
 import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
 import org.apache.ignite.tcbot.engine.user.IUserStorage;
 import org.apache.ignite.tcservice.model.user.User;
@@ -55,11 +55,11 @@ public class Login {
     @Path("primaryServerData")
     @PermitAll
     public ServerDataResponse primaryServerUrl() {
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
-        ITcBotConfig tcBotCfg = injector.getInstance(ITcBotConfig.class);
+        ITcBotConfig tcBotCfg = appCtx.getInstance(ITcBotConfig.class);
         String srvId = tcBotCfg.primaryServerCode();
-        String host = injector.getInstance(ITeamcityIgnitedProvider.class).server(srvId, null).host();
+        String host = appCtx.getInstance(ITeamcityIgnitedProvider.class).server(srvId, null).host();
         return new ServerDataResponse(host);
     }
 
@@ -71,10 +71,10 @@ public class Login {
         Preconditions.checkNotNull(username);
         Preconditions.checkNotNull(pwd);
 
-        final Injector injector = CtxListener.getInjector(ctx);
-        ITcBotConfig cfg = injector.getInstance(ITcBotConfig.class);
-        final ITcLogin tcLogin = injector.getInstance(ITcLogin.class);
-        IUserStorage users = injector.getInstance(IUserStorage.class);
+        final TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
+        ITcBotConfig cfg = appCtx.getInstance(ITcBotConfig.class);
+        final ITcLogin tcLogin = appCtx.getInstance(ITcLogin.class);
+        IUserStorage users = appCtx.getInstance(IUserStorage.class);
 
         String primarySrvCode = cfg.primaryServerCode();
 
@@ -123,8 +123,6 @@ public class Login {
 
                 return loginRes;
             }
-
-            //todo new registration should be checked on server first
             user.userKeyKcv = userKeyCandidateKcv;
 
             user.email = tcUser.email;
@@ -151,8 +149,6 @@ public class Login {
             if (!Arrays.equals(userKeyCandidateKcv, user.userKeyKcv))
                 return loginRes; //password validation failed
         }
-
-        //todo may be enrich user data here as well.
         userSes.userKeyUnderToken = CryptUtil.aesEncrypt(tokBytes, userKeyCandidate);
 
         users.putSession(sessId, userSes);
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/login/UserService.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/login/UserService.java
index b6864149..03f876e9 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/login/UserService.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/login/UserService.java
@@ -19,7 +19,7 @@ package org.apache.ignite.ci.web.rest.login;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
-import com.google.inject.Injector;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.FormParam;
@@ -71,11 +71,11 @@ public class UserService {
         if (prov == null)
             return new SimpleResult("");
 
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
         return userMenu(prov,
-            injector.getInstance(IUserStorage.class),
-            injector.getInstance(IssueDetector.class));
+            appCtx.getInstance(IUserStorage.class),
+            appCtx.getInstance(IssueDetector.class));
     }
 
     @NotNull public SimpleResult userMenu(ITcBotUserCreds prov, IUserStorage users, IssueDetector issueDetector) {
@@ -96,21 +96,21 @@ public class UserService {
     public SimpleResult setAuthorizedState() {
         final ITcBotUserCreds prov = ITcBotUserCreds.get(req);
 
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
-        IssueDetector issueDetector = injector.getInstance(IssueDetector.class);
-        final ITcBotBgAuth helper = injector.getInstance(ITcBotBgAuth.class);
+        IssueDetector issueDetector = appCtx.getInstance(IssueDetector.class);
+        final ITcBotBgAuth helper = appCtx.getInstance(ITcBotBgAuth.class);
         helper.setServerAuthorizerCreds(prov);
 
         issueDetector.startBackgroundCheck(prov);
 
-        CtxListener.getInjector(ctx).getInstance(TcBotTriggerAndSignOffService.class).startObserver();
+        CtxListener.getApplicationContext(ctx).getInstance(TcBotTriggerAndSignOffService.class).startObserver();
 
-        Cleaner cleaner = injector.getInstance(Cleaner.class);
+        Cleaner cleaner = appCtx.getInstance(Cleaner.class);
         cleaner.startBackgroundClean();
 
         return userMenu(prov,
-            injector.getInstance(IUserStorage.class),
+            appCtx.getInstance(IUserStorage.class),
             issueDetector);
     }
 
@@ -119,13 +119,11 @@ public class UserService {
     public TcHelperUserUi getUserData(@Nullable @QueryParam("login") final String loginParm) {
         final String currUserLogin = ITcBotUserCreds.get(req).getPrincipalId();
         final String login = Strings.isNullOrEmpty(loginParm) ? currUserLogin : loginParm;
-        Injector injector = CtxListener.getInjector(ctx);
-        ITcBotConfig cfg = injector.getInstance(ITcBotConfig.class);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
+        ITcBotConfig cfg = appCtx.getInstance(ITcBotConfig.class);
 
-        IUserStorage users = injector.getInstance(IUserStorage.class);
+        IUserStorage users = appCtx.getInstance(IUserStorage.class);
         final TcHelperUser user = users.getUser(login);
-
-        //todo can filter accessibliity
         final TcHelperUserUi tcHelperUserUi = new TcHelperUserUi(user,
                 cfg.getTrackedBranches().branchesStream()
                         .map(ITrackedBranch::name)
@@ -143,8 +141,6 @@ public class UserService {
 
             tcHelperUserUi.data.add(credsUi);
         }
-
-        //todo if user is not current disable addBuild creds
         return tcHelperUserUi;
     }
 
@@ -154,9 +150,8 @@ public class UserService {
     public SimpleResult resetCredentials(@Nullable @FormParam("login") final String loginParm) {
         final String currUserLogin = ITcBotUserCreds.get(req).getPrincipalId();
         final String login = Strings.isNullOrEmpty(loginParm) ? currUserLogin : loginParm;
-        //todo check admin
 
-        final IUserStorage users = CtxListener.getInjector(ctx).getInstance(IUserStorage.class);
+        final IUserStorage users = CtxListener.getApplicationContext(ctx).getInstance(IUserStorage.class);
         final TcHelperUser user = users.getUser(login);
 
         user.resetCredentials();
@@ -177,13 +172,11 @@ public class UserService {
 
         final ITcBotUserCreds prov = ITcBotUserCreds.get(req);
         final String currUserLogin = prov.getPrincipalId();
-        final Injector injector = CtxListener.getInjector(ctx);
-        final ITcLogin tcLogin = injector.getInstance(ITcLogin.class);
+        final TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
+        final ITcLogin tcLogin = appCtx.getInstance(ITcLogin.class);
 
-        final IUserStorage users = injector.getInstance(IUserStorage.class);
+        final IUserStorage users = appCtx.getInstance(IUserStorage.class);
         final TcHelperUser user = users.getUser(currUserLogin);
-
-        //todo check service credentials first
         final User tcAddUser = tcLogin.checkServiceUserAndPassword(svcId, svcLogin, svcPwd);
 
         if (tcAddUser == null)
@@ -209,9 +202,9 @@ public class UserService {
         @Nullable @FormParam("fullName") final String fullName,
         Form form) {
 
-        final String login = ITcBotUserCreds.get(req).getPrincipalId(); //todo check admin Strings.isNullOrEmpty(loginParm) ? currUserLogin : loginParm;
+        final String login = ITcBotUserCreds.get(req).getPrincipalId();
 
-        final IUserStorage users = CtxListener.getInjector(ctx).getInstance(IUserStorage.class);
+        final IUserStorage users = CtxListener.getApplicationContext(ctx).getInstance(IUserStorage.class);
         final TcHelperUser user = users.getUser(login);
 
         user.resetNotifications();
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/long_running/BuildsLongRunningTestsReport.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/long_running/BuildsLongRunningTestsReport.java
index 2eac7766..8e1d951a 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/long_running/BuildsLongRunningTestsReport.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/long_running/BuildsLongRunningTestsReport.java
@@ -49,7 +49,7 @@ public class BuildsLongRunningTestsReport {
     public LrTestsFullSummaryUi getBranch(@Nullable @QueryParam("branch") String branchOrNull) {
         final ITcBotUserCreds creds = ITcBotUserCreds.get(req);
 
-        final TrackedBranchChainsProcessor tbProc = CtxListener.getInjector(ctx).getInstance(TrackedBranchChainsProcessor.class);
+        final TrackedBranchChainsProcessor tbProc = CtxListener.getApplicationContext(ctx).getInstance(TrackedBranchChainsProcessor.class);
 
         return tbProc.getTrackedBranchLongRunningTestsSummary(branchOrNull, creds);
     }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/monitoring/MonitoringService.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/monitoring/MonitoringService.java
index f2b5706d..6dd213c2 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/monitoring/MonitoringService.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/monitoring/MonitoringService.java
@@ -35,8 +35,8 @@ import org.apache.ignite.cache.affinity.Affinity;
 import org.apache.ignite.ci.web.CtxListener;
 import org.apache.ignite.ci.web.model.SimpleResult;
 import org.apache.ignite.tcbot.common.conf.TcBotWorkDir;
-import org.apache.ignite.tcbot.common.interceptor.AutoProfilingInterceptor;
-import org.apache.ignite.tcbot.common.interceptor.MonitoredTaskInterceptor;
+import org.apache.ignite.tcbot.common.monitoring.MonitoredTasks;
+import org.apache.ignite.tcbot.common.monitoring.ProfilingMonitor;
 import org.apache.ignite.tcbot.engine.build.AiPromptRequestMonitor;
 import org.apache.ignite.tcbot.engine.conf.INotificationChannel;
 import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
@@ -104,9 +104,9 @@ public class MonitoringService {
     @PermitAll
     @Path("tasks")
     public List<TaskResult> getTaskMonitoring() {
-        MonitoredTaskInterceptor instance = CtxListener.getInjector(ctx).getInstance(MonitoredTaskInterceptor.class);
+        MonitoredTasks instance = instance(MonitoredTasks.class);
 
-        final Collection<MonitoredTaskInterceptor.Invocation> list = instance.getList();
+        final Collection<? extends MonitoredTasks.Invocation> list = instance.getList();
 
         return list.stream().map(invocation -> {
             final TaskResult res = new TaskResult();
@@ -124,7 +124,7 @@ public class MonitoringService {
     @GET
     @Path("appLogSummaryLink")
     public AppLogSummaryLink getAppLogSummaryLink() {
-        MonitoredTaskInterceptor instance = CtxListener.getInjector(ctx).getInstance(MonitoredTaskInterceptor.class);
+        MonitoredTasks instance = instance(MonitoredTasks.class);
 
         AppLogSummaryLink res = new AppLogSummaryLink();
         res.startTs = instance.startedTs();
@@ -375,9 +375,9 @@ public class MonitoringService {
     @PermitAll
     @Path("profiling")
     public List<HotSpot> getHotMethods() {
-        AutoProfilingInterceptor instance = CtxListener.getInjector(ctx).getInstance(AutoProfilingInterceptor.class);
+        ProfilingMonitor instance = instance(ProfilingMonitor.class);
 
-        Collection<AutoProfilingInterceptor.Invocation> profile = instance.getInvocations();
+        Collection<? extends ProfilingMonitor.Invocation> profile = instance.getInvocations();
 
         Stream<HotSpot> hotSpotStream = profile.stream().map(inv -> {
             HotSpot hotSpot = new HotSpot();
@@ -396,7 +396,7 @@ public class MonitoringService {
     @POST
     @Path("resetProfiling")
     public SimpleResult resetProfiling() {
-        AutoProfilingInterceptor instance = CtxListener.getInjector(ctx).getInstance(AutoProfilingInterceptor.class);
+        ProfilingMonitor instance = instance(ProfilingMonitor.class);
 
         instance.reset();
 
@@ -407,9 +407,8 @@ public class MonitoringService {
     @PermitAll
     @Path("testSlackNotification")
     public SimpleResult testSlackNotification() {
-        ISlackSender slackSender = CtxListener.getInjector(ctx).getInstance(ISlackSender.class);
-
-        ITcBotConfig tcBotConfig = CtxListener.getInjector(ctx).getInstance(ITcBotConfig.class);
+        ISlackSender slackSender = instance(ISlackSender.class);
+        ITcBotConfig tcBotConfig = instance(ITcBotConfig.class);
 
         try {
             NotificationsConfig notifications = tcBotConfig.notifications();
@@ -429,9 +428,8 @@ public class MonitoringService {
     @POST
     @Path("testEmailNotification")
     public SimpleResult testEmailNotification(@FormParam("address") String address) {
-        IEmailSender emailSender = CtxListener.getInjector(ctx).getInstance(IEmailSender.class);
-
-        ITcBotConfig tcBotConfig = CtxListener.getInjector(ctx).getInstance(ITcBotConfig.class);
+        IEmailSender emailSender = instance(IEmailSender.class);
+        ITcBotConfig tcBotConfig = instance(ITcBotConfig.class);
 
         try {
             NotificationsConfig notifications = tcBotConfig.notifications();
@@ -453,7 +451,7 @@ public class MonitoringService {
     @PermitAll
     @Path("cacheMetrics")
     public List<CacheMetricsUi> getCacheStat() {
-        Ignite ignite = CtxListener.getInjector(ctx).getInstance(Ignite.class);
+        Ignite ignite = instance(Ignite.class);
 
         final Collection<String> strings = ignite.cacheNames();
 
@@ -505,8 +503,12 @@ public class MonitoringService {
     @GET
     @Path("aiPrompts")
     public List<AiPromptRequestMonitor.Request> getAiPromptRequests() {
-        AiPromptRequestMonitor monitor = CtxListener.getInjector(ctx).getInstance(AiPromptRequestMonitor.class);
+        AiPromptRequestMonitor monitor = instance(AiPromptRequestMonitor.class);
 
         return monitor.getRequests();
     }
+
+    private <T> T instance(Class<T> type) {
+        return CtxListener.getApplicationContext(ctx).getInstance(type);
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/pr/GetPrTestFailures.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/pr/GetPrTestFailures.java
index c0347023..0d9c22a0 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/pr/GetPrTestFailures.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/pr/GetPrTestFailures.java
@@ -17,24 +17,18 @@
 
 package org.apache.ignite.ci.web.rest.pr;
 
-import com.google.inject.Injector;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
 import javax.annotation.Nonnull;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.FormParam;
 import javax.ws.rs.GET;
-import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
-import org.apache.ignite.ci.github.PullRequest;
 import org.apache.ignite.ci.user.ITcBotUserCreds;
 import org.apache.ignite.ci.web.CtxListener;
-import org.apache.ignite.githubignited.IGitHubConnIgnited;
-import org.apache.ignite.githubignited.IGitHubConnIgnitedProvider;
-import org.apache.ignite.githubservice.IGitHubConnection;
 import org.apache.ignite.tcbot.engine.build.TestFailuresAiPromptBuilder;
 import org.apache.ignite.tcbot.engine.pr.PrChainsProcessor;
 import org.apache.ignite.tcbot.engine.ui.DsSummaryUi;
@@ -63,7 +57,7 @@ public class GetPrTestFailures {
         @Nonnull @QueryParam("branchForTc") String branchForTc,
         @Nullable @QueryParam("baseBranchForTc") String baseBranchForTc) {
         return new UpdateInfo().initCounters(
-            CtxListener.getInjector(ctx).getInstance(PrChainsProcessor.class)
+            CtxListener.getApplicationContext(ctx).getInstance(PrChainsProcessor.class)
                 .getPrUpdateCounters(srvCodeOrAlias, branchForTc, baseBranchForTc, ITcBotUserCreds.get(req)));
     }
 
@@ -91,8 +85,8 @@ public class GetPrTestFailures {
         @QueryParam("checkAllLogs") @Nullable Boolean checkAllLogs,
         SyncMode mode) {
         final ITcBotUserCreds creds = ITcBotUserCreds.get(req);
-        final Injector injector = CtxListener.getInjector(ctx);
-        final PrChainsProcessor prChainsProcessor = injector.getInstance(PrChainsProcessor.class);
+        final TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
+        final PrChainsProcessor prChainsProcessor = appCtx.getInstance(PrChainsProcessor.class);
 
         return prChainsProcessor.getTestFailuresSummary(creds, srvId, suiteId, branchForTc, act, cnt, baseBranchForTc,
             checkAllLogs,
@@ -145,9 +139,9 @@ public class GetPrTestFailures {
         @Nullable @QueryParam("maxDetailsChars") Integer maxDetailsChars,
         @Nullable @QueryParam("testName") String testName,
         @Nullable @QueryParam("promptSuiteId") String promptSuiteId) {
-        final Injector injector = CtxListener.getInjector(ctx);
+        final TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
-        return injector.getInstance(PrChainsProcessor.class).getPrFailuresAiPrompt(
+        return appCtx.getInstance(PrChainsProcessor.class).getPrFailuresAiPrompt(
             ITcBotUserCreds.get(req),
             srvId,
             suiteId,
@@ -159,40 +153,4 @@ public class GetPrTestFailures {
             testName,
             promptSuiteId);
     }
-
-    @POST
-    @Path("notifyGit")
-    public String getNotifyGit(
-        @Nullable @QueryParam("serverId") String srvId,
-        @Nonnull @QueryParam("suiteId") String suiteId,
-        @Nonnull @QueryParam("branchForTc") String branchForTc,
-        @Nonnull @QueryParam("action") String act,
-        @Nullable @QueryParam("count") Integer cnt,
-        @Nonnull @FormParam("notifyMsg") String msg) {
-        if (!branchForTc.startsWith("pull/"))
-            return "Given branch is not a pull request. Notify works only for pull requests.";
-
-        final Injector injector = CtxListener.getInjector(ctx);
-        final IGitHubConnIgnited srv = injector.getInstance(IGitHubConnIgnitedProvider.class).server(srvId);
-
-        PullRequest pr;
-
-        try {
-            Integer prId = IGitHubConnection.convertBranchToPrId(branchForTc);
-
-            if (prId == null)
-                return "Invalid TC branch name: [" + branchForTc + "]";
-
-            pr = srv.getPullRequest(prId);
-        }
-        catch (RuntimeException e) {
-            return "Exception happened - " + e.getMessage();
-        }
-
-        String statusesUrl = pr.getStatusesUrl();
-
-        srv.notifyGit(statusesUrl, msg);
-
-        return "Git was notified.";
-    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java
index d39f3740..b88d0cff 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.ci.web.rest.tracked;
 
-import com.google.inject.Injector;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -62,7 +62,6 @@ public class GetTrackedBranchTestResults {
     private static final Logger logger = LoggerFactory.getLogger(GetTrackedBranchTestResults.class);
 
     public static final String TRACKED = "tracked";
-    public static final int DEFAULT_COUNT = 10;
 
     /** Slow tracked branch request threshold. */
     private static final long SLOW_TRACKED_RESULTS_WARN_MS =
@@ -81,31 +80,13 @@ public class GetTrackedBranchTestResults {
     public UpdateInfo getTestFailsUpdates(@Nullable @QueryParam("branch") String branchOrNull) {
         UpdateInfo info = new UpdateInfo();
 
-        Map<Integer, Integer> counters = CtxListener.getInjector(ctx).getInstance(IDetailedStatusForTrackedBranch.class)
+        Map<Integer, Integer> counters = CtxListener.getApplicationContext(ctx).getInstance(IDetailedStatusForTrackedBranch.class)
             .getTrackedBranchUpdateCounters(branchOrNull, ITcBotUserCreds.get(req));
         info.initCounters(counters);
 
         return info;
     }
 
-    @GET
-    @Path("results/txt")
-    @Produces(MediaType.TEXT_PLAIN)
-    public String getTestFailsText(@Nullable @QueryParam("branch") String branchOrNull,
-        @Nullable @QueryParam("checkAllLogs") Boolean checkAllLogs,
-        @Nullable @QueryParam("trustedTests") Boolean trustedTests,
-        @Nullable @QueryParam("tagSelected") String tagSelected,
-        @Nullable @QueryParam("tagForHistSelected") String tagForHistSelected,
-        @Nullable @QueryParam("displayMode") String displayMode,
-        @Nullable @QueryParam("sortOption") String sortOption,
-        @Nullable @QueryParam("count") Integer mergeCnt,
-        @Nullable @QueryParam("showTestLongerThan") Integer showTestLongerThan,
-        @Nullable @QueryParam("muted") Boolean showMuted,
-        @Nullable @QueryParam("ignored") Boolean showIgnored) {
-        return getTestFailsResultsNoSync(branchOrNull, checkAllLogs, trustedTests, tagSelected, tagForHistSelected,
-            displayMode, sortOption, mergeCnt, showTestLongerThan, showMuted, showIgnored).toString();
-    }
-
     @GET
     @Path("results/aiPrompt")
     @Produces(MediaType.TEXT_PLAIN)
@@ -118,7 +99,7 @@ public class GetTrackedBranchTestResults {
         @Nullable @QueryParam("promptSuiteId") String promptSuiteId) {
         int actualMergeBuilds = (mergeCnt == null || mergeCnt < 1) ? 1 : mergeCnt;
 
-        return CtxListener.getInjector(ctx)
+        return CtxListener.getApplicationContext(ctx)
             .getInstance(TrackedBranchChainsProcessor.class)
             .getTrackedBranchFailuresAiPrompt(branchOrNull,
                 actualMergeBuilds,
@@ -185,13 +166,13 @@ public class GetTrackedBranchTestResults {
 
         ITcBotUserCreds creds = ITcBotUserCreds.get(req);
 
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
         int actualMergeBuilds = (mergeCnt == null || mergeCnt < 1) ? 1 : mergeCnt;
 
         int maxDurationSec = (showTestLongerThan == null || showTestLongerThan < 1) ? 0 : showTestLongerThan;
 
-        DsSummaryUi res = injector.getInstance(IDetailedStatusForTrackedBranch.class)
+        DsSummaryUi res = appCtx.getInstance(IDetailedStatusForTrackedBranch.class)
             .getTrackedBranchTestFailures(branch,
                 checkAllLogs,
                 actualMergeBuilds,
@@ -211,53 +192,6 @@ public class GetTrackedBranchTestResults {
         return res;
     }
 
-    @GET
-    @Path("mergedUpdates")
-    public UpdateInfo getAllTestFailsUpdates(@Nullable @QueryParam("branch") String branchOrNull) {
-        return new UpdateInfo().initCounters(
-            CtxListener.getInjector(ctx)
-                .getInstance(IDetailedStatusForTrackedBranch.class)
-                .getTrackedBranchUpdateCounters(branchOrNull, ITcBotUserCreds.get(req)));
-    }
-
-    @GET
-    @Path("mergedResultsNoSync")
-    public DsSummaryUi getAllTestFailsNoSync(@Nullable @QueryParam("branch") String branch,
-                                             @Nullable @QueryParam("count") Integer cnt,
-                                             @Nullable @QueryParam("checkAllLogs") Boolean checkAllLogs) {
-        return mergedBuildsResults(branch, cnt, checkAllLogs, SyncMode.NONE);
-    }
-
-    @GET
-    @Path("mergedResults")
-    @NotNull
-    public DsSummaryUi getAllTestFailsForMergedBuidls(@Nullable @QueryParam("branch") String branchOpt,
-                                                      @QueryParam("count") Integer cnt,
-                                                      @Nullable @QueryParam("checkAllLogs") Boolean checkAllLogs) {
-        return mergedBuildsResults(branchOpt, cnt, checkAllLogs, SyncMode.RELOAD_QUEUED);
-    }
-
-    @NotNull private DsSummaryUi mergedBuildsResults(
-        @QueryParam("branch") @Nullable String branchOpt,
-        @QueryParam("count") Integer cnt,
-        @QueryParam("checkAllLogs") @Nullable Boolean checkAllLogs,
-        SyncMode mode) {
-        long startNanos = System.nanoTime();
-
-        ITcBotUserCreds creds = ITcBotUserCreds.get(req);
-        int cntLimit = cnt == null ? DEFAULT_COUNT : cnt;
-        Injector injector = CtxListener.getInjector(ctx);
-
-        DsSummaryUi res = injector.getInstance(TrackedBranchChainsProcessor.class)
-            .getTrackedBranchTestFailures(branchOpt, checkAllLogs, cntLimit, creds, mode,
-                false, null, null, DisplayMode.OnlyFailures, null,
-                -1, false, false);
-
-        logSlowTrackedResult(startNanos, "merged", branchOpt, cntLimit, mode, res);
-
-        return res;
-    }
-
     /**
      * Logs slow tracked branch request.
      */
@@ -284,8 +218,8 @@ public class GetTrackedBranchTestResults {
     ) {
         ITcBotUserCreds creds = ITcBotUserCreds.get(req);
 
-        Injector injector = CtxListener.getInjector(ctx);
-        ITcBotConfig cfg = injector.getInstance(ITcBotConfig.class);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
+        ITcBotConfig cfg = appCtx.getInstance(ITcBotConfig.class);
 
         if (F.isEmpty(srvCode))
             srvCode = cfg.primaryServerCode();
@@ -293,9 +227,9 @@ public class GetTrackedBranchTestResults {
         if (F.isEmpty(projectId))
             projectId = DEFAULT_PROJECT_ID;
 
-        injector.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, creds);
+        appCtx.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, creds);
 
-        return injector
+        return appCtx
             .getInstance(TcBotTriggerAndSignOffService.class)
             .getMutes(srvCode, projectId, creds);
     }
@@ -304,9 +238,9 @@ public class GetTrackedBranchTestResults {
     @Path("summary")
     public List<GuardBranchStatusUi> getIdsIfAccessible() {
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
-        Injector injector = CtxListener.getInjector(ctx);
-        ITcBotConfig cfg = injector.getInstance(ITcBotConfig.class);
-        IDetailedStatusForTrackedBranch status = injector.getInstance(IDetailedStatusForTrackedBranch.class);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
+        ITcBotConfig cfg = appCtx.getInstance(ITcBotConfig.class);
+        IDetailedStatusForTrackedBranch status = appCtx.getInstance(IDetailedStatusForTrackedBranch.class);
 
         return cfg.getTrackedBranches().branchesStream()
             .map(bt -> status.getBranchSummary(bt.name(), prov)).filter(Objects::nonNull)
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java
index de24b9b6..33286b90 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java
@@ -16,7 +16,7 @@
  */
 package org.apache.ignite.ci.web.rest.visa;
 
-import com.google.inject.Injector;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
@@ -58,7 +58,7 @@ public class TcBotVisaService {
     @Path("cancel")
     public boolean stopObservation(@NotNull @QueryParam("server") String srv,
         @NotNull @QueryParam("branch") String branchForTc) {
-            return CtxListener.getInjector(ctx)
+            return CtxListener.getApplicationContext(ctx)
                 .getInstance(BuildObserver.class)
                 .stopObservation(new ContributionKey(srv, branchForTc));
     }
@@ -68,7 +68,7 @@ public class TcBotVisaService {
     @GET
     @Path("history")
     public Collection<VisaStatus> history() {
-        return CtxListener.getInjector(ctx)
+        return CtxListener.getApplicationContext(ctx)
             .getInstance(TcBotTriggerAndSignOffService.class)
             .getVisasStatus(ITcBotUserCreds.get(req));
     }
@@ -82,11 +82,11 @@ public class TcBotVisaService {
     public List<ContributionToCheck> contributions(@Nullable @QueryParam("serverId") String srvCode) {
         ITcBotUserCreds credsProv = ITcBotUserCreds.get(req);
 
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
-        injector.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, credsProv);
+        appCtx.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, credsProv);
 
-        return injector.getInstance(TcBotTriggerAndSignOffService.class).getContributionsToCheck(srvCode, credsProv);
+        return appCtx.getInstance(TcBotTriggerAndSignOffService.class).getContributionsToCheck(srvCode, credsProv);
     }
 
     @GET
@@ -95,11 +95,11 @@ public class TcBotVisaService {
         @QueryParam("prId") String prId) {
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
 
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
-        injector.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, prov);
+        appCtx.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, prov);
 
-        return injector.getInstance(TcBotTriggerAndSignOffService.class).contributionStatuses(srvCode, prov, prId);
+        return appCtx.getInstance(TcBotTriggerAndSignOffService.class).contributionStatuses(srvCode, prov, prId);
     }
 
     @GET
@@ -107,13 +107,13 @@ public class TcBotVisaService {
     public CurrentVisaStatus currentVisaStatus(@Nullable @QueryParam("serverId") String srvCode,
         @Nonnull @QueryParam("suiteId") String suiteId,
         @QueryParam("tcBranch") String tcBranch) {
-        Injector injector = CtxListener.getInjector(ctx);
+        TcBotApplicationContext appCtx = CtxListener.getApplicationContext(ctx);
 
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
 
-        injector.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, prov);
+        appCtx.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, prov);
 
-        return injector.getInstance(TcBotTriggerAndSignOffService.class)
+        return appCtx.getInstance(TcBotTriggerAndSignOffService.class)
             .currentVisaStatus(srvCode, prov, suiteId, tcBranch);
     }
 }
diff --git a/ignite-tc-helper-web/src/main/webapp/all.html b/ignite-tc-helper-web/src/main/webapp/all.html
deleted file mode 100644
index ed928655..00000000
--- a/ignite-tc-helper-web/src/main/webapp/all.html
+++ /dev/null
@@ -1,186 +0,0 @@
-<html>
-<head>
-    <title>Ignite Teamcity - current failures</title>
-    <link rel="icon" href="img/leaf.svg">
-    <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
-    <link rel="stylesheet" href="css/style-1.5.css">
-    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.2/css/all.css"
-          integrity="sha384-/rXc/GQVaYpyDdyxK+ecHPVYJSN9bmVFBvjA/9eOB+pb3F2w2N6fc5qB9Ew5yIns" crossorigin="anonymous">
-
-
-    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
-    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
-    <script src="js/common-1.7.js"></script>
-    <script src="js/testfails-2.3.js"></script>
-</head>
-<body>
-<script>
-    var g_shownDataHashCodeHex = "";
-
-    $(document).ready(function () {
-        $.getScript("js/testfails-2.3.js", function (data, textStatus, jqxhr) {
-        });
-
-        $(document).tooltip();
-
-        loadData();
-
-        $.ajax({url: "rest/branches/version", success: showVersionInfo, error: showErrInLoadStatus});
-
-        $( "#tagSelect" ).change(function() {
-            var selectedTag = $( "#tagSelect option:selected" ).val()
-
-            $( ".suiteBlock" ).each(function() {
-                if(selectedTag == 'all' || $(this).find(".buildTag:contains('" + selectedTag +"')").length > 0)
-                    $(this).show();
-                else
-                    $(this).hide();
-            })
-        });
-    });
-
-
-    function parmsForRest() {
-        var curReqParms = "";
-
-        var branch = findGetParameter("branch");
-        if (branch != null)
-            curReqParms += "?branch=" + branch;
-
-        var count = findGetParameter("count");
-        if (count != null)
-            curReqParms += "&count=" + count;
-
-        var checkAllLogs = findGetParameter("checkAllLogs");
-        if (checkAllLogs != null)
-            curReqParms += "&checkAllLogs=" + checkAllLogs;
-
-        return curReqParms;
-    }
-
-
-    function checkForUpdate() {
-        var curFailuresUrl = "rest/tracked/mergedUpdates" + parmsForRest();
-
-        $.ajax({
-            url: curFailuresUrl,
-            success: function (result) {
-                if (g_shownDataHashCodeHex !== "" && isDefinedAndFilled(result.hashCodeHex)) {
-                    if (g_shownDataHashCodeHex === result.hashCodeHex) {
-                        setTimeout(checkForUpdate, 10000);
-
-                        $("#loadStatus").html("");
-                    } else {
-                        loadData(); // data changed, show new
-                    }
-                } else {
-                    loadData();
-                }
-            },
-            error: showErrInLoadStatus
-        });
-    }
-
-    function loadData() {
-        var curFailuresUrl = "rest/tracked/mergedResults" + parmsForRest();
-
-        $("#loadStatus").html("&#8987; Please wait. Loading merged runs may require significant time.");
-        setTimeout(loadPartialData, 3000);
-        $.ajax({
-            url: curFailuresUrl,
-            success: function (result) {
-                showData(result);
-
-                g_shownDataHashCodeHex = isDefinedAndFilled(result.hashCodeHex) ? result.hashCodeHex : "";
-            },
-            error: showErrInLoadStatus
-        });
-    }
-
-
-    function loadPartialData() {
-        var curFailuresUrl = "rest/tracked/mergedResultsNoSync" + parmsForRest();
-
-        if (g_shownDataHashCodeHex !== "") {
-            return;
-        }
-        $.ajax({
-            url: curFailuresUrl,
-            success: function (result) {
-                if (g_shownDataHashCodeHex !== "") {
-                    return;
-                }
-
-                var validResult = true;
-                for (var i = 0; i < result.servers.length; i++) {
-                    var server = result.servers[i];
-
-                    if (isDefinedAndFilled(server.buildNotFound) && server.buildNotFound) {
-                        validResult = false;
-                        break;
-                    }
-                }
-                if (validResult)
-                    showData(result);
-
-                setTimeout(loadPartialData, 3000);
-            },
-            error: showErrInLoadStatus
-        });
-    }
-
-
-    function showData(result) {
-        var repMode = "./all.html" + parmsForRest() + "&reportMode=" + true;
-
-        $("#divFailures").html(showChainOnServersResults(result)
-            + " <a href='" + repMode + "'>report mode</a>");
-
-        refillTagSelect();
-    }
-
-    function refillTagSelect() {
-        var newTagList = new Set();
-
-        $("div#divFailures table tr td span.buildTag").each(function(){
-            newTagList.add(this.innerText);
-        })
-
-        var tagSelect = $("#tagSelect");
-
-        tagSelect.empty();
-
-        tagSelect.append(
-            $("<option></option>")
-                .attr("value", "all")
-                .text("All")
-        );
-
-        newTagList.forEach(function(key) {
-          tagSelect.append(
-            $("<option></option>")
-                .attr("value", key)
-                .text(key)
-          );
-        });
-    }
-
-</script>
-
-
-<script>
-   window.location='current.html' + parmsForRest() + "&count=10";
-</script>
-
-<a href="current.html?count=10">This repors functionality was moved here</a>
-
-
-<div id="loadStatus"></div>
-<div><a href=".">Home</a> <select id="tagSelect" style="float:right"></select></div>
-<br/>
-<div id="divFailures"></div>
-
-<div id="version"></div>
-<div style="visibility:hidden;"><div id="triggerConfirm" title="Trigger Confirmation"></div><div id="triggerDialog" title="Trigger Result"></div></div>
-</body>
-</html>
\ No newline at end of file
diff --git a/ignite-tc-helper-web/src/main/webapp/build.html b/ignite-tc-helper-web/src/main/webapp/build.html
index 799e41c7..235327b7 100644
--- a/ignite-tc-helper-web/src/main/webapp/build.html
+++ b/ignite-tc-helper-web/src/main/webapp/build.html
@@ -127,12 +127,10 @@ function loadPartialData() {
 }
 
 function showData(result) {
-    var txtUrl = "rest/build/failures/txt" + parmsForRest();
     var aiPromptUrl = "rest/build/failures/aiPrompt" + parmsForRest();
 
     $("#divFailures").html(showChainOnServersResults(result)
         + " <a href='"+ aiPromptUrl + "' title='Download AI prompt with TeamCity failure context'>AI prompt</a>"
-        // + " <a href='"+ txtUrl + "'>txt</a>"
     );
 }
 
diff --git a/ignite-tc-helper-web/src/main/webapp/chart.html b/ignite-tc-helper-web/src/main/webapp/chart.html
deleted file mode 100644
index e2ad90aa..00000000
--- a/ignite-tc-helper-web/src/main/webapp/chart.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<script>
-    window.location='comparison.html';
-</script>
-
-<a href="trends.html">Page moved here</a>
\ No newline at end of file
diff --git a/ignite-tc-helper-web/src/main/webapp/comparison.html b/ignite-tc-helper-web/src/main/webapp/comparison.html
deleted file mode 100644
index 6f7554de..00000000
--- a/ignite-tc-helper-web/src/main/webapp/comparison.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<script>
-    window.location='trends.html';
-</script>
-
-<a href="trends.html">Page moved here</a>
\ No newline at end of file
diff --git a/ignite-tc-helper-web/src/main/webapp/current.html b/ignite-tc-helper-web/src/main/webapp/current.html
index 1df2fd60..48e71eb9 100644
--- a/ignite-tc-helper-web/src/main/webapp/current.html
+++ b/ignite-tc-helper-web/src/main/webapp/current.html
@@ -333,8 +333,6 @@ function showData(result) {
     gVue.$data.tagsPresent = Array.from(setOfTags);
     gVue.$data.tagsForHistPresent = Array.from(setOfHistTags);
 
-    //var txtUrl = "rest/tracked/results/txt" + parmsForRest();
-
     var minFailRate = gVue.$data.failRateRange[0];
 
     var maxFailRate = gVue.$data.failRateRange[1];
@@ -344,7 +342,6 @@ function showData(result) {
     let resHtml = showChainResultsWithSettings(result, new Settings(minFailRate, maxFailRate, result.javaFlags, hideFlakyFailures));
 
     $("#divFailures").html(resHtml);
-    //        + " <a href='"+ txtUrl + "'>txt</a>");
 }
 
 function aiPromptUrlForTest(testName) {
diff --git a/ignite-tc-helper-web/src/main/webapp/img/browser.png b/ignite-tc-helper-web/src/main/webapp/img/browser.png
deleted file mode 100644
index c57f7eb1..00000000
Binary files a/ignite-tc-helper-web/src/main/webapp/img/browser.png and /dev/null differ
diff --git a/ignite-tc-helper-web/src/main/webapp/index0.html b/ignite-tc-helper-web/src/main/webapp/index0.html
index 0b8232ac..d8835512 100644
--- a/ignite-tc-helper-web/src/main/webapp/index0.html
+++ b/ignite-tc-helper-web/src/main/webapp/index0.html
@@ -66,7 +66,7 @@ function showCurrentBranchesData(result) {
         res += id + ":";
         res += "<a href='current.html?branch=" + id + "'><button>Latest (" + id + ")</button></a>";
         res += " &nbsp;&nbsp;<a href='current.html?branch=" + id + "&checkAllLogs=true' title='With logs processing'><button>Latest (" + id + " + logs)</button></a>";
-        res += " &nbsp;&nbsp;<a href='all.html?branch=" + id + "'><button title='Failures from last 10 runs merged'>History (" + id + ")</button></a>";
+        res += " &nbsp;&nbsp;<a href='current.html?branch=" + id + "&count=10'><button title='Failures from last 10 runs merged'>History (" + id + ")</button></a>";
         //  res += "</div>";
         res += "<br>";
     }
@@ -147,12 +147,6 @@ function showBuildsOnServers(result) {
 <br>
 
 Statistics: <br>
-<!--<a href="chart.html">Build metrics daily history</a><br>
-<a href="restpretty.html?url=top/failing">Top failing tests</a> (JSON) <br>
-<a href="restpretty.html?url=top/longRunning">Top long running tests</a> (JSON) <br>
-<a href="restpretty.html?url=top/failingSuite">Top failing suites</a> (JSON) <br>
-<a href="./status">Current Build Status (obsolete)</a><br>
-<br>-->
 <a href="trends.html">Comparison master's branch in the date interval</a><br>
 
 Other: <br>
diff --git a/ignite-tc-helper-web/src/main/webapp/js/testfails-2.3.js b/ignite-tc-helper-web/src/main/webapp/js/testfails-2.3.js
index d7882eea..98b03909 100644
--- a/ignite-tc-helper-web/src/main/webapp/js/testfails-2.3.js
+++ b/ignite-tc-helper-web/src/main/webapp/js/testfails-2.3.js
@@ -291,11 +291,6 @@ function showChainCurrentStatusData(chain, settings) {
 
     res += "</td><td>";
 
-    // if (settings.isGithubAvailable()) {
-    //     g_srv_to_notify_git = server;
-    //     res += "<button onclick='notifyGit()'>Update PR status</button>";
-    // }
-
     let baseBranchForTc = chain.baseBranchForTc;
     if (settings.isJiraAvailable() && isDefinedAndFilled(srvCodeForTriggering)) {
         res += "<button onclick='commentJira(\"" + srvCodeForTriggering + "\", " +
diff --git a/ignite-tc-helper-web/src/main/webapp/prs.html b/ignite-tc-helper-web/src/main/webapp/prs.html
index 2c76984d..1c9ba2e8 100644
--- a/ignite-tc-helper-web/src/main/webapp/prs.html
+++ b/ignite-tc-helper-web/src/main/webapp/prs.html
@@ -244,16 +244,6 @@
 
         <br>Check results of branch/PR TeamCity Run All:
         <div id="suitesForPrCheck"></div>
-
-        <!--Notify GitHub:   <br>
-        <div id="notifyGitHub">
-            <form>
-                Server: <input type='text' name='serverId' value="apache" readonly>
-                Branch: <input type='text' name='branchForTc' required>
-                <input type='submit' name='action' value='Notify'>
-            </form>
-        </div>
-        <br>-->
     </div>
 </div>
 
@@ -261,4 +251,4 @@
 
 <div style="visibility:hidden"><div id="triggerConfirm" title="Trigger Confirmation"></div><div id="triggerDialog" title="Trigger Result"></div></div>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/ignite-tc-helper-web/src/main/webapp/restpretty.html b/ignite-tc-helper-web/src/main/webapp/restpretty.html
deleted file mode 100644
index 404f6fb4..00000000
--- a/ignite-tc-helper-web/src/main/webapp/restpretty.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <title>Apache Ignite Teamcity Bot</title>
-    <link rel="icon" href="img/leaf.svg">
-
-    <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
-    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
-    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
-</head>
-<body>
-<pre id="ciResponseText"></pre>
-
-<div id="loadStatus"></div>
-<script>
-
-function findGetParameter(parameterName) {
-    var result = null,
-        tmp = [];
-    location.search
-        .substr(1)
-        .split("&")
-        .forEach(function (item) {
-          tmp = item.split("=");
-          if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
-        });
-    return result;
-}
-
-$(document).ready(function() {
-    $( document ).tooltip();
-    loadData();
-     //todo fix setInterval(loadData, 60000)
-});
-
-function loadData() {
-    $("#loadStatus").html("&#8987; Please wait");
-    $.ajax({
-        url: "rest/" + findGetParameter("url"),
-        success: function(result) {
-            $("#loadStatus").html("");
-            showData(result);
-        },
-        error: function(jqXHR, exception) {
-            if (jqXHR.status === 0) {
-                $("#loadStatus").html('Not connect.\n Verify Network.');
-            } else if (jqXHR.status === 404) {
-                $("#loadStatus").html('Requested page not found. [404]');
-            } else if (jqXHR.status === 500) {
-                $("#loadStatus").html('Internal Server Error [500].');
-            } else if (exception === 'parsererror') {
-                $("#loadStatus").html('Requested JSON parse failed.');
-            } else if (exception === 'timeout') {
-                $("#loadStatus").html('Time out error.');
-            } else if (exception === 'abort') {
-                $("#loadStatus").html('Ajax request aborted.');
-            } else {
-                $("#loadStatus").html('Uncaught Error.\n' + jqXHR.responseText);
-            }
-        }
-
-    }, );
-}
-
-function showData(result) {
-    var ciResponseText = document.getElementById('ciResponseText');
-    ciResponseText.innerHTML =  JSON.stringify(result, null, '\t');
-}
-</script>
-</body>
-</html>
\ No newline at end of file
diff --git a/ignite-tc-helper-web/src/main/webapp/services.html b/ignite-tc-helper-web/src/main/webapp/services.html
deleted file mode 100644
index c7d88e2f..00000000
--- a/ignite-tc-helper-web/src/main/webapp/services.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<script>
-    window.location='prs.html';
-</script>
-
-<a href="prs.html">Page moved here</a>
\ No newline at end of file
diff --git a/ignite-tc-helper-web/src/main/webapp/statistics.html b/ignite-tc-helper-web/src/main/webapp/statistics.html
deleted file mode 100644
index 6f7554de..00000000
--- a/ignite-tc-helper-web/src/main/webapp/statistics.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<script>
-    window.location='trends.html';
-</script>
-
-<a href="trends.html">Page moved here</a>
\ No newline at end of file
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/di/DiContextTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/di/DiContextTest.java
index 10e1bcd7..4d094a18 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/di/DiContextTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/di/DiContextTest.java
@@ -26,7 +26,7 @@ import org.apache.ignite.IgniteCache;
 import org.apache.ignite.ci.observer.BuildObserver;
 import org.apache.ignite.ci.observer.ObserverTask;
 import org.apache.ignite.ci.tcbot.ITcBotBgAuth;
-import org.apache.ignite.ci.tcbot.TcBotWebAppModule;
+import org.apache.ignite.tcbot.app.guice.TcBotWebAppModule;
 import org.apache.ignite.tcbot.common.interceptor.MonitoredTaskInterceptor;
 import org.apache.ignite.tcbot.engine.chain.BuildChainProcessor;
 import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
@@ -56,6 +56,7 @@ public class DiContextTest {
         validateInstanceCachedFor(injector, BuildChainProcessor.class);
     }
 
+    @SuppressWarnings({"unchecked", "rawtypes"})
     public Injector getInjector() {
         TcBotWebAppModule igniteTcBotModule = new TcBotWebAppModule();
         Ignite ignite = mock(Ignite.class);
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessorTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessorTest.java
index bffaa895..0f935cba 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessorTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessorTest.java
@@ -20,7 +20,7 @@ import com.google.common.collect.Lists;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -66,7 +66,7 @@ public class BuildChainProcessorTest {
     /** Injector. */
     private Injector injector = Guice.createInjector(new AbstractModule() {
         @Override protected void configure() {
-            bind(IStringCompactor.class).to(InMemoryStringCompactor.class).in(new SingletonScope());
+            bind(IStringCompactor.class).to(InMemoryStringCompactor.class).in(Scopes.SINGLETON);
 
             bind(IBuildLogProcessor.class).toInstance(Mockito.mock(IBuildLogProcessor.class));
         }
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
index 91098ebc..325e6851 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.ci.tcbot.chain;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.ci.github.PullRequest;
 import org.apache.ignite.githubignited.IGitHubConnIgnited;
@@ -73,7 +73,7 @@ public class MockBasedTcBotModule extends AbstractModule {
 
     /** {@inheritDoc} */
     @Override protected void configure() {
-        bind(IStringCompactor.class).to(InMemoryStringCompactor.class).in(new SingletonScope());
+        bind(IStringCompactor.class).to(InMemoryStringCompactor.class).in(Scopes.SINGLETON);
 
         bind(IBuildLogProcessor.class).toInstance(Mockito.mock(IBuildLogProcessor.class));
 
@@ -87,7 +87,7 @@ public class MockBasedTcBotModule extends AbstractModule {
         IJiraServerConfig jiraCfg = mock(IJiraServerConfig.class);
         mockJira(jiraCfg);
 
-        bind(ITeamcityIgnitedProvider.class).to(TeamcityIgnitedProviderMock.class).in(new SingletonScope());
+        bind(ITeamcityIgnitedProvider.class).to(TeamcityIgnitedProviderMock.class).in(Scopes.SINGLETON);
 
         final ITcBotConfig cfg = new ITcBotConfig() {
             @Override public String primaryServerCode() {
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessorTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessorTest.java
index 093fdca0..a832185e 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessorTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessorTest.java
@@ -113,8 +113,6 @@ public class PrChainsProcessorTest {
         TestCompactedV2.resetCached();
         TestCompactedMult.resetCached();
     }
-
-    //todo flaky test
     @Test
     public void testTestFailureWithoutStatReportedAsBlocker() {
         IStringCompactor c = injector.getInstance(IStringCompactor.class);
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/issue/IssueDetectorTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/issue/IssueDetectorTest.java
index aeb07fca..191b52b2 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/issue/IssueDetectorTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/issue/IssueDetectorTest.java
@@ -125,12 +125,6 @@ public class IssueDetectorTest {
 
         System.out.println(masterStatus);
         assertTrue(masterStatus, masterStatus.contains("New issues found " + expIssuesCnt));
-
-        /* todo: https://issues.apache.org/jira/browse/IGNITE-10620
-
-        - Add examples of failed tests into history, validate notifications originated.
-
-         */
         issueDetector.sendNewNotificationsEx();
 
         issueDetector.stop();
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/board/BoardServiceTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/board/BoardServiceTest.java
index 2aec3e41..1dc0ab85 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/board/BoardServiceTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/board/BoardServiceTest.java
@@ -20,7 +20,7 @@ package org.apache.ignite.tcbot.engine.board;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -411,7 +411,7 @@ public class BoardServiceTest {
         /** {@inheritDoc} */
         @Override protected void configure() {
             bind(Ignite.class).toInstance(ignite);
-            bind(IScheduler.class).to(DirectExecNoWaitScheduler.class).in(new SingletonScope());
+            bind(IScheduler.class).to(DirectExecNoWaitScheduler.class).in(Scopes.SINGLETON);
 
             ITcBotConfig cfg = Mockito.mock(ITcBotConfig.class);
             bind(ITcBotConfig.class).toInstance(cfg);
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/board/TeamcityIgnitedModule.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/board/TeamcityIgnitedModule.java
index e0ef73e7..108f9d03 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/board/TeamcityIgnitedModule.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/board/TeamcityIgnitedModule.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.tcbot.engine.board;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildConditionDao;
 import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeDao;
 import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeRefDao;
@@ -52,28 +52,28 @@ import static org.mockito.Mockito.mock;
 public class TeamcityIgnitedModule extends AbstractModule {
     /** {@inheritDoc} */
     @Override protected void configure() {
-        bind(BuildRefDao.class).in(new SingletonScope());
-        bind(BuildRefSync.class).in(new SingletonScope());
-        bind(BuildConditionDao.class).in(new SingletonScope());
-        bind(FatBuildDao.class).in(new SingletonScope());
-        bind(ProactiveFatBuildSync.class).in(new SingletonScope());
-        bind(ChangeSync.class).in(new SingletonScope());
+        bind(BuildRefDao.class).in(Scopes.SINGLETON);
+        bind(BuildRefSync.class).in(Scopes.SINGLETON);
+        bind(BuildConditionDao.class).in(Scopes.SINGLETON);
+        bind(FatBuildDao.class).in(Scopes.SINGLETON);
+        bind(ProactiveFatBuildSync.class).in(Scopes.SINGLETON);
+        bind(ChangeSync.class).in(Scopes.SINGLETON);
         bind(ChangeDao.class).toInstance(mock(ChangeDao.class));
-        bind(BuildTypeRefDao.class).in(new SingletonScope());
-        bind(BuildTypeDao.class).in(new SingletonScope());
-        bind(BuildTypeSync.class).in(new SingletonScope());
-        bind(BuildStartTimeStorage.class).in(new SingletonScope());
-        bind(MuteDao.class).in(new SingletonScope());
-        bind(MuteSync.class).in(new SingletonScope());
-        bind(BuildLogCheckResultDao.class).in(new SingletonScope());
-        bind(SuiteInvocationHistoryDao.class).in(new SingletonScope());
-        bind(HistoryCollector.class).in(new SingletonScope());
-        bind(ILogProductSpecific.class).to(LogIgniteSpecific.class).in(new SingletonScope());
-        bind(UpdateCountersStorage.class).in(new SingletonScope());
-        bind(Cleaner.class).in(new SingletonScope());
-        bind(DefectsStorage.class).in(new SingletonScope());
-        bind(IIssuesStorage.class).to(IssuesStorage.class).in(new SingletonScope());
-        bind(BoardService.class).in(new SingletonScope());
+        bind(BuildTypeRefDao.class).in(Scopes.SINGLETON);
+        bind(BuildTypeDao.class).in(Scopes.SINGLETON);
+        bind(BuildTypeSync.class).in(Scopes.SINGLETON);
+        bind(BuildStartTimeStorage.class).in(Scopes.SINGLETON);
+        bind(MuteDao.class).in(Scopes.SINGLETON);
+        bind(MuteSync.class).in(Scopes.SINGLETON);
+        bind(BuildLogCheckResultDao.class).in(Scopes.SINGLETON);
+        bind(SuiteInvocationHistoryDao.class).in(Scopes.SINGLETON);
+        bind(HistoryCollector.class).in(Scopes.SINGLETON);
+        bind(ILogProductSpecific.class).to(LogIgniteSpecific.class).in(Scopes.SINGLETON);
+        bind(UpdateCountersStorage.class).in(Scopes.SINGLETON);
+        bind(Cleaner.class).in(Scopes.SINGLETON);
+        bind(DefectsStorage.class).in(Scopes.SINGLETON);
+        bind(IIssuesStorage.class).to(IssuesStorage.class).in(Scopes.SINGLETON);
+        bind(BoardService.class).in(Scopes.SINGLETON);
         bind(ITeamcityIgnitedProvider.class).toInstance(mock(ITeamcityIgnitedProvider.class));
         bind(IUserStorage.class).toInstance(mock(IUserStorage.class));
 
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/CleanerTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/CleanerTest.java
index ce47c61f..d8a7e1dd 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/CleanerTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/CleanerTest.java
@@ -20,7 +20,7 @@ package org.apache.ignite.tcbot.engine.cleaner;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 import java.lang.reflect.Field;
 import java.util.Random;
 import org.apache.ignite.Ignite;
@@ -273,7 +273,7 @@ public class CleanerTest {
         /** {@inheritDoc} */
         @Override protected void configure() {
             bind(Ignite.class).toInstance(ignite);
-            bind(IScheduler.class).to(DirectExecNoWaitScheduler.class).in(new SingletonScope());
+            bind(IScheduler.class).to(DirectExecNoWaitScheduler.class).in(Scopes.SINGLETON);
 
             final IJiraIntegrationProvider jiraProv = Mockito.mock(IJiraIntegrationProvider.class);
             bind(IJiraIntegrationProvider.class).toInstance(jiraProv);
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/TeamcityIgnitedModule.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/TeamcityIgnitedModule.java
index 79834ce2..5df8cc68 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/TeamcityIgnitedModule.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcbot/engine/cleaner/TeamcityIgnitedModule.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.tcbot.engine.cleaner;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildConditionDao;
 import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeDao;
 import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeRefDao;
@@ -47,27 +47,27 @@ import org.apache.ignite.tcservice.TcRealConnectionModule;
 public class TeamcityIgnitedModule extends AbstractModule {
     /** {@inheritDoc} */
     @Override protected void configure() {
-        bind(BuildRefDao.class).in(new SingletonScope());
-        bind(BuildRefSync.class).in(new SingletonScope());
-        bind(BuildConditionDao.class).in(new SingletonScope());
-        bind(FatBuildDao.class).in(new SingletonScope());
-        bind(ProactiveFatBuildSync.class).in(new SingletonScope());
-        bind(ChangeSync.class).in(new SingletonScope());
-        bind(ChangeDao.class).in(new SingletonScope());
-        bind(BuildTypeRefDao.class).in(new SingletonScope());
-        bind(BuildTypeDao.class).in(new SingletonScope());
-        bind(BuildTypeSync.class).in(new SingletonScope());
-        bind(BuildStartTimeStorage.class).in(new SingletonScope());
-        bind(MuteDao.class).in(new SingletonScope());
-        bind(MuteSync.class).in(new SingletonScope());
-        bind(BuildLogCheckResultDao.class).in(new SingletonScope());
-        bind(SuiteInvocationHistoryDao.class).in(new SingletonScope());
-        bind(HistoryCollector.class).in(new SingletonScope());
-        bind(ILogProductSpecific.class).to(LogIgniteSpecific.class).in(new SingletonScope());
-        bind(UpdateCountersStorage.class).in(new SingletonScope());
-        bind(Cleaner.class).in(new SingletonScope());
-        bind(DefectsStorage.class).in(new SingletonScope());
-        bind(IIssuesStorage.class).to(IssuesStorage.class).in(new SingletonScope());
+        bind(BuildRefDao.class).in(Scopes.SINGLETON);
+        bind(BuildRefSync.class).in(Scopes.SINGLETON);
+        bind(BuildConditionDao.class).in(Scopes.SINGLETON);
+        bind(FatBuildDao.class).in(Scopes.SINGLETON);
+        bind(ProactiveFatBuildSync.class).in(Scopes.SINGLETON);
+        bind(ChangeSync.class).in(Scopes.SINGLETON);
+        bind(ChangeDao.class).in(Scopes.SINGLETON);
+        bind(BuildTypeRefDao.class).in(Scopes.SINGLETON);
+        bind(BuildTypeDao.class).in(Scopes.SINGLETON);
+        bind(BuildTypeSync.class).in(Scopes.SINGLETON);
+        bind(BuildStartTimeStorage.class).in(Scopes.SINGLETON);
+        bind(MuteDao.class).in(Scopes.SINGLETON);
+        bind(MuteSync.class).in(Scopes.SINGLETON);
+        bind(BuildLogCheckResultDao.class).in(Scopes.SINGLETON);
+        bind(SuiteInvocationHistoryDao.class).in(Scopes.SINGLETON);
+        bind(HistoryCollector.class).in(Scopes.SINGLETON);
+        bind(ILogProductSpecific.class).to(LogIgniteSpecific.class).in(Scopes.SINGLETON);
+        bind(UpdateCountersStorage.class).in(Scopes.SINGLETON);
+        bind(Cleaner.class).in(Scopes.SINGLETON);
+        bind(DefectsStorage.class).in(Scopes.SINGLETON);
+        bind(IIssuesStorage.class).to(IssuesStorage.class).in(Scopes.SINGLETON);
 
         TcRealConnectionModule module = new TcRealConnectionModule();
 
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcignited/IgnitedTcInMemoryIntegrationTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcignited/IgnitedTcInMemoryIntegrationTest.java
index 875627cc..c200ff10 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcignited/IgnitedTcInMemoryIntegrationTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/tcignited/IgnitedTcInMemoryIntegrationTest.java
@@ -20,7 +20,7 @@ import com.google.common.collect.Lists;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileWriter;
@@ -217,7 +217,6 @@ public class IgnitedTcInMemoryIntegrationTest {
         String buildTypeId = "IgniteTests24Java8_RunAll";
         String branchName = "<default>";
         List<BuildRefCompacted> hist = srv.getAllBuildsCompacted(buildTypeId, branchName);
-        //todo mult branches including pull/4926/head
 
         assertTrue(!hist.isEmpty());
 
@@ -473,7 +472,7 @@ public class IgnitedTcInMemoryIntegrationTest {
         Injector injector = Guice.createInjector(new AbstractModule() {
             @Override protected void configure() {
                 bind(Ignite.class).toInstance(ignite);
-                bind(IStringCompactor.class).to(IgniteStringCompactor.class).in(new SingletonScope());
+                bind(IStringCompactor.class).toInstance(new IgniteStringCompactor(() -> ignite));
                 bind(IDataSourcesConfigSupplier.class).toInstance(Mockito.mock(IDataSourcesConfigSupplier.class));
                 bind(ILogProductSpecific.class).toInstance(Mockito.mock(ILogProductSpecific.class));
             }
@@ -615,8 +614,6 @@ public class IgnitedTcInMemoryIntegrationTest {
             c.getStringId(PrChainsProcessorTest.TEST_FLAKY_IN_MASTER),
             c.getStringId(PrChainsProcessorTest.CACHE_1),
             c.getStringId(branch));
-
-        // todo register builds buildsMap somehow in injector
         // assertNotNull(testRunHist);
         // assertEquals(0.5, testRunHist.getFailRate(), 0.1);
 
@@ -624,7 +621,6 @@ public class IgnitedTcInMemoryIntegrationTest {
             , c.getStringId(branch));
 
         assertNotNull(cache1Hist);
-        // todo register builds somehow in injector
         //assertEquals(1.0, cache1Hist.self().getFailRate(), 0.1);
         //assertEquals(0.18, cache1Hist.self().getCriticalFailRate(), 0.05);
     }
@@ -903,7 +899,7 @@ public class IgnitedTcInMemoryIntegrationTest {
         /** {@inheritDoc} */
         @Override protected void configure() {
             bind(Ignite.class).toInstance(ignite);
-            bind(IScheduler.class).to(DirectExecNoWaitScheduler.class).in(new SingletonScope());
+            bind(IScheduler.class).to(DirectExecNoWaitScheduler.class).in(Scopes.SINGLETON);
 
             final IJiraIntegrationProvider jiraProv = Mockito.mock(IJiraIntegrationProvider.class);
             bind(IJiraIntegrationProvider.class).toInstance(jiraProv);
diff --git a/jetty-launcher/build.gradle b/jetty-launcher/build.gradle
index e1fd2a64..748e965c 100644
--- a/jetty-launcher/build.gradle
+++ b/jetty-launcher/build.gradle
@@ -66,13 +66,13 @@ dependencies {
         transitive = false
     }
 
-    implementation group: 'org.eclipse.jetty', name: 'jetty-util', version: jettyVer
-    implementation group: 'org.eclipse.jetty', name: 'jetty-server', version: jettyVer
-    implementation group: 'org.eclipse.jetty.ee8', name: 'jetty-ee8-webapp', version: jettyVer
+    implementation "org.eclipse.jetty:jetty-util:$jettyVer"
+    implementation "org.eclipse.jetty:jetty-server:$jettyVer"
+    implementation "org.eclipse.jetty.ee8:jetty-ee8-webapp:$jettyVer"
 
-    implementation group: 'com.google.guava', name: 'guava', version: guavaVer
+    implementation "com.google.guava:guava:$guavaVer"
 
-    implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVer
-    implementation group: 'ch.qos.logback', name: 'logback-core', version: logbackVer
-    implementation group: 'ch.qos.logback', name: 'logback-classic', version: logbackVer
+    implementation "org.slf4j:slf4j-api:$slf4jVer"
+    implementation "ch.qos.logback:logback-core:$logbackVer"
+    implementation "ch.qos.logback:logback-classic:$logbackVer"
 }
diff --git a/migrator/build.gradle b/migrator/build.gradle
index 997bd293..6aa62210 100644
--- a/migrator/build.gradle
+++ b/migrator/build.gradle
@@ -8,14 +8,14 @@ repositories {
 
 dependencies {
     implementation "org.apache.ignite:ignite-core:$ignVer"
-    implementation group: 'ch.qos.logback', name: 'logback-classic', version: logbackVer
+    implementation "ch.qos.logback:logback-classic:$logbackVer"
     implementation project(':tcbot-common')
 
     testImplementation project(':ignite-tc-helper-web')
     testImplementation project(':tcbot-persistence')
     testImplementation project(':tcbot-teamcity-ignited')
     testImplementation "org.apache.ignite:ignite-slf4j:$ignVer"
-    testImplementation group: 'junit', name: 'junit', version: junitVer
+    testImplementation "junit:junit:$junitVer"
 }
 
 application {
diff --git a/settings.gradle b/settings.gradle
index fd67a803..bcb5ac16 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,7 +1,7 @@
 include 'ignite-tc-helper-web'
 include 'jetty-launcher'
 include 'migrator'
-include 'tcbot-server-node'
+include 'tcbot-app-guice'
 include 'tcbot-common'
 include 'tcbot-notify'
 include 'tcbot-persistence'
diff --git a/tcbot-engine/build.gradle b/tcbot-app-guice/build.gradle
similarity index 53%
copy from tcbot-engine/build.gradle
copy to tcbot-app-guice/build.gradle
index 3606f363..4c022ac4 100644
--- a/tcbot-engine/build.gradle
+++ b/tcbot-app-guice/build.gradle
@@ -15,15 +15,22 @@
  * limitations under the License.
  */
 
-apply plugin: 'java'
+apply plugin: 'java-library'
 
 dependencies {
-    api project(":tcbot-teamcity-ignited")
-    api project(":tcbot-github-ignited")
-    api project(":tcbot-jira-ignited")
-    api project(":tcbot-notify")
+    implementation project(":tcbot-common")
+    implementation project(":tcbot-engine")
+    implementation project(":tcbot-github")
+    implementation project(":tcbot-github-ignited")
+    implementation project(":tcbot-jira")
+    implementation project(":tcbot-jira-ignited")
+    implementation project(":tcbot-notify")
+    implementation project(":tcbot-persistence")
+    implementation project(":tcbot-teamcity")
+    implementation project(":tcbot-teamcity-ignited")
+    implementation project(":ignite-tc-helper-web")
 
-    testImplementation group: 'junit', name: 'junit', version: junitVer
-    testImplementation group: 'org.mockito', name: 'mockito-core', version: mockitoVer
+    implementation "com.google.inject:guice:$guiceVer"
+    implementation 'javax.inject:javax.inject:1'
+    implementation 'aopalliance:aopalliance:1.0'
 }
-
diff --git a/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/GitHubIgnitedModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/githubignited/GitHubIgnitedModule.java
similarity index 93%
rename from tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/GitHubIgnitedModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/githubignited/GitHubIgnitedModule.java
index 9c199651..e443cca2 100644
--- a/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/GitHubIgnitedModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/githubignited/GitHubIgnitedModule.java
@@ -17,7 +17,7 @@
 package org.apache.ignite.githubignited;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 import org.apache.ignite.githubservice.GitHubIntegrationModule;
 
 /**
@@ -28,6 +28,6 @@ public class GitHubIgnitedModule extends AbstractModule {
     @Override protected void configure() {
         install(new GitHubIntegrationModule());
 
-        bind(IGitHubConnIgnitedProvider.class).to(GitHubIgnitedProvImpl.class).in(new SingletonScope());
+        bind(IGitHubConnIgnitedProvider.class).to(GitHubIgnitedProvImpl.class).in(Scopes.SINGLETON);
     }
 }
diff --git a/tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubIntegrationModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/githubservice/GitHubIntegrationModule.java
similarity index 65%
copy from tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubIntegrationModule.java
copy to tcbot-app-guice/src/main/java/org/apache/ignite/githubservice/GitHubIntegrationModule.java
index 63090ad5..1e644679 100644
--- a/tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubIntegrationModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/githubservice/GitHubIntegrationModule.java
@@ -17,12 +17,20 @@
 package org.apache.ignite.githubservice;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+import org.apache.ignite.tcbot.common.conf.IDataSourcesConfigSupplier;
 
 public class GitHubIntegrationModule extends AbstractModule {
-    /** {@inheritDoc} */
-    @Override protected void configure() {
-        bind(IGitHubConnection.class).to(GitHubConnectionImpl.class);
-        bind(IGitHubConnectionProvider.class).to(GitHubCachingProvider.class).in(new SingletonScope());
+    @Provides
+    IGitHubConnection gitHubConnection(IDataSourcesConfigSupplier cfg) {
+        return new GitHubConnectionImpl(cfg);
+    }
+
+    @Provides
+    @Singleton
+    IGitHubConnectionProvider gitHubConnectionProvider(Provider<IGitHubConnection> factory) {
+        return new GitHubCachingProvider(factory::get);
     }
 }
diff --git a/tcbot-jira-ignited/src/main/java/org/apache/ignite/jiraignited/JiraIgnitedModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/jiraignited/JiraIgnitedModule.java
similarity index 87%
rename from tcbot-jira-ignited/src/main/java/org/apache/ignite/jiraignited/JiraIgnitedModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/jiraignited/JiraIgnitedModule.java
index c58341fd..e7752bdb 100644
--- a/tcbot-jira-ignited/src/main/java/org/apache/ignite/jiraignited/JiraIgnitedModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/jiraignited/JiraIgnitedModule.java
@@ -17,7 +17,7 @@
 package org.apache.ignite.jiraignited;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 import org.apache.ignite.jiraservice.JiraIntegrationModule;
 
 /**
@@ -28,8 +28,8 @@ public class JiraIgnitedModule extends AbstractModule {
     @Override protected void configure() {
         bind(IJiraIgnitedProvider.class).to(JiraIgnitedProvider.class);
 
-        bind(JiraTicketDao.class).in(new SingletonScope());
-        bind(JiraTicketSync.class).in(new SingletonScope());
+        bind(JiraTicketDao.class).in(Scopes.SINGLETON);
+        bind(JiraTicketSync.class).in(Scopes.SINGLETON);
 
         install(new JiraIntegrationModule());
     }
diff --git a/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/JiraIntegrationModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/jiraservice/JiraIntegrationModule.java
similarity index 92%
rename from tcbot-jira/src/main/java/org/apache/ignite/jiraservice/JiraIntegrationModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/jiraservice/JiraIntegrationModule.java
index 325a94ee..85ba7697 100644
--- a/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/JiraIntegrationModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/jiraservice/JiraIntegrationModule.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.jiraservice;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 
 /**
  * JIRA pure integration module
@@ -27,6 +27,6 @@ public class JiraIntegrationModule extends AbstractModule {
     /** {@inheritDoc} */
     @Override protected void configure() {
         bind(IJiraIntegration.class).to(Jira.class);
-        bind(IJiraIntegrationProvider.class).to(JiraIntegrationProvider.class).in(new SingletonScope());
+        bind(IJiraIntegrationProvider.class).to(JiraIntegrationProvider.class).in(Scopes.SINGLETON);
     }
 }
diff --git a/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/app/guice/GuiceTcBotApplicationContext.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/app/guice/GuiceTcBotApplicationContext.java
new file mode 100644
index 00000000..d654a0d6
--- /dev/null
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/app/guice/GuiceTcBotApplicationContext.java
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.tcbot.app.guice;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.spi.ProvisionListener;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.ci.db.TcHelperDb;
+import org.apache.ignite.ci.observer.BuildObserver;
+import org.apache.ignite.ci.tcbot.issue.IssueDetector;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
+import org.apache.ignite.tcbot.common.monitoring.MonitoredTasks;
+import org.apache.ignite.tcbot.engine.cleaner.Cleaner;
+import org.apache.ignite.tcbot.engine.conf.INotificationChannel;
+import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
+import org.apache.ignite.tcbot.engine.conf.NotificationsConfig;
+import org.apache.ignite.tcbot.engine.pool.TcUpdatePool;
+import org.apache.ignite.tcbot.notify.ISlackSender;
+import org.apache.ignite.tcbot.persistence.scheduler.IScheduler;
+import org.apache.ignite.tcservice.http.TeamcityRecorder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class GuiceTcBotApplicationContext implements TcBotApplicationContext {
+    /** Logger. */
+    private static final Logger logger = LoggerFactory.getLogger(GuiceTcBotApplicationContext.class);
+
+    private Injector injector;
+    private final LifecycleTracker lifecycleTracker = new LifecycleTracker();
+
+    private final AtomicBoolean started = new AtomicBoolean();
+    private final AtomicBoolean ready = new AtomicBoolean();
+    private final AtomicBoolean closed = new AtomicBoolean();
+
+    /** {@inheritDoc} */
+    @Override public synchronized void start() {
+        if (started.get())
+            return;
+
+        if (closed.get())
+            throw new IllegalStateException("TC Bot application context is already closed");
+
+        if (!started.compareAndSet(false, true))
+            return;
+
+        try {
+            TcBotWebAppModule module = new TcBotWebAppModule();
+            injector = Guice.createInjector(new LifecycleTrackingModule(lifecycleTracker), module);
+
+            Future<Ignite> igniteFuture = module.startIgniteInit(injector);
+            startBackgroundServicesWhenReady(igniteFuture);
+        }
+        catch (RuntimeException | Error e) {
+            started.set(false);
+
+            throw e;
+        }
+
+    }
+
+    private void startBackgroundServicesWhenReady(Future<Ignite> igniteFuture) {
+        Thread thread = new Thread(() -> {
+            try {
+                igniteFuture.get();
+
+                if (!started.get() || closed.get())
+                    return;
+
+                getInstance(BuildObserver.class);
+                ready.set(true);
+            }
+            catch (Exception e) {
+                logger.error("Exception during background services start: " + e.getMessage(), e);
+            }
+        }, "tc-bot-background-services-start");
+
+        thread.setDaemon(true);
+        thread.start();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isReady() {
+        return ready.get() && !closed.get();
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> T getInstance(Class<T> type) {
+        if (injector == null)
+            throw new IllegalStateException("TC Bot application context is not started");
+
+        return injector.getInstance(type);
+    }
+
+    /** {@inheritDoc} */
+    @Override public synchronized void close() {
+        if (!closed.compareAndSet(false, true))
+            return;
+
+        ready.set(false);
+
+        Injector injector = this.injector;
+        if (injector == null)
+            return;
+
+        sendMessageToSlackChannel("TeamCity Bot is stopped!");
+
+        shutdown("shutdown", () -> {
+            shutdownIfProvisioned(IssueDetector.class, IssueDetector::stop);
+            shutdownIfProvisioned(TcUpdatePool.class, TcUpdatePool::stop);
+            shutdownIfProvisioned(BuildObserver.class, BuildObserver::stop);
+            shutdownIfProvisioned(IScheduler.class, IScheduler::stop);
+            shutdownIfProvisioned(Cleaner.class, Cleaner::stop);
+        });
+
+        shutdown("TeamCity recorder shutdown", () -> {
+            shutdownIfProvisioned(TeamcityRecorder.class, TeamcityRecorder::stop);
+        });
+
+        shutdown("monitoring shutdown", () -> {
+            shutdownIfProvisioned(MonitoredTasks.class, MonitoredTasks::close);
+        });
+
+        shutdown("Ignite shutdown", () -> {
+            TcHelperDb.stop(getInstance(Ignite.class));
+        });
+
+        this.injector = null;
+    }
+
+    private <T> void shutdownIfProvisioned(Class<T> type, ThrowingConsumer<T> action) throws Exception {
+        T instance = lifecycleTracker.getInstance(type);
+
+        if (instance != null)
+            action.accept(instance);
+    }
+
+    private void shutdown(String action, ThrowingRunnable actionToRun) {
+        try {
+            actionToRun.run();
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+
+            logger.error("Exception during " + action + ": " + e.getMessage(), e);
+        }
+    }
+
+    private void sendMessageToSlackChannel(String msg) {
+        try {
+            ISlackSender slackSender = getInstance(ISlackSender.class);
+            ITcBotConfig tcBotConfig = getInstance(ITcBotConfig.class);
+            NotificationsConfig notifications = tcBotConfig.notifications();
+
+            for (INotificationChannel channel : notifications.channels()) {
+                if (channel.slack() != null && channel.slack().startsWith("#"))
+                    slackSender.sendMessage(channel.slack(), msg, notifications);
+            }
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+
+            logger.error("Exception during sending message to the slack channel: " + e.getMessage(), e);
+        }
+    }
+
+    private interface ThrowingRunnable {
+        void run() throws Exception;
+    }
+
+    private interface ThrowingConsumer<T> {
+        void accept(T value) throws Exception;
+    }
+
+    private static class LifecycleTrackingModule extends AbstractModule {
+        private final ProvisionListener listener;
+
+        private LifecycleTrackingModule(ProvisionListener listener) {
+            this.listener = listener;
+        }
+
+        /** {@inheritDoc} */
+        @Override protected void configure() {
+            bindListener(Matchers.any(), listener);
+        }
+    }
+
+    private static class LifecycleTracker implements ProvisionListener {
+        private final List<Object> instances = new ArrayList<>();
+
+        /** {@inheritDoc} */
+        @Override public <T> void onProvision(ProvisionInvocation<T> provision) {
+            T instance = provision.provision();
+
+            if (instance == null)
+                return;
+
+            synchronized (instances) {
+                for (Object existing : instances) {
+                    if (existing == instance)
+                        return;
+                }
+
+                instances.add(instance);
+            }
+        }
+
+        private <T> T getInstance(Class<T> type) {
+            synchronized (instances) {
+                for (Object instance : instances) {
+                    if (type.isInstance(instance))
+                        return type.cast(instance);
+                }
+            }
+
+            return null;
+        }
+    }
+}
diff --git a/tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubIntegrationModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/app/guice/GuiceTcBotApplicationContextFactory.java
similarity index 67%
rename from tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubIntegrationModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/app/guice/GuiceTcBotApplicationContextFactory.java
index 63090ad5..7eab37b7 100644
--- a/tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubIntegrationModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/app/guice/GuiceTcBotApplicationContextFactory.java
@@ -14,15 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.githubservice;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+package org.apache.ignite.tcbot.app.guice;
 
-public class GitHubIntegrationModule extends AbstractModule {
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContext;
+import org.apache.ignite.tcbot.common.application.TcBotApplicationContextFactory;
+
+public class GuiceTcBotApplicationContextFactory implements TcBotApplicationContextFactory {
     /** {@inheritDoc} */
-    @Override protected void configure() {
-        bind(IGitHubConnection.class).to(GitHubConnectionImpl.class);
-        bind(IGitHubConnectionProvider.class).to(GitHubCachingProvider.class).in(new SingletonScope());
+    @Override public TcBotApplicationContext create() {
+        return new GuiceTcBotApplicationContext();
     }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/TcBotWebAppModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/app/guice/TcBotWebAppModule.java
similarity index 74%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/TcBotWebAppModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/app/guice/TcBotWebAppModule.java
index 29ef04bd..871fcc4a 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/TcBotWebAppModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/app/guice/TcBotWebAppModule.java
@@ -14,20 +14,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.ci.tcbot;
+package org.apache.ignite.tcbot.app.guice;
 
 import com.google.common.base.Preconditions;
 import com.google.inject.AbstractModule;
 import com.google.inject.Injector;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 import javax.inject.Provider;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.ci.db.Ignite1Init;
 import org.apache.ignite.ci.observer.BuildObserver;
 import org.apache.ignite.ci.observer.ObserverTask;
+import org.apache.ignite.ci.tcbot.ITcBotBgAuth;
+import org.apache.ignite.ci.tcbot.TcBotBgAuthImpl;
 import org.apache.ignite.ci.tcbot.conf.LocalFilesBasedConfig;
 import org.apache.ignite.ci.tcbot.issue.IssueDetector;
 import org.apache.ignite.ci.tcbot.trends.MasterTrendsService;
@@ -60,26 +61,29 @@ public class TcBotWebAppModule extends AbstractModule {
         bind(Ignite.class).toProvider((Provider<Ignite>)() -> {
             Preconditions.checkNotNull(igniteFut, "Ignite future is not yet initialized");
 
+            if (!igniteFut.isDone())
+                throw new ServicesStartingException(new RuntimeException("Ignite is not yet available"));
+
             try {
-                return igniteFut.get(10, TimeUnit.SECONDS);
-            }
-            catch (TimeoutException e) {
-                throw new ServicesStartingException(e);
+                return igniteFut.get();
             }
-            catch (Exception e) {
-                e.printStackTrace();
+            catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
 
                 throw ExceptionUtil.propagateException(e);
             }
+            catch (ExecutionException e) {
+                throw ExceptionUtil.propagateException(e);
+            }
         });
 
         bind(ITeamcityConn.class).toInstance(new TeamcityServiceConnection());
-        bind(TcUpdatePool.class).in(new SingletonScope());
-        bind(IssueDetector.class).in(new SingletonScope());
-        bind(ObserverTask.class).in(new SingletonScope());
-        bind(BuildObserver.class).in(new SingletonScope());
-        bind(VisasHistoryStorage.class).in(new SingletonScope());
-        bind(Cleaner.class).in(new SingletonScope());
+        bind(TcUpdatePool.class).in(Scopes.SINGLETON);
+        bind(IssueDetector.class).in(Scopes.SINGLETON);
+        bind(ObserverTask.class).in(Scopes.SINGLETON);
+        bind(BuildObserver.class).in(Scopes.SINGLETON);
+        bind(VisasHistoryStorage.class).in(Scopes.SINGLETON);
+        bind(Cleaner.class).in(Scopes.SINGLETON);
 
         install(new TcBotPersistenceModule());
         install(new TeamcityIgnitedModule());
@@ -90,23 +94,22 @@ public class TcBotWebAppModule extends AbstractModule {
 
         // common services
         install(new TcBotEngineModule());
-        bind(ITcBotConfig.class).to(LocalFilesBasedConfig.class).in(new SingletonScope());
-        //todo remove duplication of instances for base and for overriden class
-        bind(IDataSourcesConfigSupplier.class).to(LocalFilesBasedConfig.class).in(new SingletonScope());
-        bind(MasterTrendsService.class).in(new SingletonScope());
-        bind(ITcBotBgAuth.class).to(TcBotBgAuthImpl.class).in(new SingletonScope());
+        bind(ITcBotConfig.class).to(LocalFilesBasedConfig.class).in(Scopes.SINGLETON);
+        bind(IDataSourcesConfigSupplier.class).to(LocalFilesBasedConfig.class).in(Scopes.SINGLETON);
+        bind(MasterTrendsService.class).in(Scopes.SINGLETON);
+        bind(ITcBotBgAuth.class).to(TcBotBgAuthImpl.class).in(Scopes.SINGLETON);
     }
 
     public void setIgniteFut(Future<Ignite> igniteFut) {
         this.igniteFut = igniteFut;
     }
 
-    public Injector startIgniteInit(Injector injector) {
+    public Future<Ignite> startIgniteInit(Injector injector) {
         final Ignite1Init instance = injector.getInstance(Ignite1Init.class);
         final Future<Ignite> submit = instance.getIgniteFuture();
         setIgniteFut(submit);
 
-        return injector;
+        return submit;
     }
 
 }
diff --git a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/TcBotCommonModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/TcBotCommonModule.java
similarity index 100%
rename from tcbot-common/src/main/java/org/apache/ignite/tcbot/common/TcBotCommonModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/TcBotCommonModule.java
diff --git a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/AutoProfilingInterceptor.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/AutoProfilingInterceptor.java
similarity index 94%
rename from tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/AutoProfilingInterceptor.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/AutoProfilingInterceptor.java
index fda3d114..0cb3065f 100644
--- a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/AutoProfilingInterceptor.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/AutoProfilingInterceptor.java
@@ -26,15 +26,16 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
+import org.apache.ignite.tcbot.common.monitoring.ProfilingMonitor;
 
-public class AutoProfilingInterceptor implements MethodInterceptor {
+public class AutoProfilingInterceptor implements MethodInterceptor, ProfilingMonitor {
     private final ConcurrentMap<String, Invocation> totalTime = new ConcurrentHashMap<>();
 
     public void reset() {
         totalTime.clear();
     }
 
-    public static class Invocation {
+    public static class Invocation implements ProfilingMonitor.Invocation {
         private final AtomicLong timeNanos = new AtomicLong();
         private final AtomicInteger callsCnt = new AtomicInteger();
         private String name;
diff --git a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/AutoProfilingInterceptorModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/AutoProfilingInterceptorModule.java
similarity index 91%
rename from tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/AutoProfilingInterceptorModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/AutoProfilingInterceptorModule.java
index f0448c9f..e4dc8b57 100644
--- a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/AutoProfilingInterceptorModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/AutoProfilingInterceptorModule.java
@@ -18,6 +18,7 @@ package org.apache.ignite.tcbot.common.interceptor;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.matcher.Matchers;
+import org.apache.ignite.tcbot.common.monitoring.ProfilingMonitor;
 
 public class AutoProfilingInterceptorModule extends AbstractModule {
     @Override protected void configure() {
@@ -32,5 +33,6 @@ public class AutoProfilingInterceptorModule extends AbstractModule {
             profilingInterceptor);
 
         bind(AutoProfilingInterceptor.class).toInstance(profilingInterceptor);
+        bind(ProfilingMonitor.class).toInstance(profilingInterceptor);
     }
 }
diff --git a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/GuavaCachedInterceptor.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/GuavaCachedInterceptor.java
similarity index 55%
rename from tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/GuavaCachedInterceptor.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/GuavaCachedInterceptor.java
index 6c0180f0..61841cd4 100644
--- a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/GuavaCachedInterceptor.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/GuavaCachedInterceptor.java
@@ -16,31 +16,30 @@
  */
 package org.apache.ignite.tcbot.common.interceptor;
 
+import java.time.Duration;
+
 import com.google.common.base.Preconditions;
-import com.google.common.base.Throwables;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
 import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
-import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.TimeUnit;
 import javax.annotation.Nonnull;
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
 
 public class GuavaCachedInterceptor implements MethodInterceptor {
-    private final ConcurrentMap<String, Cache<List, Optional>> caches = new ConcurrentHashMap<>();
+    private final ConcurrentMap<String, Cache<List<Object>, Optional<Object>>> caches = new ConcurrentHashMap<>();
 
     @Override public Object invoke(MethodInvocation invocation) throws Throwable {
         final Method invocationMtd = invocation.getMethod();
         GuavaCached annotation = invocationMtd.getAnnotation(GuavaCached.class);
 
-        Cache<List, Optional> cache = caches.computeIfAbsent(cacheId(invocation), k -> {
-            CacheBuilder builder = CacheBuilder.newBuilder();
+        Cache<List<Object>, Optional<Object>> cache = caches.computeIfAbsent(cacheId(invocation), k -> {
+            CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
 
             if (annotation.softValues())
                 builder = builder.softValues();
@@ -49,46 +48,41 @@ public class GuavaCachedInterceptor implements MethodInterceptor {
                 builder = builder.maximumSize(annotation.maximumSize());
 
             if (annotation.expireAfterAccessSecs() > 0)
-                builder.expireAfterAccess(annotation.expireAfterAccessSecs(), TimeUnit.SECONDS);
+                builder.expireAfterAccess(Duration.ofSeconds(annotation.expireAfterAccessSecs()));
 
             if (annotation.expireAfterWriteSecs() > 0)
-                builder.expireAfterWrite(annotation.expireAfterWriteSecs(), TimeUnit.SECONDS);
+                builder.expireAfterWrite(Duration.ofSeconds(annotation.expireAfterWriteSecs()));
 
             return builder.build();
         });
 
         List<Object> cacheKey = Arrays.asList(invocation.getArguments());
 
-        Optional optional = cache.get(cacheKey,
-            new Callable<Optional>() {
-                @Override public Optional call() throws Exception {
-                    Object res;
-                    try {
-                        res = invocation.proceed();
-                    }
-                    catch (Throwable throwable) {
-                        Throwables.propagateIfPossible(throwable, Exception.class);
-
-                        throw new RuntimeException(throwable);
-                    }
-                    return Optional.ofNullable(res);
-                }
-            });
-
-        if (!annotation.cacheNullRval()) {
-            if (!optional.isPresent())
-                cache.invalidate(cacheKey);
-        }
+        Optional<Object> optional = cache.get(cacheKey, () -> {
+            try {
+                return Optional.ofNullable(invocation.proceed());
+            }
+            catch (Throwable throwable) {
+                if (throwable instanceof Exception)
+                    throw (Exception)throwable;
 
-        if (!annotation.cacheNegativeNumbersRval()) {
-            if (optional.isPresent()) {
-                Object o = optional.get();
-                Preconditions.checkState(o instanceof Number, "Invalid return value of method: " + cacheKey);
+                if (throwable instanceof Error)
+                    throw (Error)throwable;
 
-                Number num = (Number)o;
-                if (num.longValue() < 0)
-                    cache.invalidate(cacheKey);
+                throw new RuntimeException(throwable);
             }
+        });
+
+        if (!annotation.cacheNullRval() && optional.isEmpty())
+            cache.invalidate(cacheKey);
+
+        if (!annotation.cacheNegativeNumbersRval() && optional.isPresent()) {
+            Object o = optional.get();
+            Preconditions.checkState(o instanceof Number, "Invalid return value of method: " + cacheKey);
+
+            Number num = (Number)o;
+            if (num.longValue() < 0)
+                cache.invalidate(cacheKey);
         }
 
         return optional.orElse(null);
@@ -96,10 +90,8 @@ public class GuavaCachedInterceptor implements MethodInterceptor {
 
     @Nonnull
     private String cacheId(MethodInvocation invocation) {
-        final Method invocationMtd = invocation.getMethod();
-        final String cls = invocationMtd.getDeclaringClass().getName();
-        final String mtd = invocationMtd.getName();
+        Method method = invocation.getMethod();
 
-        return cls + "." + mtd;
+        return method.getDeclaringClass().getName() + "." + method.getName();
     }
 }
diff --git a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/GuavaCachedModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/GuavaCachedModule.java
similarity index 100%
rename from tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/GuavaCachedModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/GuavaCachedModule.java
diff --git a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/MonitoredTaskInterceptor.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/MonitoredTaskInterceptor.java
similarity index 91%
rename from tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/MonitoredTaskInterceptor.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/MonitoredTaskInterceptor.java
index a47b55ea..cb43706e 100644
--- a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/MonitoredTaskInterceptor.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/MonitoredTaskInterceptor.java
@@ -35,11 +35,12 @@ import javax.annotation.Nonnull;
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
 import org.apache.ignite.tcbot.common.conf.TcBotWorkDir;
+import org.apache.ignite.tcbot.common.monitoring.MonitoredTasks;
 import org.apache.ignite.tcbot.common.util.TimeUtil;
 
 import static org.apache.ignite.tcbot.common.util.TimeUtil.timestampForLogsSimpleDate;
 
-public class MonitoredTaskInterceptor implements MethodInterceptor, AutoCloseable {
+public class MonitoredTaskInterceptor implements MethodInterceptor, MonitoredTasks {
     private final ConcurrentMap<String, Invocation> totalTime = new ConcurrentSkipListMap<>();
 
     private final long startedTs = System.currentTimeMillis();
@@ -52,8 +53,8 @@ public class MonitoredTaskInterceptor implements MethodInterceptor, AutoCloseabl
         try {
             final File workDir = TcBotWorkDir.resolveWorkDir();
             File tcbotLogs = new File(workDir, "tcbot_logs");
-            File file = new File(tcbotLogs, "monitoring"+
-                timestampForLogsSimpleDate(System.currentTimeMillis())+".log");
+            File file = new File(tcbotLogs, "monitoring" +
+                timestampForLogsSimpleDate(System.currentTimeMillis()) + ".log");
 
             if (!tcbotLogs.exists())
                 tcbotLogs.mkdirs();
@@ -72,7 +73,7 @@ public class MonitoredTaskInterceptor implements MethodInterceptor, AutoCloseabl
         fileWriter = null;
     }
 
-    public static class Invocation {
+    public static class Invocation implements MonitoredTasks.Invocation {
         private final AtomicLong lastStartTs = new AtomicLong();
         private final AtomicLong lastEndTs = new AtomicLong();
         private final AtomicReference<Object> lastResult = new AtomicReference<>();
@@ -142,7 +143,7 @@ public class MonitoredTaskInterceptor implements MethodInterceptor, AutoCloseabl
             if (lastEndTs.get() == 0) {
                 long time = System.currentTimeMillis() - lastStartTs.get();
 
-                return ("(running for " + TimeUtil.millisToDurationPrintable(time) + ")");
+                return "(running for " + TimeUtil.millisToDurationPrintable(time) + ")";
             }
 
             return Objects.toString(lastResult.get());
@@ -162,7 +163,7 @@ public class MonitoredTaskInterceptor implements MethodInterceptor, AutoCloseabl
 
     /** {@inheritDoc} */
     @Override public Object invoke(MethodInvocation invocation) throws Throwable {
-        if(init.compareAndSet(false,true))
+        if (init.compareAndSet(false, true))
             initLogging();
 
         final long startTs = System.currentTimeMillis();
@@ -200,17 +201,7 @@ public class MonitoredTaskInterceptor implements MethodInterceptor, AutoCloseabl
             return;
 
         try {
-            StringBuilder sb = new StringBuilder();
-            sb.append(str);
-
-            if (duration > 1) {
-                sb.append(", duration: ");
-                sb.append(TimeUtil.millisToDurationPrintable(duration));
-            }
-
-            sb.append(String.format("%n"));
-
-            fileWriter.write(sb.toString());
+            fileWriter.write(str + durationSuffix(duration) + System.lineSeparator());
             fileWriter.flush();
         }
         catch (IOException e) {
@@ -218,6 +209,10 @@ public class MonitoredTaskInterceptor implements MethodInterceptor, AutoCloseabl
         }
     }
 
+    private static String durationSuffix(long duration) {
+        return duration > 1 ? ", duration: " + TimeUtil.millisToDurationPrintable(duration) : "";
+    }
+
     private static class TaskSettings {
         private final String name;
         private final boolean log;
@@ -252,10 +247,10 @@ public class MonitoredTaskInterceptor implements MethodInterceptor, AutoCloseabl
             if (arguments != null && idx >= 0 && idx < arguments.length)
                 fullKey.append(".").append(arguments[idx]);
 
-            int[] ints = annotation.nameExtArgsIndexes();
+            int[] argIndexes = annotation.nameExtArgsIndexes();
 
-            for (int i = 0; i < ints.length; i++) {
-                int argIdx = ints[i];
+            for (int i = 0; i < argIndexes.length; i++) {
+                int argIdx = argIndexes[i];
                 if (arguments != null && argIdx >= 0 && argIdx < arguments.length) {
                     if (i == 0)
                         fullKey.append(":");
diff --git a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/MonitoredTaskInterceptorModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/MonitoredTaskInterceptorModule.java
similarity index 91%
rename from tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/MonitoredTaskInterceptorModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/MonitoredTaskInterceptorModule.java
index 10cd706c..3730dbec 100644
--- a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/interceptor/MonitoredTaskInterceptorModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/common/interceptor/MonitoredTaskInterceptorModule.java
@@ -18,6 +18,7 @@ package org.apache.ignite.tcbot.common.interceptor;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.matcher.Matchers;
+import org.apache.ignite.tcbot.common.monitoring.MonitoredTasks;
 
 public class MonitoredTaskInterceptorModule extends AbstractModule {
     @Override protected void configure() {
@@ -32,6 +33,7 @@ public class MonitoredTaskInterceptorModule extends AbstractModule {
             profilingInterceptor);
 
         bind(MonitoredTaskInterceptor.class).toInstance(profilingInterceptor);
+        bind(MonitoredTasks.class).toInstance(profilingInterceptor);
     }
 
 }
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/TcBotEngineModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/engine/TcBotEngineModule.java
similarity index 77%
rename from tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/TcBotEngineModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/engine/TcBotEngineModule.java
index a36e5ec8..c8eaf438 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/TcBotEngineModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/engine/TcBotEngineModule.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.tcbot.engine;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 import org.apache.ignite.tcbot.common.TcBotCommonModule;
 import org.apache.ignite.tcbot.engine.board.BoardService;
 import org.apache.ignite.tcbot.engine.boardmute.MutedIssuesDao;
@@ -39,20 +39,20 @@ import org.apache.ignite.tcbot.engine.user.UserAndSessionsStorage;
 public class TcBotEngineModule extends AbstractModule {
     /** {@inheritDoc} */
     @Override protected void configure() {
-        bind(BuildChainProcessor.class).in(new SingletonScope());
-        bind(IDetailedStatusForTrackedBranch.class).to(TrackedBranchChainsProcessor.class).in(new SingletonScope());
-        bind(SingleBuildResultsService.class).in(new SingletonScope());
+        bind(BuildChainProcessor.class).in(Scopes.SINGLETON);
+        bind(IDetailedStatusForTrackedBranch.class).to(TrackedBranchChainsProcessor.class).in(Scopes.SINGLETON);
+        bind(SingleBuildResultsService.class).in(Scopes.SINGLETON);
 
-        bind(BuildTimeService.class).in(new SingletonScope());
+        bind(BuildTimeService.class).in(Scopes.SINGLETON);
 
-        bind(IIssuesStorage.class).to(IssuesStorage.class).in(new SingletonScope());
+        bind(IIssuesStorage.class).to(IssuesStorage.class).in(Scopes.SINGLETON);
 
-        bind(BoardService.class).in(new SingletonScope());
+        bind(BoardService.class).in(Scopes.SINGLETON);
 
-        bind(IUserStorage.class).to(UserAndSessionsStorage.class).in(new SingletonScope());
+        bind(IUserStorage.class).to(UserAndSessionsStorage.class).in(Scopes.SINGLETON);
 
-        bind(MutedIssuesDao.class).in(new SingletonScope());
-        bind(NewTestsStorage.class).in(new SingletonScope());
+        bind(MutedIssuesDao.class).in(Scopes.SINGLETON);
+        bind(NewTestsStorage.class).in(Scopes.SINGLETON);
 
         install(new TcBotCommonModule());
     }
diff --git a/tcbot-notify/src/main/java/org/apache/ignite/tcbot/notify/TcBotNotificationsModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/notify/TcBotNotificationsModule.java
similarity index 83%
rename from tcbot-notify/src/main/java/org/apache/ignite/tcbot/notify/TcBotNotificationsModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/notify/TcBotNotificationsModule.java
index ae8f7dc8..98fb07de 100644
--- a/tcbot-notify/src/main/java/org/apache/ignite/tcbot/notify/TcBotNotificationsModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/notify/TcBotNotificationsModule.java
@@ -17,7 +17,7 @@
 package org.apache.ignite.tcbot.notify;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 
 /**
  *
@@ -25,7 +25,7 @@ import com.google.inject.internal.SingletonScope;
 public class TcBotNotificationsModule extends AbstractModule {
     /** {@inheritDoc} */
     @Override protected void configure() {
-        bind(IEmailSender.class).to(EmailSender.class).in(new SingletonScope());
-        bind(ISlackSender.class).to(SlackSender.class).in(new SingletonScope());
+        bind(IEmailSender.class).to(EmailSender.class).in(Scopes.SINGLETON);
+        bind(ISlackSender.class).to(SlackSender.class).in(Scopes.SINGLETON);
     }
 }
diff --git a/tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/TcBotPersistenceModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/persistence/TcBotPersistenceModule.java
similarity index 76%
copy from tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/TcBotPersistenceModule.java
copy to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/persistence/TcBotPersistenceModule.java
index 38eca98f..598707fb 100644
--- a/tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/TcBotPersistenceModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/persistence/TcBotPersistenceModule.java
@@ -18,14 +18,15 @@
 package org.apache.ignite.tcbot.persistence;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+import org.apache.ignite.Ignite;
 
 public class TcBotPersistenceModule extends AbstractModule {
-    @Override
-    protected void configure() {
-        super.configure();
-
-
-        bind(IStringCompactor.class).to(IgniteStringCompactor.class).in(new SingletonScope());
+    @Provides
+    @Singleton
+    IStringCompactor stringCompactor(Provider<Ignite> igniteProvider) {
+        return new IgniteStringCompactor(igniteProvider::get);
     }
 }
diff --git a/tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/scheduler/SchedulerModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/persistence/scheduler/SchedulerModule.java
similarity index 88%
rename from tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/scheduler/SchedulerModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/persistence/scheduler/SchedulerModule.java
index 2cd2ea72..bc792ab2 100644
--- a/tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/scheduler/SchedulerModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcbot/persistence/scheduler/SchedulerModule.java
@@ -18,11 +18,11 @@
 package org.apache.ignite.tcbot.persistence.scheduler;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 
 public class SchedulerModule extends AbstractModule {
     /** {@inheritDoc} */
     @Override protected void configure() {
-        bind(IScheduler.class).to(TcBotScheduler.class).in(new SingletonScope());
+        bind(IScheduler.class).to(TcBotScheduler.class).in(Scopes.SINGLETON);
     }
 }
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedModule.java
similarity index 72%
rename from tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedModule.java
index 273c00fb..9741651c 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedModule.java
@@ -17,7 +17,7 @@
 package org.apache.ignite.tcignited;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildConditionDao;
 import org.apache.ignite.tcignited.build.UpdateCountersStorage;
 import org.apache.ignite.tcignited.buildlog.BuildLogCheckResultDao;
@@ -53,25 +53,25 @@ public class TeamcityIgnitedModule extends AbstractModule {
 
     /** {@inheritDoc} */
     @Override protected void configure() {
-        bind(ITeamcityIgnitedProvider.class).to(TcIgnitedCachingProvider.class).in(new SingletonScope());
-        bind(BuildRefDao.class).in(new SingletonScope());
-        bind(BuildRefSync.class).in(new SingletonScope());
-        bind(BuildConditionDao.class).in(new SingletonScope());
-        bind(FatBuildDao.class).in(new SingletonScope());
-        bind(ProactiveFatBuildSync.class).in(new SingletonScope());
-        bind(ChangeSync.class).in(new SingletonScope());
-        bind(ChangeDao.class).in(new SingletonScope());
-        bind(BuildTypeRefDao.class).in(new SingletonScope());
-        bind(BuildTypeDao.class).in(new SingletonScope());
-        bind(BuildTypeSync.class).in(new SingletonScope());
-        bind(BuildStartTimeStorage.class).in(new SingletonScope());
-        bind(MuteDao.class).in(new SingletonScope());
-        bind(MuteSync.class).in(new SingletonScope());
-        bind(BuildLogCheckResultDao.class).in(new SingletonScope());
-        bind(SuiteInvocationHistoryDao.class).in(new SingletonScope());
-        bind(HistoryCollector.class).in(new SingletonScope());
-        bind(ILogProductSpecific.class).to(LogIgniteSpecific.class).in(new SingletonScope());
-        bind(UpdateCountersStorage.class).in(new SingletonScope());
+        bind(ITeamcityIgnitedProvider.class).to(TcIgnitedCachingProvider.class).in(Scopes.SINGLETON);
+        bind(BuildRefDao.class).in(Scopes.SINGLETON);
+        bind(BuildRefSync.class).in(Scopes.SINGLETON);
+        bind(BuildConditionDao.class).in(Scopes.SINGLETON);
+        bind(FatBuildDao.class).in(Scopes.SINGLETON);
+        bind(ProactiveFatBuildSync.class).in(Scopes.SINGLETON);
+        bind(ChangeSync.class).in(Scopes.SINGLETON);
+        bind(ChangeDao.class).in(Scopes.SINGLETON);
+        bind(BuildTypeRefDao.class).in(Scopes.SINGLETON);
+        bind(BuildTypeDao.class).in(Scopes.SINGLETON);
+        bind(BuildTypeSync.class).in(Scopes.SINGLETON);
+        bind(BuildStartTimeStorage.class).in(Scopes.SINGLETON);
+        bind(MuteDao.class).in(Scopes.SINGLETON);
+        bind(MuteSync.class).in(Scopes.SINGLETON);
+        bind(BuildLogCheckResultDao.class).in(Scopes.SINGLETON);
+        bind(SuiteInvocationHistoryDao.class).in(Scopes.SINGLETON);
+        bind(HistoryCollector.class).in(Scopes.SINGLETON);
+        bind(ILogProductSpecific.class).to(LogIgniteSpecific.class).in(Scopes.SINGLETON);
+        bind(UpdateCountersStorage.class).in(Scopes.SINGLETON);
 
         TcRealConnectionModule module = new TcRealConnectionModule();
         if (conn != null)
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessorModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessorModule.java
similarity index 93%
rename from tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessorModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessorModule.java
index aa0f5baf..71d44938 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessorModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessorModule.java
@@ -17,11 +17,11 @@
 package org.apache.ignite.tcignited.buildlog;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 
 public class BuildLogProcessorModule extends AbstractModule {
     @Override
     protected void configure() {
-        bind(IBuildLogProcessor.class).to(BuildLogProcessor.class).in(new SingletonScope());
+        bind(IBuildLogProcessor.class).to(BuildLogProcessor.class).in(Scopes.SINGLETON);
     }
 }
diff --git a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/TcRealConnectionModule.java b/tcbot-app-guice/src/main/java/org/apache/ignite/tcservice/TcRealConnectionModule.java
similarity index 90%
rename from tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/TcRealConnectionModule.java
rename to tcbot-app-guice/src/main/java/org/apache/ignite/tcservice/TcRealConnectionModule.java
index 55753304..5955c7e0 100644
--- a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/TcRealConnectionModule.java
+++ b/tcbot-app-guice/src/main/java/org/apache/ignite/tcservice/TcRealConnectionModule.java
@@ -17,7 +17,7 @@
 package org.apache.ignite.tcservice;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
+import com.google.inject.Scopes;
 import org.apache.ignite.tcservice.http.ITeamcityHttpConnection;
 import org.apache.ignite.tcservice.http.TeamcityRecorder;
 import org.apache.ignite.tcservice.http.TeamcityRecordingConnection;
@@ -37,8 +37,8 @@ public class TcRealConnectionModule extends AbstractModule {
         else
             bind(ITeamcityHttpConnection.class).to(TeamcityRecordingConnection.class);
 
-        bind(TeamcityRecorder.class).in(new SingletonScope());
-        bind(ITcLogin.class).to(TcLoginImpl.class).in(new SingletonScope());
+        bind(TeamcityRecorder.class).in(Scopes.SINGLETON);
+        bind(ITcLogin.class).to(TcLoginImpl.class).in(Scopes.SINGLETON);
     }
 
     public void overrideHttp(ITeamcityHttpConnection conn) {
diff --git a/tcbot-app-guice/src/main/resources/META-INF/services/org.apache.ignite.tcbot.common.application.TcBotApplicationContextFactory b/tcbot-app-guice/src/main/resources/META-INF/services/org.apache.ignite.tcbot.common.application.TcBotApplicationContextFactory
new file mode 100644
index 00000000..b30cf755
--- /dev/null
+++ b/tcbot-app-guice/src/main/resources/META-INF/services/org.apache.ignite.tcbot.common.application.TcBotApplicationContextFactory
@@ -0,0 +1 @@
+org.apache.ignite.tcbot.app.guice.GuiceTcBotApplicationContextFactory
diff --git a/tcbot-common/build.gradle b/tcbot-common/build.gradle
index 570cc131..64eb95c5 100644
--- a/tcbot-common/build.gradle
+++ b/tcbot-common/build.gradle
@@ -18,23 +18,14 @@
 apply plugin: 'java'
 
 dependencies {
-    api group: 'com.google.guava', name: 'guava', version: guavaVer
+    api "com.google.guava:guava:$guavaVer"
 
-    api group: 'org.slf4j', name: 'slf4j-api', version: slf4jVer
-    //Apache License Version 2.0
-    api group: 'com.google.code.gson', name: 'gson', version: gsonVer
+    api "org.slf4j:slf4j-api:$slf4jVer"
+    api "com.google.code.findbugs:jsr305:$jsr305Ver"
+    api "org.checkerframework:checker-qual:$checkerQualVer"
 
-    api group: 'javax.inject', name: 'javax.inject', version: '1'
-    api group: 'com.google.inject', name: 'guice', version: guiceVer
-    api group: 'com.google.code.findbugs', name: 'jsr305', version: jsr305Ver
-    api group: 'org.checkerframework', name: 'checker-qual', version: checkerQualVer
-
-    api group: 'org.xerial.snappy', name: 'snappy-java', version: snappyVer
-
-    api group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1'
-    api group: 'com.sun.xml.bind', name: 'jaxb-impl', version: jaxbVer
-    api group: 'com.sun.xml.bind', name: 'jaxb-core', version: '2.3.0'
+    implementation 'javax.xml.bind:jaxb-api:2.3.1'
     
-    testImplementation group: 'junit', name: 'junit', version: junitVer;
-    testImplementation group: 'org.mockito', name: 'mockito-core', version: mockitoVer;
+    testImplementation "junit:junit:$junitVer";
+    testImplementation "org.mockito:mockito-core:$mockitoVer";
 }
diff --git a/tcbot-notify/build.gradle b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/application/TcBotApplicationContext.java
similarity index 78%
copy from tcbot-notify/build.gradle
copy to tcbot-common/src/main/java/org/apache/ignite/tcbot/common/application/TcBotApplicationContext.java
index f4464588..7d5722a3 100644
--- a/tcbot-notify/build.gradle
+++ b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/application/TcBotApplicationContext.java
@@ -15,12 +15,14 @@
  * limitations under the License.
  */
 
-apply plugin: 'java'
+package org.apache.ignite.tcbot.common.application;
 
-dependencies {
-    api project(":tcbot-common")
+public interface TcBotApplicationContext extends AutoCloseable {
+    void start();
 
-    api group: 'com.sun.mail', name: 'javax.mail', version: mailVer
+    boolean isReady();
 
-    api group: 'com.ullink.slack', name: 'simpleslackapi', version: '1.4.0'
+    <T> T getInstance(Class<T> type);
+
+    @Override void close();
 }
diff --git a/tcbot-jira-ignited/build.gradle b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/application/TcBotApplicationContextFactory.java
similarity index 85%
copy from tcbot-jira-ignited/build.gradle
copy to tcbot-common/src/main/java/org/apache/ignite/tcbot/common/application/TcBotApplicationContextFactory.java
index bb41aa53..4fb55620 100644
--- a/tcbot-jira-ignited/build.gradle
+++ b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/application/TcBotApplicationContextFactory.java
@@ -15,10 +15,8 @@
  * limitations under the License.
  */
 
-apply plugin: 'java'
+package org.apache.ignite.tcbot.common.application;
 
-dependencies {
-    api project(":tcbot-jira")
-    api project(":tcbot-persistence")
+public interface TcBotApplicationContextFactory {
+    TcBotApplicationContext create();
 }
-
diff --git a/tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/TcBotPersistenceModule.java b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/application/TcBotApplicationContexts.java
similarity index 63%
rename from tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/TcBotPersistenceModule.java
rename to tcbot-common/src/main/java/org/apache/ignite/tcbot/common/application/TcBotApplicationContexts.java
index 38eca98f..f4d0036d 100644
--- a/tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/TcBotPersistenceModule.java
+++ b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/application/TcBotApplicationContexts.java
@@ -15,17 +15,19 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.tcbot.persistence;
+package org.apache.ignite.tcbot.common.application;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.internal.SingletonScope;
-
-public class TcBotPersistenceModule extends AbstractModule {
-    @Override
-    protected void configure() {
-        super.configure();
+import java.util.ServiceLoader;
 
+public final class TcBotApplicationContexts {
+    private TcBotApplicationContexts() {
+        // No-op.
+    }
 
-        bind(IStringCompactor.class).to(IgniteStringCompactor.class).in(new SingletonScope());
+    public static TcBotApplicationContext create() {
+        return ServiceLoader.load(TcBotApplicationContextFactory.class)
+            .findFirst()
+            .orElseThrow(() -> new IllegalStateException("No TC Bot application context factory found"))
+            .create();
     }
 }
diff --git a/tcbot-persistence/build.gradle b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/monitoring/MonitoredTasks.java
similarity index 64%
copy from tcbot-persistence/build.gradle
copy to tcbot-common/src/main/java/org/apache/ignite/tcbot/common/monitoring/MonitoredTasks.java
index baa488d3..9ac8df5a 100644
--- a/tcbot-persistence/build.gradle
+++ b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/monitoring/MonitoredTasks.java
@@ -15,20 +15,30 @@
  * limitations under the License.
  */
 
-apply plugin: 'java'
+package org.apache.ignite.tcbot.common.monitoring;
 
-repositories {
-    mavenCentral()
-    mavenLocal()
-}
+import java.util.Collection;
 
-dependencies {
-    api project(":tcbot-common")
+public interface MonitoredTasks extends AutoCloseable {
+    Collection<? extends Invocation> getList();
 
-    api (group: 'org.apache.ignite', name: 'ignite-core', version: ignVer) {
-        exclude group: 'org.jetbrains'
-    }
+    long startedTs();
 
-    api "org.apache.ignite:ignite-indexing:$ignVer"
-}
+    @Override void close() throws Exception;
+
+    interface Invocation {
+        String name();
+
+        int count();
+
+        long startTs();
 
+        long endTs();
+
+        String start();
+
+        String end();
+
+        String result();
+    }
+}
diff --git a/tcbot-persistence/build.gradle b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/monitoring/ProfilingMonitor.java
similarity index 73%
copy from tcbot-persistence/build.gradle
copy to tcbot-common/src/main/java/org/apache/ignite/tcbot/common/monitoring/ProfilingMonitor.java
index baa488d3..65616c98 100644
--- a/tcbot-persistence/build.gradle
+++ b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/monitoring/ProfilingMonitor.java
@@ -15,20 +15,20 @@
  * limitations under the License.
  */
 
-apply plugin: 'java'
+package org.apache.ignite.tcbot.common.monitoring;
 
-repositories {
-    mavenCentral()
-    mavenLocal()
-}
+import java.util.Collection;
 
-dependencies {
-    api project(":tcbot-common")
+public interface ProfilingMonitor {
+    void reset();
 
-    api (group: 'org.apache.ignite', name: 'ignite-core', version: ignVer) {
-        exclude group: 'org.jetbrains'
-    }
+    Collection<? extends Invocation> getInvocations();
 
-    api "org.apache.ignite:ignite-indexing:$ignVer"
-}
+    interface Invocation {
+        long getNanos();
 
+        int getCount();
+
+        String getName();
+    }
+}
diff --git a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/CryptUtil.java b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/CryptUtil.java
index b56f44d3..92427c47 100644
--- a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/CryptUtil.java
+++ b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/CryptUtil.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.tcbot.common.util;
 
-import com.google.common.base.Throwables;
-
 import javax.annotation.Nonnull;
 import javax.crypto.*;
 import javax.crypto.spec.SecretKeySpec;
@@ -40,7 +38,7 @@ public class CryptUtil {
 
             return  sha256_HMAC.doFinal(data.getBytes(CHARSET));
         } catch (NoSuchAlgorithmException | InvalidKeyException e) {
-            throw Throwables.propagate(e);
+            throw new RuntimeException(e);
         }
     }
 
@@ -51,7 +49,7 @@ public class CryptUtil {
             return cipher.doFinal(data);
         }
         catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
-            throw Throwables.propagate(e);
+            throw new RuntimeException(e);
         }
     }
 
@@ -62,7 +60,7 @@ public class CryptUtil {
             return cipher.doFinal(data);
         }
         catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
-            throw Throwables.propagate(e);
+            throw new RuntimeException(e);
         }
     }
 
diff --git a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/HttpUtil.java b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/HttpUtil.java
index 837b1ba2..27435147 100644
--- a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/HttpUtil.java
+++ b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/HttpUtil.java
@@ -37,6 +37,7 @@ import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 import org.apache.ignite.tcbot.common.exeption.ServiceUnauthorizedException;
 import org.apache.ignite.tcbot.common.exeption.ServiceBadRequestException;
@@ -53,6 +54,7 @@ import javax.annotation.Nullable;
 public class HttpUtil {
     /** Logger. */
     private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class);
+    private static final int TIMEOUT_MS = 60_000;
 
     /**
      * @param inputStream Input stream.
@@ -61,16 +63,9 @@ public class HttpUtil {
         if (inputStream == null)
             return "<null>";
 
-        BufferedReader in = new BufferedReader(
-            new InputStreamReader(inputStream));
-        String inputLine;
-        StringBuilder res = new StringBuilder();
-
-        while ((inputLine = in.readLine()) != null) {
-            res.append(inputLine);
-            res.append("\n");
+        try (BufferedReader in = new BufferedReader(new InputStreamReader(inputStream))) {
+            return in.lines().collect(Collectors.joining("\n", "", "\n"));
         }
-        return res.toString();
     }
 
     /**
@@ -88,13 +83,12 @@ public class HttpUtil {
         final Stopwatch started = Stopwatch.createStarted();
         URL obj = new URL(url);
         HttpURLConnection con = (HttpURLConnection)obj.openConnection();
-        con.setConnectTimeout(60000); //todo make configurable
-        con.setReadTimeout(60000);
+        con.setConnectTimeout(TIMEOUT_MS);
+        con.setReadTimeout(TIMEOUT_MS);
 
         con.setRequestProperty("Authorization", "Basic " + basicAuthTok);
-        con.setRequestProperty("Connection", "Keep-Alive");
-        con.setRequestProperty("Keep-Alive", "header");
-        con.setRequestProperty("accept-charset", StandardCharsets.UTF_8.toString());
+        useKeepAlive(con);
+        acceptUtf8(con);
 
         int resCode;
 
@@ -128,19 +122,14 @@ public class HttpUtil {
         if (githubAuthTok != null)
             con.setRequestProperty("Authorization", "token " + githubAuthTok);
 
-        con.setRequestProperty("accept-charset", StandardCharsets.UTF_8.toString());
-        con.setRequestProperty("Connection", "Keep-Alive");
-        con.setRequestProperty("Keep-Alive", "header");
+        acceptUtf8(con);
+        useKeepAlive(con);
 
         int resCode = con.getResponseCode();
 
-        if(rspHeaders != null) {
-            rspHeaders.keySet().forEach((k) -> {
-                String link = con.getHeaderField(k);
+        if (rspHeaders != null)
+            rspHeaders.keySet().forEach(k -> rspHeaders.put(k, con.getHeaderField(k)));
 
-                rspHeaders.put(k, link);
-            });
-        }
         logger.info(Thread.currentThread().getName() + ": Required: " + started.elapsed(TimeUnit.MILLISECONDS)
             + "ms : Sending 'GET' request to : " + url + " Response: " + resCode);
 
@@ -176,11 +165,10 @@ public class HttpUtil {
 
         con.setRequestMethod("POST");
         con.setRequestProperty("Authorization", "Basic " + tok);
-        con.setRequestProperty("Connection", "Keep-Alive");
-        con.setRequestProperty("Keep-Alive", "header");
+        useKeepAlive(con);
         Charset charset = StandardCharsets.UTF_8;
 
-        con.setRequestProperty("accept-charset", charset.toString());
+        acceptUtf8(con);
         con.setRequestProperty("content-type", "application/xml");
 
         con.setDoOutput(true);
@@ -329,41 +317,6 @@ public class HttpUtil {
         }
     }
 
-    /**
-     * Send POST request to the GitHub url.
-     *
-     * @param githubAuthTok Authorization token.
-     * @param url URL.
-     * @param body Request POST params.
-     * @return Response body from given url.
-     * @throws IOException If failed.
-     */
-    public static String sendPostAsStringToGit(String githubAuthTok, String url, String body) throws IOException {
-        URL obj = new URL(url);
-        HttpURLConnection con = (HttpURLConnection)obj.openConnection();
-        Charset charset = StandardCharsets.UTF_8;
-
-        con.setRequestProperty("accept-charset", charset.toString());
-        con.setRequestProperty("Authorization", "token " + githubAuthTok);
-        con.setRequestProperty("Connection", "Keep-Alive");
-        con.setRequestProperty("Keep-Alive", "header");
-        con.setRequestProperty("content-type", "application/json");
-
-        con.setRequestMethod("POST");
-
-        con.setDoOutput(true);
-
-        try (OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), charset)){
-            writer.write(body); // Write POST query string (if any needed).
-        }
-
-        logger.info("\nSending 'POST' request to URL : " + url + "\n" + body);
-
-        try (InputStream inputStream = getInputStream(con, gitHubAuthDiagnostic(githubAuthTok))){
-            return readIsToString(inputStream);
-        }
-    }
-
     /**
      * Send POST request to the JIRA url.
      *
@@ -381,8 +334,7 @@ public class HttpUtil {
         con.setRequestProperty("accept-charset", charset.toString());
         con.setRequestProperty("Authorization", "Basic " + jiraAuthTok);
         con.setRequestProperty("content-type", "application/json");
-        con.setRequestProperty("Connection", "Keep-Alive");
-        con.setRequestProperty("Keep-Alive", "header");
+        useKeepAlive(con);
 
         con.setRequestMethod("POST");
 
@@ -414,8 +366,7 @@ public class HttpUtil {
         con.setRequestProperty("accept-charset", charset.toString());
         con.setRequestProperty("Authorization", "Basic " + jiraAuthTok);
         con.setRequestProperty("content-type", "application/json");
-        con.setRequestProperty("Connection", "Keep-Alive");
-        con.setRequestProperty("Keep-Alive", "header");
+        useKeepAlive(con);
 
         con.setRequestMethod("GET");
 
@@ -428,4 +379,13 @@ public class HttpUtil {
             return readIsToString(inputStream);
         }
     }
+
+    private static void useKeepAlive(HttpURLConnection con) {
+        con.setRequestProperty("Connection", "Keep-Alive");
+        con.setRequestProperty("Keep-Alive", "header");
+    }
+
+    private static void acceptUtf8(HttpURLConnection con) {
+        con.setRequestProperty("accept-charset", StandardCharsets.UTF_8.toString());
+    }
 }
diff --git a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/ObjectInterner.java b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/ObjectInterner.java
index 4d997be7..f9182cbb 100644
--- a/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/ObjectInterner.java
+++ b/tcbot-common/src/main/java/org/apache/ignite/tcbot/common/util/ObjectInterner.java
@@ -26,7 +26,6 @@ import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.util.Collection;
 import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -104,7 +103,7 @@ public class ObjectInterner {
                 if (fldVal.getClass().getPackage().getName().startsWith("org.apache.ignite.ci"))
                     compressed.addAndGet(internFields(fldVal));
                 else if (fldVal instanceof Collection) {
-                    Collection collection = (Collection)fldVal;
+                    Collection<?> collection = (Collection<?>)fldVal;
 
                     for (Object next : collection) {
                         if (next.getClass().getPackage().getName().startsWith("org.apache.ignite.ci"))
@@ -112,12 +111,9 @@ public class ObjectInterner {
                     }
                 }
                 else if(fldVal instanceof Map) {
-                    Map map = (Map)fldVal;
+                    Map<?, ?> map = (Map<?, ?>)fldVal;
 
-                    Set<Map.Entry> set = map.entrySet();
-
-                    for (Map.Entry  nextEntry : set) {
-                        Object val = nextEntry.getValue();
+                    for (Object val : map.values()) {
 
                         if (val.getClass().getPackage().getName().startsWith("org.apache.ignite.ci"))
                             compressed.addAndGet(internFields(val));
diff --git a/tcbot-engine/build.gradle b/tcbot-engine/build.gradle
index 3606f363..7f9a2981 100644
--- a/tcbot-engine/build.gradle
+++ b/tcbot-engine/build.gradle
@@ -23,7 +23,10 @@ dependencies {
     api project(":tcbot-jira-ignited")
     api project(":tcbot-notify")
 
-    testImplementation group: 'junit', name: 'junit', version: junitVer
-    testImplementation group: 'org.mockito', name: 'mockito-core', version: mockitoVer
+    implementation 'javax.inject:javax.inject:1'
+    implementation 'javax.xml.bind:jaxb-api:2.3.1'
+
+    testImplementation "junit:junit:$junitVer"
+    testImplementation "org.mockito:mockito-core:$mockitoVer"
 }
 
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/board/BoardService.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/board/BoardService.java
index 33e427a9..b4c62043 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/board/BoardService.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/board/BoardService.java
@@ -285,11 +285,7 @@ public class BoardService {
     @MonitoredTask(name = "Convert issues to defect")
     protected String issuesToDefects() {
         Stream<Issue> stream = issuesStorage.allIssues();
-
-        //todo make property how old issues can be considered as configuration parameter
         long minIssueTs = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(14);
-
-        //todo not so good to to call init() twice
         fatBuildDao.init();
         changeDao.init();
 
@@ -318,8 +314,6 @@ public class BoardService {
                 FatBuildCompacted fatBuild = fatBuildDao.getFatBuild(srvId, key.buildId);
                 if (fatBuild == null)
                     return;
-
-                //todo non test failures
                 String testName = issue.issueKey().getTestOrBuildName();
 
                 int issueTypeCid = compactor.getStringId(issue.type);
@@ -401,8 +395,6 @@ public class BoardService {
             Preconditions.checkState(admin);
         }
 
-        //todo if it is not forced resovle need to check blockers count for now
-
         int strId = compactor.getStringId(principalId);
         defect.resolvedByUsernameId(strId);
 
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/chain/MultBuildRunCtx.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/chain/MultBuildRunCtx.java
index c784065e..46c1d34e 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/chain/MultBuildRunCtx.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/chain/MultBuildRunCtx.java
@@ -279,11 +279,10 @@ public class MultBuildRunCtx implements ISuiteResults {
     }
 
     public long getJavaLevelDeadlocksCount() {
-        List<ILogCheckResult> collect = getLogChecksIfFinished().collect(Collectors.toList());
-
-        return collect.stream().map(r -> r.getCustomProblems(compactor))
-                .filter(set -> set.contains(ProblemOccurrence.JAVA_LEVEL_DEADLOCK))
-                .count();
+        return getLogChecksIfFinished()
+            .map(r -> r.getCustomProblems(compactor))
+            .filter(set -> set.contains(ProblemOccurrence.JAVA_LEVEL_DEADLOCK))
+            .count();
     }
 
     public long getCancelledBuildsCount() {
@@ -308,7 +307,6 @@ public class MultBuildRunCtx implements ISuiteResults {
             .forEach(map -> {
                 map.forEach(
                     (testName, logCheckResult) -> {
-                        //todo may be it is better to find   avg
                         long bytes = (long)logCheckResult.getLogSizeBytes();
                         if (bytes > LOG_CONSUMER_BORDER_BYTES)
                             logSizeBytes.merge(testName, bytes, Math::max);
@@ -398,10 +396,7 @@ public class MultBuildRunCtx implements ISuiteResults {
             .mapToLong(l -> l)
             .average();
 
-        if (average.isPresent())
-            return (long)average.getAsDouble();
-
-        return null;
+        return average.isPresent() ? (long)average.getAsDouble() : null;
     }
 
     /**
@@ -412,10 +407,7 @@ public class MultBuildRunCtx implements ISuiteResults {
             .mapToLong(SingleBuildRunCtx::testsDuration)
             .average();
 
-        if (average.isPresent())
-            return (long)average.getAsDouble();
-
-        return null;
+        return average.isPresent() ? (long)average.getAsDouble() : null;
     }
 
     /**
@@ -459,11 +451,11 @@ public class MultBuildRunCtx implements ISuiteResults {
     }
 
     public Integer queuedBuildCount() {
-        return queuedBuildCount == null ? Integer.valueOf(0) : queuedBuildCount;
+        return queuedBuildCount == null ? 0 : queuedBuildCount;
     }
 
     public Integer runningBuildCount() {
-        return runningBuildCount == null ? Integer.valueOf(0) : runningBuildCount;
+        return runningBuildCount == null ? 0 : runningBuildCount;
     }
 
     /**
@@ -478,10 +470,9 @@ public class MultBuildRunCtx implements ISuiteResults {
 
                 final String vcsUsername = change.vcsUsername(compactor);
 
-                if (Strings.isNullOrEmpty(tcUserFullName))
-                    return vcsUsername;
-
-                return vcsUsername + " [" + tcUserFullName + "]";
+                return Strings.isNullOrEmpty(tcUserFullName)
+                    ? vcsUsername
+                    : vcsUsername + " [" + tcUserFullName + "]";
             });
     }
 
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/pr/PrChainsProcessor.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/pr/PrChainsProcessor.java
index f47b9898..4b524dea 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/pr/PrChainsProcessor.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/pr/PrChainsProcessor.java
@@ -349,7 +349,6 @@ public class PrChainsProcessor {
      * @param tcIgnited
      * @param baseBranch
      */
-    //todo may avoid creation of UI model for simple comment.
     private List<ShortSuiteUi> findBlockerFailures(FullChainRunCtx fullChainRunCtx,
         ITeamcityIgnited tcIgnited,
         String baseBranch) {
@@ -394,7 +393,6 @@ public class PrChainsProcessor {
      * @param tcIgnited
      * @param baseBranch
      */
-    //todo may avoid creation of UI model for simple comment.
     private List<ShortSuiteNewTestsUi> findNewTests(FullChainRunCtx fullChainRunCtx,
         ITeamcityIgnited tcIgnited,
         String baseBranch) {
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/BoardDefectSummaryUi.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/BoardDefectSummaryUi.java
index 7b99cbda..6fbd1383 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/BoardDefectSummaryUi.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/BoardDefectSummaryUi.java
@@ -24,6 +24,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.function.Function;
+import java.util.function.Predicate;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -50,14 +51,17 @@ public class BoardDefectSummaryUi {
     }
 
     public Set<String> getTags() {
-        //todo bad code, make tag filter configurable.
-        return tags.stream().filter(t -> teamTagPattern.matcher(t).matches()).collect(Collectors.toSet());
+        return tags.stream()
+            .filter(t -> teamTagPattern.matcher(t).matches())
+            .collect(Collectors.toSet());
     }
 
     public List<String> getSuites() {
-        return defect.buildsInvolved().values().stream().map(
-            b -> b.build().buildTypeName()
-        ).distinct().map(compactor::getStringFromId).collect(Collectors.toList());
+        return defect.buildsInvolved().values().stream()
+            .map(b -> b.build().buildTypeName())
+            .distinct()
+            .map(compactor::getStringFromId)
+            .collect(Collectors.toList());
     }
 
     public String getSuitesSummary() {
@@ -88,7 +92,9 @@ public class BoardDefectSummaryUi {
     }
 
     public List<String> getBlameCandidates() {
-        return defect.blameCandidates().stream().map(c -> c.vcsUsername(compactor)).collect(Collectors.toList());
+        return defect.blameCandidates().stream()
+            .map(c -> c.vcsUsername(compactor))
+            .collect(Collectors.toList());
     }
 
     public String getBlameCandidateSummary() {
@@ -116,7 +122,7 @@ public class BoardDefectSummaryUi {
     }
 
     public String getTrackedBranch() {
-       return compactor.getStringFromId(defect.trackedBranchCid());
+        return compactor.getStringFromId(defect.trackedBranchCid());
     }
 
     public int getId() {
@@ -136,18 +142,22 @@ public class BoardDefectSummaryUi {
     }
 
     private Stream<BoardDefectIssueUi> issues(IssueResolveStatus... types) {
-        return issuesList.stream().filter(iss -> {
+        return issuesList.stream().filter(hasStatus(types));
+    }
+
+    private static Predicate<BoardDefectIssueUi> hasStatus(IssueResolveStatus... types) {
+        return issue -> {
             for (IssueResolveStatus type : types) {
-                if (iss.status() == type)
+                if (issue.status() == type)
                     return true;
             }
 
             return false;
-        });
+        };
     }
 
     public List<BoardDefectIssueUi> getIgnoredIssues() {
-        return issues(IssueResolveStatus.IGNORED).collect(Collectors.toList());
+        return issuesList(IssueResolveStatus.IGNORED);
     }
 
     public String getSummaryIgnoredIssues() {
@@ -159,7 +169,7 @@ public class BoardDefectSummaryUi {
     }
 
     public List<BoardDefectIssueUi> getFailingIssues() {
-        return issues(IssueResolveStatus.FAILING).collect(Collectors.toList());
+        return issuesList(IssueResolveStatus.FAILING);
     }
 
     public String getSummaryFailingIssues() {
@@ -174,9 +184,8 @@ public class BoardDefectSummaryUi {
         return forceResolveAllowed;
     }
 
-
     public List<BoardDefectIssueUi> getFixedIssues() {
-        return issues(IssueResolveStatus.FIXED).collect(Collectors.toList());
+        return issuesList(IssueResolveStatus.FIXED);
     }
 
     public String getSummaryFixedIssues() {
@@ -188,7 +197,7 @@ public class BoardDefectSummaryUi {
     }
 
     public List<BoardDefectIssueUi> getUnclearIssues() {
-        return issues(IssueResolveStatus.UNKNOWN).collect(Collectors.toList());
+        return issuesList(IssueResolveStatus.UNKNOWN);
     }
 
     public String getSummaryUnclearIssues() {
@@ -206,4 +215,8 @@ public class BoardDefectSummaryUi {
     public void setForceResolveAllowed(boolean admin) {
         this.forceResolveAllowed = admin;
     }
+
+    private List<BoardDefectIssueUi> issuesList(IssueResolveStatus status) {
+        return issues(status).collect(Collectors.toList());
+    }
 }
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsChainUi.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsChainUi.java
index 165e97da..6dcfbbe7 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsChainUi.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsChainUi.java
@@ -285,7 +285,7 @@ public class DsChainUi {
 
                 DsTestFailureUi failure = createOccurForLogConsumer(testLogConsuming);
 
-                failure.name = "[" + suite.suiteName() + "] " + failure.name; //todo suite as be separate field
+                failure.name = "[" + suite.suiteName() + "] " + failure.name;
 
                 logConsumers.add(failure);
             }
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsSuiteUi.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsSuiteUi.java
index 772b0156..ca22175f 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsSuiteUi.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsSuiteUi.java
@@ -178,67 +178,47 @@ public class DsSuiteUi extends ShortSuiteUi {
         webToHist = buildWebLinkToHist(tcIgnited, suite, suite.branchName());
         webToHistBaseBranch = buildWebLinkToHist(tcIgnited, suite, baseBranch);
 
-        if (true) {
-            List<TestCompactedMult> tests = suite.getFilteredTests(test ->
-                test.hasLongRunningTest(maxDurationSec)
-                    || test.includeIntoReport(tcIgnited, baseBranchId, showMuted, showIgnored));
-
-            Function<TestCompactedMult, Float> function = testCompactedMult -> {
-                IRunHistory res = testCompactedMult.history(tcIgnited, baseBranchId);
-
-                return res == null ? 0f : res.getFailRate();
-            };
-
-            tests.sort(Comparator.comparing(function).reversed());
-
-            tests.stream()
-                .map(occurrence -> new DsTestFailureUi()
-                    .initFromOccurrence(occurrence,
-                        tcIgnited,
-                        suite.projectId(),
-                        suite.branchName(),
-                        baseBranch,
-                        baseBranchId,
-                        curBranchId,
-                        requireParamVal))
-                .forEach(testFailureUi -> testFailures.add(testFailureUi));
-
-            suite.getTopLongRunning().forEach(occurrence -> {
-                if (occurrence.getAvgDurationMs() > TimeUnit.SECONDS.toMillis(15)) {
-                    final DsTestFailureUi failure = createOrrucForLongRun(tcIgnited, compactor, suite, occurrence, baseBranch, requireParamVal);
-
-                    topLongRunning.add(failure);
-                }
-            });
-
-            suite.getCriticalFailLastStartedTest().forEach(
-                lastTest -> {
-                    final DsTestFailureUi failure = new DsTestFailureUi();
-                    failure.name = lastTest + " (last started)";
-                    testFailures.add(failure);
-                }
-            );
-
-            suite.getLogsCheckResults().forEach(map -> {
-                    map.forEach(
-                        (testName, logCheckResult) -> {
-                            if (logCheckResult.hasWarns())
-                                this.findFailureAndAddWarning(testName, logCheckResult);
-                        }
-                    );
-                }
-            );
-
-            suite.getTopLogConsumers().forEach(
-                (entry) -> logConsumers.add(createOccurForLogConsumer(entry))
-            );
-
-
-            totalTests = suite.totalTests();
-
-            if(calcTrustedTests)
-                trustedTests = suite.trustedTests(tcIgnited, baseBranchId);
-        }
+        List<TestCompactedMult> tests = suite.getFilteredTests(test ->
+            test.hasLongRunningTest(maxDurationSec)
+                || test.includeIntoReport(tcIgnited, baseBranchId, showMuted, showIgnored));
+
+        tests.sort(Comparator.comparing(failRate(tcIgnited, baseBranchId)).reversed());
+
+        tests.stream()
+            .map(occurrence -> new DsTestFailureUi()
+                .initFromOccurrence(occurrence,
+                    tcIgnited,
+                    suite.projectId(),
+                    suite.branchName(),
+                    baseBranch,
+                    baseBranchId,
+                    curBranchId,
+                    requireParamVal))
+            .forEach(testFailures::add);
+
+        suite.getTopLongRunning().forEach(occurrence -> {
+            if (occurrence.getAvgDurationMs() > TimeUnit.SECONDS.toMillis(15))
+                topLongRunning.add(createOrrucForLongRun(tcIgnited, compactor, suite, occurrence, baseBranch, requireParamVal));
+        });
+
+        suite.getCriticalFailLastStartedTest().forEach(lastTest -> {
+            DsTestFailureUi failure = new DsTestFailureUi();
+            failure.name = lastTest + " (last started)";
+            testFailures.add(failure);
+        });
+
+        suite.getLogsCheckResults().forEach(map ->
+            map.forEach((testName, logCheckResult) -> {
+                if (logCheckResult.hasWarns())
+                    findFailureAndAddWarning(testName, logCheckResult);
+            }));
+
+        suite.getTopLogConsumers().forEach(entry -> logConsumers.add(createOccurForLogConsumer(entry)));
+
+        totalTests = suite.totalTests();
+
+        if (calcTrustedTests)
+            trustedTests = suite.trustedTests(tcIgnited, baseBranchId);
 
         suite.getBuildsWithThreadDump().forEach(buildId -> {
             webUrlThreadDump = "/rest/" + GetBuildLog.GET_BUILD_LOG + "/" + GetBuildLog.THREAD_DUMP
@@ -301,6 +281,14 @@ public class DsSuiteUi extends ShortSuiteUi {
         return statInBaseBranch;
     }
 
+    private static Function<TestCompactedMult, Float> failRate(ITeamcityIgnited tcIgnited, Integer baseBranchId) {
+        return test -> {
+            IRunHistory history = test.history(tcIgnited, baseBranchId);
+
+            return history == null ? 0f : history.getFailRate();
+        };
+    }
+
     @Nonnull
     public static DsTestFailureUi createOccurForLogConsumer(Map.Entry<String, Long> entry) {
         DsTestFailureUi failure = new DsTestFailureUi();
@@ -325,16 +313,14 @@ public class DsSuiteUi extends ShortSuiteUi {
 
     public void findFailureAndAddWarning(String testName, ITestLogCheckResult logCheckRes) {
         DsTestFailureUi failure = testFailures.stream().filter(f -> f.name.contains(testName)).findAny().orElseGet(
-            () -> {
-                return warnOnly.stream().filter(f -> f.name.contains(testName)).findAny().orElseGet(
-                    () -> {
-                        DsTestFailureUi f = new DsTestFailureUi();
-                        f.name = testName + " (warning)";
-                        warnOnly.add(f);
-
-                        return f;
-                    });
-            });
+            () -> warnOnly.stream().filter(f -> f.name.contains(testName)).findAny().orElseGet(
+                () -> {
+                    DsTestFailureUi f = new DsTestFailureUi();
+                    f.name = testName + " (warning)";
+                    warnOnly.add(f);
+
+                    return f;
+                }));
 
         failure.warnings.addAll(logCheckRes.getWarns());
     }
diff --git a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsTestFailureUi.java b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsTestFailureUi.java
index 9f85413e..e944fc0f 100644
--- a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsTestFailureUi.java
+++ b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsTestFailureUi.java
@@ -109,7 +109,6 @@ public class DsTestFailureUi extends ShortTestFailureUi {
             .map(ITest::getDetailsText)
             .filter(Objects::nonNull)
             .forEach(details -> {
-                //todo check integration with JIRA
                 if (webIssueUrl == null)
                     checkAndFillByPrefix(details, "https://issues.apache.org/jira/browse/");
 
@@ -117,7 +116,7 @@ public class DsTestFailureUi extends ShortTestFailureUi {
                     checkAndFillByPrefix(details, "http://issues.apache.org/jira/browse/");
 
                 for (String s : details.split("\n")) {
-                    if (LogMsgToWarn.needWarn(s))
+                    if (LogMsgToWarn.isWarningLine(s))
                         warnings.add(s);
                 }
             });
diff --git a/tcbot-github-ignited/build.gradle b/tcbot-github-ignited/build.gradle
index bc131e9b..e23b1a1f 100644
--- a/tcbot-github-ignited/build.gradle
+++ b/tcbot-github-ignited/build.gradle
@@ -20,5 +20,7 @@ apply plugin: 'java'
 dependencies {
     api project(":tcbot-github")
     api project(":tcbot-persistence")
+
+    implementation 'javax.inject:javax.inject:1'
 }
 
diff --git a/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/GitHubConnIgnitedImpl.java b/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/GitHubConnIgnitedImpl.java
index 14b2b3e3..96fabd81 100644
--- a/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/GitHubConnIgnitedImpl.java
+++ b/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/GitHubConnIgnitedImpl.java
@@ -99,11 +99,6 @@ class GitHubConnIgnitedImpl implements IGitHubConnIgnited {
         return prCache.get(prNumberToCacheKey(prNum));
     }
 
-    /** {@inheritDoc} */
-    @Override public void notifyGit(String url, String body) {
-        conn.notifyGit(url, body);
-    }
-
     /** {@inheritDoc} */
     @Override public String gitBranchPrefix() {
         return config().gitBranchPrefix();
diff --git a/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/GitHubIgnitedProvImpl.java b/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/GitHubIgnitedProvImpl.java
index 99e8a2d9..d1708839 100644
--- a/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/GitHubIgnitedProvImpl.java
+++ b/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/GitHubIgnitedProvImpl.java
@@ -16,12 +16,13 @@
  */
 package org.apache.ignite.githubignited;
 
+import java.time.Duration;
+
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 import javax.inject.Inject;
 import javax.inject.Provider;
 import org.apache.ignite.githubservice.IGitHubConnection;
@@ -35,7 +36,7 @@ class GitHubIgnitedProvImpl implements IGitHubConnIgnitedProvider {
     private final Cache<String, IGitHubConnIgnited> srvs
         = CacheBuilder.newBuilder()
         .maximumSize(100)
-        .expireAfterAccess(60, TimeUnit.MINUTES)
+        .expireAfterAccess(Duration.ofMinutes(60))
         //.softValues()
         .build();
 
diff --git a/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/IGitHubConnIgnited.java b/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/IGitHubConnIgnited.java
index 1ceb3226..956f1671 100644
--- a/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/IGitHubConnIgnited.java
+++ b/tcbot-github-ignited/src/main/java/org/apache/ignite/githubignited/IGitHubConnIgnited.java
@@ -47,14 +47,6 @@ public interface IGitHubConnIgnited {
     /** {@inheritDoc} */
     public List<String> getBranches();
 
-    /**
-     * Send POST request with given body.
-     *
-     * @param url Url.
-     * @param body Request body.
-     */
-    public void notifyGit(String url, String body);
-
     /**
      * Prefix to be added to git branch instead of {@link IJiraServerConfig#branchNumPrefix()}. Usually it is a lower
      * case of JIRA branch mention, e.. JIRA branch num is 'IGNITE-', and git is 'ignite-'
diff --git a/tcbot-github/build.gradle b/tcbot-github/build.gradle
index d395787d..2854abe7 100644
--- a/tcbot-github/build.gradle
+++ b/tcbot-github/build.gradle
@@ -21,9 +21,11 @@ dependencies {
     api project(":tcbot-common")
     // GitHub integration shares entries for pure and Ignited connection, so persistence module is here for interfaces/annotations
     api project(":tcbot-persistence")
-    
-    testImplementation group: 'junit', name: 'junit', version: junitVer
-    testImplementation group: 'org.mockito', name: 'mockito-core', version: mockitoVer
+
+    api "com.google.code.gson:gson:$gsonVer"
+
+    testImplementation "junit:junit:$junitVer"
+    testImplementation "org.mockito:mockito-core:$mockitoVer"
 }
 
 
diff --git a/tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubCachingProvider.java b/tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubCachingProvider.java
index d3524422..43b4329d 100644
--- a/tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubCachingProvider.java
+++ b/tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubCachingProvider.java
@@ -16,26 +16,30 @@
  */
 package org.apache.ignite.githubservice;
 
+import java.time.Duration;
+
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import javax.inject.Inject;
-import javax.inject.Provider;
+import java.util.function.Supplier;
 import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
 
 class GitHubCachingProvider implements IGitHubConnectionProvider {
-    @Inject private Provider<IGitHubConnection> factory;
+    private final Supplier<IGitHubConnection> factory;
 
     private final Cache<String, IGitHubConnection> srvs
         = CacheBuilder.newBuilder()
         .maximumSize(100)
-        .expireAfterAccess(16, TimeUnit.MINUTES)
+        .expireAfterAccess(Duration.ofMinutes(16))
         .softValues()
         .build();
 
+    GitHubCachingProvider(Supplier<IGitHubConnection> factory) {
+        this.factory = factory;
+    }
+
     /** {@inheritDoc} */
     @Override public IGitHubConnection server(String srvCode) {
         try {
diff --git a/tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubConnectionImpl.java b/tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubConnectionImpl.java
index 21fb7754..ab2463c9 100644
--- a/tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubConnectionImpl.java
+++ b/tcbot-github/src/main/java/org/apache/ignite/githubservice/GitHubConnectionImpl.java
@@ -20,18 +20,8 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
-import org.apache.ignite.tcbot.common.conf.IDataSourcesConfigSupplier;
-import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
-import org.apache.ignite.ci.github.GitHubBranchShort;
-import org.apache.ignite.ci.github.PullRequest;
-import org.apache.ignite.tcbot.common.conf.IGitHubConfig;
-import org.apache.ignite.tcbot.common.util.HttpUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import javax.inject.Inject;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -49,6 +39,14 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.LockSupport;
+import org.apache.ignite.ci.github.GitHubBranchShort;
+import org.apache.ignite.ci.github.PullRequest;
+import org.apache.ignite.tcbot.common.conf.IDataSourcesConfigSupplier;
+import org.apache.ignite.tcbot.common.conf.IGitHubConfig;
+import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
+import org.apache.ignite.tcbot.common.util.HttpUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import static com.google.common.base.Strings.isNullOrEmpty;
 
@@ -57,8 +55,7 @@ class GitHubConnectionImpl implements IGitHubConnection {
     private static final Logger logger = LoggerFactory.getLogger(GitHubConnectionImpl.class);
 
     /** Config. */
-    @Inject
-    private IDataSourcesConfigSupplier cfg;
+    private final IDataSourcesConfigSupplier cfg;
 
     /** Service (server) code. */
     private String srvCode;
@@ -77,6 +74,10 @@ class GitHubConnectionImpl implements IGitHubConnection {
 
     private static AtomicLong lastRq = new AtomicLong();
 
+    GitHubConnectionImpl(IDataSourcesConfigSupplier cfg) {
+        this.cfg = cfg;
+    }
+
     /**
      * @param linkRspHdrVal Value of Link response HTTP header.
      */
@@ -150,21 +151,6 @@ class GitHubConnectionImpl implements IGitHubConnection {
         throw new IllegalStateException("Unreachable");
     }
 
-    /** {@inheritDoc} */
-    @AutoProfiling
-    @Override public boolean notifyGit(String url, String body) {
-        try {
-            HttpUtil.sendPostAsStringToGit(config().gitAuthTok(), url, body);
-
-            return true;
-        }
-        catch (IOException e) {
-            logger.error("Failed to notify Git [errMsg=" + e.getMessage() + ']');
-
-            return false;
-        }
-    }
-
     /** {@inheritDoc} */
     @AutoProfiling
     @Override public List<PullRequest> getPullRequestsPage(@Nullable String fullUrl,
diff --git a/tcbot-github/src/main/java/org/apache/ignite/githubservice/IGitHubConnection.java b/tcbot-github/src/main/java/org/apache/ignite/githubservice/IGitHubConnection.java
index e806f372..2ab7c760 100644
--- a/tcbot-github/src/main/java/org/apache/ignite/githubservice/IGitHubConnection.java
+++ b/tcbot-github/src/main/java/org/apache/ignite/githubservice/IGitHubConnection.java
@@ -36,15 +36,6 @@ public interface IGitHubConnection {
     /** */
     public PullRequest getPullRequest(Integer id);
 
-    /**
-     * Send POST request with given body.
-     *
-     * @param url Url.
-     * @param body Request body.
-     * @return {@code True} - if GitHub was notified. {@code False} - otherwise.
-     */
-    public boolean notifyGit(String url, String body);
-
     /**
      * @param fullUrl Full url - null for first page, not null for next page.
      * @param outLinkNext Out link for return next page full url.
diff --git a/tcbot-jira-ignited/build.gradle b/tcbot-jira-ignited/build.gradle
index bb41aa53..e12f3008 100644
--- a/tcbot-jira-ignited/build.gradle
+++ b/tcbot-jira-ignited/build.gradle
@@ -20,5 +20,7 @@ apply plugin: 'java'
 dependencies {
     api project(":tcbot-jira")
     api project(":tcbot-persistence")
+
+    implementation 'javax.inject:javax.inject:1'
 }
 
diff --git a/tcbot-jira-ignited/src/main/java/org/apache/ignite/jiraignited/JiraIgnitedProvider.java b/tcbot-jira-ignited/src/main/java/org/apache/ignite/jiraignited/JiraIgnitedProvider.java
index 4f4571b1..bdfb94f6 100644
--- a/tcbot-jira-ignited/src/main/java/org/apache/ignite/jiraignited/JiraIgnitedProvider.java
+++ b/tcbot-jira-ignited/src/main/java/org/apache/ignite/jiraignited/JiraIgnitedProvider.java
@@ -16,13 +16,14 @@
  */
 package org.apache.ignite.jiraignited;
 
+import java.time.Duration;
+
 import com.google.common.base.Strings;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
-import com.google.inject.Provider;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 import javax.inject.Inject;
+import javax.inject.Provider;
 import org.apache.ignite.jiraservice.IJiraIntegration;
 import org.apache.ignite.jiraservice.IJiraIntegrationProvider;
 import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
@@ -41,7 +42,7 @@ public class JiraIgnitedProvider implements IJiraIgnitedProvider {
     private final Cache<String, IJiraIgnited> srvs
         = CacheBuilder.newBuilder()
         .maximumSize(100)
-        .expireAfterAccess(16, TimeUnit.MINUTES)
+        .expireAfterAccess(Duration.ofMinutes(16))
         .softValues()
         .build();
 
diff --git a/tcbot-jira/build.gradle b/tcbot-jira/build.gradle
index ffafe364..0f03aa73 100644
--- a/tcbot-jira/build.gradle
+++ b/tcbot-jira/build.gradle
@@ -22,7 +22,10 @@ dependencies {
     // JIRA integration shares entries for pure and Ignited connection, so persistence module is here for interfaces/annotations
     api project(":tcbot-persistence")
 
-    testImplementation group: 'junit', name: 'junit', version: junitVer
-    testImplementation group: 'org.mockito', name: 'mockito-core', version: mockitoVer
-}
+    api "com.google.code.gson:gson:$gsonVer"
+
+    implementation 'javax.inject:javax.inject:1'
 
+    testImplementation "junit:junit:$junitVer"
+    testImplementation "org.mockito:mockito-core:$mockitoVer"
+}
diff --git a/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/JiraIntegrationProvider.java b/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/JiraIntegrationProvider.java
index 62d648c3..a4b94fc6 100644
--- a/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/JiraIntegrationProvider.java
+++ b/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/JiraIntegrationProvider.java
@@ -17,13 +17,14 @@
 
 package org.apache.ignite.jiraservice;
 
+import java.time.Duration;
+
 import com.google.common.base.Strings;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
-import com.google.inject.Provider;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 import javax.inject.Inject;
+import javax.inject.Provider;
 import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
 
 /**
@@ -38,7 +39,7 @@ class JiraIntegrationProvider implements IJiraIntegrationProvider {
     private final Cache<String, IJiraIntegration> srvs
         = CacheBuilder.newBuilder()
         .maximumSize(100)
-        .expireAfterAccess(16, TimeUnit.MINUTES)
+        .expireAfterAccess(Duration.ofMinutes(16))
         .softValues()
         .build();
 
diff --git a/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/adapters/TypeFactory.java b/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/adapters/TypeFactory.java
index 7bb08e29..b1bfa473 100644
--- a/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/adapters/TypeFactory.java
+++ b/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/adapters/TypeFactory.java
@@ -52,13 +52,13 @@ public class TypeFactory<T> implements TypeAdapterFactory {
         if (!handle)
             return null;
 
-        TypeAdapter<?> delegate;
+        TypeAdapter<R> delegate;
         switch (apiVersion) {
             case V2:
-                delegate = gson.getDelegateAdapter(this, TypeToken.get(v2Class));
+                delegate = adapter(gson, v2Class);
                 break;
             case V3:
-                delegate = gson.getDelegateAdapter(this, TypeToken.get(v3Class));
+                delegate = adapter(gson, v3Class);
                 break;
             default:
                 throw new IllegalArgumentException("Unknown jira api version [ver=" + apiVersion + ']');
@@ -66,11 +66,16 @@ public class TypeFactory<T> implements TypeAdapterFactory {
 
         return new TypeAdapter<R>() {
             @Override public void write(JsonWriter out, R value) throws IOException {
-                ((TypeAdapter<R>) delegate).write(out, value);
+                delegate.write(out, value);
             }
             @Override public R read(JsonReader reader) throws IOException {
-                return ((TypeAdapter<R>) delegate).read(reader);
+                return delegate.read(reader);
             }
         }.nullSafe();
     }
+
+    @SuppressWarnings("unchecked")
+    private <R> TypeAdapter<R> adapter(Gson gson, Class<? extends T> cls) {
+        return (TypeAdapter<R>)gson.getDelegateAdapter(this, TypeToken.get(cls));
+    }
 }
diff --git a/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/package-info.java b/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/package-info.java
index 5699df1a..84cb64c3 100644
--- a/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/package-info.java
+++ b/tcbot-jira/src/main/java/org/apache/ignite/jiraservice/package-info.java
@@ -16,7 +16,6 @@
  */
 
 /**
- * This package is intended for interacting with Jira servers. It contains classes which is needed for injection Jira
- * integration service instance via Guice. And interfaces and classes which provide specified functionality.
+ * This package contains Jira integration contracts and their default implementation.
  */
 package org.apache.ignite.jiraservice;
diff --git a/tcbot-notify/build.gradle b/tcbot-notify/build.gradle
index f4464588..407884b7 100644
--- a/tcbot-notify/build.gradle
+++ b/tcbot-notify/build.gradle
@@ -20,7 +20,7 @@ apply plugin: 'java'
 dependencies {
     api project(":tcbot-common")
 
-    api group: 'com.sun.mail', name: 'javax.mail', version: mailVer
+    api "com.sun.mail:javax.mail:$mailVer"
 
-    api group: 'com.ullink.slack', name: 'simpleslackapi', version: '1.4.0'
+    api 'com.ullink.slack:simpleslackapi:1.4.0'
 }
diff --git a/tcbot-persistence/build.gradle b/tcbot-persistence/build.gradle
index baa488d3..3ea5c54a 100644
--- a/tcbot-persistence/build.gradle
+++ b/tcbot-persistence/build.gradle
@@ -25,10 +25,13 @@ repositories {
 dependencies {
     api project(":tcbot-common")
 
-    api (group: 'org.apache.ignite', name: 'ignite-core', version: ignVer) {
+    api("org.apache.ignite:ignite-core:$ignVer") {
         exclude group: 'org.jetbrains'
     }
 
     api "org.apache.ignite:ignite-indexing:$ignVer"
+
+    implementation "org.xerial.snappy:snappy-java:$snappyVer"
+
 }
 
diff --git a/tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/IgniteStringCompactor.java b/tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/IgniteStringCompactor.java
index 6cb0db21..dbd89799 100644
--- a/tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/IgniteStringCompactor.java
+++ b/tcbot-persistence/src/main/java/org/apache/ignite/tcbot/persistence/IgniteStringCompactor.java
@@ -20,9 +20,8 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
 import javax.cache.Cache;
-import javax.inject.Inject;
-import javax.inject.Provider;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteAtomicSequence;
 import org.apache.ignite.IgniteCache;
@@ -51,7 +50,7 @@ public class IgniteStringCompactor implements IStringCompactor {
     private static final String STRINGS_SEQ = "stringsSeq";
 
     /** Ignite provider. */
-    @Inject private Provider<Ignite> igniteProvider;
+    private final Supplier<Ignite> igniteProvider;
 
     /** Builds cache. */
     private IgniteCache<String, org.apache.ignite.ci.teamcity.ignited.IgniteStringCompactor.CompactorEntity> stringsCache;
@@ -59,6 +58,10 @@ public class IgniteStringCompactor implements IStringCompactor {
     /** Sequence. */
     private IgniteAtomicSequence seq;
 
+    public IgniteStringCompactor(Supplier<Ignite> igniteProvider) {
+        this.igniteProvider = igniteProvider;
+    }
+
     private void initIfNeeded() {
         if (initGuard.compareAndSet(false, true)) {
             init();
@@ -112,6 +115,7 @@ public class IgniteStringCompactor implements IStringCompactor {
     /** {@inheritDoc} */
     @AutoProfiling
     @GuavaCached(cacheNullRval = false)
+    @SuppressWarnings("deprecation")
     @Override public String getStringFromId(int id) {
         if (id < 0)
             return null;
diff --git a/tcbot-server-node/README.md b/tcbot-server-node/README.md
deleted file mode 100644
index 30d72999..00000000
--- a/tcbot-server-node/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-TC Bot server node
-------------------
-
-Incomplete module for preparing scripts to start Apache Ignite as a separate process.
\ No newline at end of file
diff --git a/tcbot-server-node/build.gradle b/tcbot-server-node/build.gradle
deleted file mode 100644
index 630082fa..00000000
--- a/tcbot-server-node/build.gradle
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-apply plugin: 'java'
-apply plugin: 'application'
-
-repositories {
-    mavenCentral()
-    mavenLocal()
-}
-
-application {
-    mainClass = 'org.apache.ignite.ci.TcBotIgniteServerLauncher'
-    applicationDefaultJvmArgs = igniteJava17JvmArgs + ["-Dteamcity.helper.home=../work",
-                                                       "-Dfile.encoding=UTF-8",
-                                                       "-Dteamcity.bot.regionsize=16", // 16g Durable Memory region
-                                                       "-server",
-                                                       "-Xmx2g",
-                                                       "-XX:+AlwaysPreTouch",
-                                                       "-XX:+UseG1GC",
-                                                       "-XX:+ScavengeBeforeFullGC",
-                                                       "-XX:+UseStringDeduplication",
-                                                       "-Djava.rmi.server.hostname=app02",
-                                                       "-Dcom.sun.management.jmxremote",
-                                                       "-Dcom.sun.management.jmxremote.port=9011",
-                                                       "-Dcom.sun.management.jmxremote.local.only=false",
-                                                       "-Dcom.sun.management.jmxremote.authenticate=false",
-                                                       "-Dcom.sun.management.jmxremote.ssl=false"]
-}
-
-distributions {
-
-}
-
-dependencies {
-    implementation (project(":tcbot-common")) {
-        transitive = false
-    }
-
-    implementation (project(":ignite-tc-helper-web"))  {
-        transitive = false
-    }
-
-    implementation group: 'com.google.guava', name: 'guava', version: guavaVer
-
-    implementation group: 'ch.qos.logback', name: 'logback-core', version: logbackVer
-    implementation group: 'ch.qos.logback', name: 'logback-classic', version: logbackVer
-
-    implementation group: 'org.apache.ignite', name: 'ignite-core', version: ignVer
-    implementation group: 'org.apache.ignite', name: 'ignite-slf4j', version: ignVer
-    implementation group: 'org.apache.ignite', name: 'ignite-direct-io', version: ignVer
-}
diff --git a/tcbot-server-node/src/main/java/org/apache/ignite/ci/TcBotIgniteServerLauncher.java b/tcbot-server-node/src/main/java/org/apache/ignite/ci/TcBotIgniteServerLauncher.java
deleted file mode 100644
index c7011f48..00000000
--- a/tcbot-server-node/src/main/java/org/apache/ignite/ci/TcBotIgniteServerLauncher.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.ci;
-
-import org.apache.ignite.Ignite;
-import org.apache.ignite.Ignition;
-import org.apache.ignite.ci.db.Ignite2Configurer;
-import org.apache.ignite.configuration.DataRegionConfiguration;
-import org.apache.ignite.configuration.DataStorageConfiguration;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.configuration.WALMode;
-import org.apache.ignite.logger.slf4j.Slf4jLogger;
-import org.apache.ignite.tcbot.common.conf.TcBotWorkDir;
-
-import java.io.File;
-import java.io.IOException;
-
-public class TcBotIgniteServerLauncher {
-    public static void main(String[] args) throws IOException {
-        final File workDir = TcBotWorkDir.resolveWorkDir();
-        Ignite2Configurer.configLogger(workDir, "tcbot_srv_logs");
-
-        final IgniteConfiguration cfg = new IgniteConfiguration();
-        Ignite2Configurer.setIgniteHome(cfg, workDir);
-        cfg.setWorkDirectory(new File(cfg.getIgniteHome(), "tcbot_srv").getCanonicalPath());
-
-/*
-        setupDisco(cfg);*/
-        cfg.setConsistentId("tcbot");
-        cfg.setGridLogger(new Slf4jLogger());
-        System.err.println("Hello");
-
-
-        final DataRegionConfiguration regConf = Ignite2Configurer.getDataRegionConfiguration();
-
-        final DataStorageConfiguration dsCfg = new DataStorageConfiguration()
-                .setWalMode(WALMode.LOG_ONLY)
-                .setWalHistorySize(1)
-                .setCheckpointFrequency(5 * 60 * 1000)
-                .setWriteThrottlingEnabled(true)
-                .setDefaultDataRegionConfiguration(regConf);
-
-        cfg.setDataStorageConfiguration(dsCfg);
-
-        System.out.println("Starting Ignite Server Node");
-
-        final Ignite ignite = Ignition.start(cfg);
-
-        System.out.println("Activating Ignite Server Node");
-
-        ignite.cluster().active(true);
-
-        System.out.println("Activate Completed");
-    }
-}
diff --git a/tcbot-teamcity-ignited/build.gradle b/tcbot-teamcity-ignited/build.gradle
index 6135679d..e1e813ff 100644
--- a/tcbot-teamcity-ignited/build.gradle
+++ b/tcbot-teamcity-ignited/build.gradle
@@ -21,7 +21,11 @@ dependencies {
     api project(":tcbot-teamcity")
     api project(":tcbot-persistence")
 
-    testImplementation group: 'junit', name: 'junit', version: junitVer;
-    testImplementation group: 'org.mockito', name: 'mockito-core', version: mockitoVer;
+    implementation 'javax.inject:javax.inject:1'
+    implementation 'javax.xml.bind:jaxb-api:2.3.1'
+    implementation "org.xerial.snappy:snappy-java:$snappyVer"
+
+    testImplementation "junit:junit:$junitVer";
+    testImplementation "org.mockito:mockito-core:$mockitoVer";
 }
 
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TcIgnitedCachingProvider.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TcIgnitedCachingProvider.java
index ecdb950e..5f68b4be 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TcIgnitedCachingProvider.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TcIgnitedCachingProvider.java
@@ -19,8 +19,8 @@ package org.apache.ignite.tcignited;
 import com.google.common.base.Strings;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
+import java.time.Duration;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 import javax.annotation.Nullable;
 import javax.inject.Inject;
 import javax.inject.Provider;
@@ -45,7 +45,7 @@ class TcIgnitedCachingProvider implements ITeamcityIgnitedProvider {
     private final Cache<String, ITeamcityIgnited> srvs
             = CacheBuilder.newBuilder()
             .maximumSize(100)
-            .expireAfterAccess(16, TimeUnit.MINUTES)
+            .expireAfterAccess(Duration.ofMinutes(16))
             .softValues()
             .build();
 
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedImpl.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedImpl.java
index e931d5e7..1ea5bbdb 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedImpl.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/TeamcityIgnitedImpl.java
@@ -164,7 +164,7 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
         this.conn = conn;
 
         srvIdMaskHigh = ITeamcityIgnited.serverIdToInt(srvCode);
-        buildRefDao.init(); //todo init somehow in auto
+        buildRefDao.init();
         buildConditionDao.init();
         fatBuildDao.init();
         changesDao.init();
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/build/ProactiveFatBuildSync.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/build/ProactiveFatBuildSync.java
index 09544dd0..8eb33d6b 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/build/ProactiveFatBuildSync.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/build/ProactiveFatBuildSync.java
@@ -364,7 +364,6 @@ public class ProactiveFatBuildSync {
     @SuppressWarnings({"WeakerAccess"})
     @AutoProfiling
     @Nullable public FatBuildCompacted reloadBuild(ITeamcityConn conn, int buildId, @Nullable FatBuildCompacted existingBuild) {
-        //todo some sort of locking to avoid double requests
 
         final String srvName = conn.serverCode();
         final int srvIdMask = ITeamcityIgnited.serverIdToInt(srvName);
@@ -435,8 +434,6 @@ public class ProactiveFatBuildSync {
                     tests = Collections.singletonList(existingBuild.getTestOcurrences(compactor));
 
                     problems = existingBuild.problems(compactor);
-
-                    //todo extract new parameters or save fat build without XML convertions
                     // - existingBuild.statistics();
                     // - int[] changes = existingBuild.changes();
                 }
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessor.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessor.java
index 513fcbac..75808f37 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessor.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/BuildLogProcessor.java
@@ -18,6 +18,7 @@ package org.apache.ignite.tcignited.buildlog;
 
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
+import java.time.Duration;
 import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
 import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
 import org.apache.ignite.tcignited.ITeamcityIgnited;
@@ -31,7 +32,6 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
@@ -49,7 +49,7 @@ class BuildLogProcessor implements IBuildLogProcessor {
     private final Cache<Long, ILogCheckResult> logCheckResultCache
             = CacheBuilder.newBuilder()
             .maximumSize(500)
-            .expireAfterAccess(3, TimeUnit.MINUTES)
+            .expireAfterAccess(Duration.ofMinutes(3))
             .softValues()
             .build();
 
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogMsgToWarn.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogMsgToWarn.java
index 78bec57c..630a2f8b 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogMsgToWarn.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildlog/LogMsgToWarn.java
@@ -23,20 +23,21 @@ import org.apache.ignite.tcservice.model.result.problems.ProblemOccurrence;
 /**
  *
  */
-//todo make non static
-//todo include test name
-//todo addBuild NPE
 public class LogMsgToWarn {
 
     private static final String JAVA_LEVEL_DEADLOCK_TXT = " Java-level deadlock:";
 
-    @Deprecated
-    public static boolean needWarn(String line) {
+    public static boolean isWarningLine(String line) {
         return line.contains("java.lang.AssertionError:")
             || line.contains(JAVA_LEVEL_DEADLOCK_TXT)
             || line.contains("Critical failure. Will be handled accordingly to configured handler");
     }
 
+    @Deprecated
+    public static boolean needWarn(String line) {
+        return isWarningLine(line);
+    }
+
     @Nullable
     public static String getProblemCode(String line) {
         if (line.contains(JAVA_LEVEL_DEADLOCK_TXT))
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefDao.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefDao.java
index d4aef425..6370520b 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefDao.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/buildref/BuildRefDao.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.tcignited.buildref;
 
 import com.google.common.cache.CacheBuilder;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -27,7 +28,6 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -84,8 +84,8 @@ public class BuildRefDao {
     private final com.google.common.cache.Cache<RunHistKey, List<BuildRefCompacted>> buildRefsInMemCache
         = CacheBuilder.newBuilder()
         .maximumSize(Boolean.valueOf(System.getProperty(TcBotSystemProperties.DEV_MODE)) ? 1000 : 8000)
-        .expireAfterAccess(16, TimeUnit.MINUTES)
-        .expireAfterWrite(45, TimeUnit.MINUTES) //workaround for stale records, enforcing to ask persistence sometimes.
+        .expireAfterAccess(Duration.ofMinutes(16))
+        .expireAfterWrite(Duration.ofMinutes(45)) //workaround for stale records, enforcing to ask persistence sometimes.
         .softValues()
         .build();
 
@@ -94,8 +94,8 @@ public class BuildRefDao {
     private final com.google.common.cache.Cache<Long, List<BuildRefCompacted>> buildRefsInMemCacheForAllBranch
         = CacheBuilder.newBuilder()
         .maximumSize(Boolean.valueOf(System.getProperty(TcBotSystemProperties.DEV_MODE)) ? 200 : 2000)
-        .expireAfterAccess(2, TimeUnit.MINUTES)
-        .expireAfterWrite(4, TimeUnit.MINUTES) //workaround for stale records
+        .expireAfterAccess(Duration.ofMinutes(2))
+        .expireAfterWrite(Duration.ofMinutes(4)) //workaround for stale records
         .softValues()
         .build();
 
@@ -323,6 +323,7 @@ public class BuildRefDao {
         }
     }
 
+    @SuppressWarnings("deprecation")
     public List<BuildRefCompacted> getBuildsForBranchNonCached(int srvId, int branchNameId) {
         List<BuildRefCompacted> list = new ArrayList<>();
 
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/AbstractRunHist.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/AbstractRunHist.java
index 8c45088e..7e387172 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/AbstractRunHist.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/AbstractRunHist.java
@@ -88,8 +88,6 @@ public abstract class AbstractRunHist implements IRunHistory {
 
             if (cur.status() == InvocationData.MISSING)
                 continue;
-
-            //todo here all previous MISSING invocations status could be checked
             if (prev != null) {
                 if (prev.status() != cur.status()
                     && cur.changesState() == ChangesState.NONE
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/HistoryCollector.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/HistoryCollector.java
index 63a2c146..6a4ef5bd 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/HistoryCollector.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/HistoryCollector.java
@@ -27,7 +27,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 import java.util.function.BiPredicate;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -94,8 +93,8 @@ public class HistoryCollector {
     private final com.google.common.cache.Cache<RunHistKey, SuiteHistory> runHistInMemCache
         = CacheBuilder.newBuilder()
         .maximumSize(Boolean.valueOf(System.getProperty(TcBotSystemProperties.DEV_MODE)) ? 1000 : 8000)
-        .expireAfterAccess(16, TimeUnit.MINUTES)
-        .expireAfterWrite(17, TimeUnit.MINUTES) //workaround for stale records
+        .expireAfterAccess(Duration.ofMinutes(16))
+        .expireAfterWrite(Duration.ofMinutes(17)) //workaround for stale records
         .softValues()
         .build();
 
diff --git a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/SuiteInvocationHistoryDao.java b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/SuiteInvocationHistoryDao.java
index 06cbb2be..4ffa4ce3 100644
--- a/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/SuiteInvocationHistoryDao.java
+++ b/tcbot-teamcity-ignited/src/main/java/org/apache/ignite/tcignited/history/SuiteInvocationHistoryDao.java
@@ -61,6 +61,7 @@ public class SuiteInvocationHistoryDao {
     }
 
     @AutoProfiling
+    @SuppressWarnings("deprecation")
     public Map<Integer, SuiteInvocation> getSuiteRunHist(int srvId, int buildTypeId, int normalizedBranchName) {
         Map<Integer, SuiteInvocation> map = new HashMap<>();
 
diff --git a/tcbot-teamcity/build.gradle b/tcbot-teamcity/build.gradle
index 53211fe1..ce77f4c8 100644
--- a/tcbot-teamcity/build.gradle
+++ b/tcbot-teamcity/build.gradle
@@ -21,8 +21,11 @@ apply plugin: 'java'
 dependencies {
     api project(":tcbot-common")
 
-    /// JAXB replacement for Java 17, API is defined in common
-    api group: 'com.sun.xml.bind', name: 'jaxb-impl', version: jaxbVer
-    api group: 'com.sun.xml.bind', name: 'jaxb-core', version: '2.3.0'
+    /// JAXB replacement for Java 17.
+    api 'javax.xml.bind:jaxb-api:2.3.1'
+    runtimeOnly "com.sun.xml.bind:jaxb-impl:$jaxbVer"
+    runtimeOnly 'com.sun.xml.bind:jaxb-core:2.3.0'
+
+    implementation 'javax.inject:javax.inject:1'
 }
 
diff --git a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/http/FileRecordingInputStream.java b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/http/FileRecordingInputStream.java
index 416399e5..46a8d8a7 100644
--- a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/http/FileRecordingInputStream.java
+++ b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/http/FileRecordingInputStream.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.tcservice.http;
 
-import com.google.common.base.Charsets;
 import com.google.common.base.Preconditions;
 
 import javax.annotation.Nonnull;
@@ -25,6 +24,7 @@ import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -98,11 +98,11 @@ public class FileRecordingInputStream extends FilterInputStream {
         super.close();
 
         if (closeGuard.compareAndSet(false, true)) {
-            file.write("\n".getBytes(Charsets.UTF_8));
+            file.write("\n".getBytes(StandardCharsets.UTF_8));
 
             lock.unlock();
 
             file.flush();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/http/TeamcityRecorder.java b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/http/TeamcityRecorder.java
index 61d0b4ac..0758974a 100644
--- a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/http/TeamcityRecorder.java
+++ b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/http/TeamcityRecorder.java
@@ -17,13 +17,13 @@
 
 package org.apache.ignite.tcservice.http;
 
-import com.google.common.base.Charsets;
 import org.apache.ignite.tcbot.common.conf.TcBotSystemProperties;
 
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.concurrent.locks.ReentrantLock;
 
 /**
@@ -50,7 +50,7 @@ public class TeamcityRecorder {
                     file = new FileOutputStream("tcrecorder.txt");
 
                 final String newUrlStartStr = "===HTTP=RECORDER=== GET " + url + "\n";
-                file.write(newUrlStartStr.getBytes(Charsets.UTF_8));
+                file.write(newUrlStartStr.getBytes(StandardCharsets.UTF_8));
 
                 FileRecordingInputStream spyStream = new FileRecordingInputStream(inputStream, file, lock);
 
diff --git a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/util/TcConnectionStaticLinker.java b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/util/TcConnectionStaticLinker.java
index a71bcf2f..7862dea7 100644
--- a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/util/TcConnectionStaticLinker.java
+++ b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/util/TcConnectionStaticLinker.java
@@ -20,7 +20,7 @@ import org.apache.ignite.tcservice.TeamcityServiceConnection;
 import org.apache.ignite.tcservice.http.TeamcityRecordingConnection;
 
 /**
- * Factory for non-guice creation of TC Connection instance.
+ * Factory for direct creation of TC Connection instance.
  */
 public class TcConnectionStaticLinker {
     /**
diff --git a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/util/XmlUtil.java b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/util/XmlUtil.java
index b0a03b5c..1fd9fde6 100644
--- a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/util/XmlUtil.java
+++ b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/util/XmlUtil.java
@@ -26,6 +26,7 @@ import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
 
 /**
  */
@@ -35,7 +36,7 @@ public class XmlUtil {
 
     public static <T> T load(Class<T> tCls, Reader reader) throws JAXBException {
         Unmarshaller unmarshaller = getContext(tCls).createUnmarshaller();
-        T unmarshal = (T)unmarshaller.unmarshal(reader);
+        T unmarshal = unmarshaller.unmarshal(new StreamSource(reader), tCls).getValue();
 
         ObjectInterner.internFields(unmarshal);