WindowsAnsiOutputStream class not found - logback

When I start Micronaut project, in the IntelliJ it shows me at the Run box error that
Caused by: java.lang.ClassNotFoundException: org.fusesource.jansi.WindowsAnsiOutputStream
I know that is something which makes console output better, but I didn't found how fix it. Project ran successfully, but I want to try fix it...

It is a problem with colored logging in Logback on Windows. To workaround that you can set withJansi to false in logback.xml config file:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<withJansi>false</withJansi>
<encoder>
<pattern>%cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>
...
</configuration>
There is also an Issue created for that, see: https://github.com/micronaut-projects/micronaut-core/issues/1521

Previous answer removes the error but not fixes the issue.
If you read comment on logback.xml you will see there is a library for Java on Windows that will show logs with colors.
I don't know if you are using Maven or SBT but adding next dependency will fix your issue.
Maven:
<dependency>
<groupId>org.fusesource.jansi</groupId>
<artifactId>jansi</artifactId>
<version>2.3.4</version>
</dependency>
Sbt:
libraryDependencies += "org.fusesource.jansi" % "jansi" % "2.3.4"
https://search.maven.org/artifact/org.fusesource.jansi/jansi/2.3.4/jar

Related

How to configure logback-based logging to handle log masking with Apache Storm?

I am trying to configure logback based log masking for Apache Storm topologies.
When I try to replace logback.xml file inside Apache Storm log4j2- directory and update worker.xml and cluster.xml file, Apache Storm nimbus and supervisors are unable to understand logback based keywords.
Error:
2022-10-02 16:31:51,671 Log4j2-TF-1-ConfiguratonFileWatcher-2 ERROR Unable to locate appender "A1" for logger config "root"
2022-10-02 16:32:51,681 Log4j2-TF-7-ConfiguratonFileWatcher-4 ERROR Error processing element appender ([configuration: null]): CLASS_NOT
Sample cluster.xml file:
<configuration monitorInterval="60" shutdownHook="disable">
<properties>
<property name="pattern">%msg%n</property>
</properties>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.FileAppender"/>
<FileAppender name="A1">
<file>logfilename.log</file>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</FileAppender>
<loggers>
<root level="info"> <!-- We log everything -->
<appender-ref ref="A1"/>
</root>
</loggers>
</configuration>
To my best knowledge, Apache Storm uses naturally log4j2, as also your logfile indicates. However, when I used log4j in Storm, I did not need to import any further classes. You also do not seem to use these logback-classes in the rest of your xml-file. So have you tried to simply remove those?

Micronaut configure logger appenders based of the enviroment

I would like to configure logging appender based on the environment, for example while running in production I would like to configure an appender that would send log to elasticsearch but while on test or development mode this appender would not be enabled.
You can override the default logback config file by using "logback.configurationFile" system variable.
java -Dlogback.configurationFile=logback-prod.xml -jar your.jar
But, if what you need is the ability to use an env variable you can do this
without to use a third-party library:
Override the logback system variable inside the main micronaut class before call main, like following
#Singleton
public class MyMicronautApplication {
public static void main(String[] args) {
var env = System.getenv("MICRONAUT_ENVIRONMENTS");
if (env != null && !env.isEmpty()) {
System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, "logback-" + env + ".xml");
}
Micronaut.run(MyMicronautApplication.class);
}
}
create you custom env based logback config file like: logback-dev.xml and put in resources dir.
the set env var MICRONAUT_ENVIRONMENTS=dev according to your deployment logic.
enjoy using logback-dev.xml, logback-prod.xml, logback-stagging.xml, etc
The work around i found was by doing conditional expressions in logback. You will need the following dependency
<!-- https://mvnrepository.com/artifact/org.codehaus.janino/janino -->
<dependency>
<groupId>org.codehaus.janino</groupId>
<artifactId>janino</artifactId>
<version>3.1.2</version>
</dependency>
Then in your logback.xml file, you can do a conditional statement such as following for selecting the appender you want to you use based on a micronaut profile. In my case, I wanted to activate the STDOUT appender if i was running the application locally but i did not want to activate the STDOUT profile if the app was running in any other environment such as dev or prod profiles, instead i wanted the RSYSLOG appender to be used.
<root level="info">
<if condition='property("MICRONAUT_ENVIRONMENTS").contains("local")'>
<then>
<appender-ref ref="STDOUT"/>
</then>
<else>
<appender-ref ref="RSYSLOG"/>
</else>
</if>
</root>
You can use conditional statements to configure other properties in your logback file.
As far I understand, Micronaut doesn't have similar thing like Spring boot ( ) implemented.
I think logback-production.xml (where production is profile
) doesn't work too - only logback.xml and logback-test.xml is suported.
I wasn't crazy about the idea of having multiple logback config files or pulling in another dependency (janino) to support this use-case.
You can also do this using environment variables.
In my logback.xml I defined 2 appenders, one for "DEV" and one for "PROD".
Then I dynamically select which appender to use via the LOG_TARGET variable. If the variable is not set then it defaults to "DEV".
<configuration>
<appender name="DEV" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{ISO8601} %-5level [%X{trace_id},%X{span_id}] [%thread] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="PROD" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder" />
</appender>
<appender name="OTEL" class="io.opentelemetry.instrumentation.logback.v1_0.OpenTelemetryAppender">
<appender-ref ref="${LOG_TARGET:-DEV}"/>
</appender>
<root level="info">
<appender-ref ref="OTEL"/>
</root>
</configuration>

How to override logback config in Sonatype Nexus 3?

I'm running Sonatype Nexus 3.15.0-01 and am a little stumped about how to override the default logback configs.
I created a file called 'logback-overrides.xml' in the 'nexus-data/etc/logback' folder containing the following:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/nexus-data/log/myApp.log</file>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
This is essentially just a simple bit of config that should cause logs to be written to '/nexus-data/log/myApp.log'. I restarted the server after adding this file, to confirm it would pick up the new configs.
However, when I check for that file, it's not present. What am I missing here?
I posted this same question on the Sonatype forums here. To sum up the answer I got there, it isn't possible to override the default logback config this way.
Possible workarounds are:
Create your own logback.xml file and build your own Docker image that extends Sonatype’s official image.
Create a volume mount for /opt/sonatype/nexus/etc/logback and customize the logback.xml on your host machine.

How to send hibernate connection info to logback

I want to get hibernate conncection info (like driver_class, url, username, password) in logback file. (Not manually)
This belows is my logback file.
<appender name="dbAppender" class="ch.qos.logback.classic.db.DBAppender">
<append>false</append> //unfortunately it does not work.
<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
<driverClass>oracle.jdbc.driver.OracleDriver</driverClass>
<url>jdbc:oracle:thin:#localhost:1521:aaa</url>
<user>bbb</user>
<password>ccc</password>
</connectionSource>
</appender>
It works. But I want to get information about connection info(like driver class, url, user, password) from hibernate.cfg.xml automatically in logback.xml.
Your cooperation would be appreciated.
Please Help.
Thanks.
Getting the values out of your hibernate.cfg.xml would probably require writing some code. However, if you externalise all your hibernate properties in a properties file you can import them into your logback configuration.
Hibernate supports using a properties file called hibernate.properties in the root of the classpath, or you could pass an instance of java.util.Properties to Configuration.setProperties() when configuring your session factory.
If you can get your hibernate properties into a properties file you can use it from logback like so:
properties file on the classpath
<configuration>
<property resource="hibernate.properties" />
<appender name="dbAppender" class="ch.qos.logback.classic.db.DBAppender">
<append>false</append> //unfortunately it does not work.
<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
<driverClass>${hibernate.connection.driver_class}</driverClass>
<url>${hibernate.connection.url}</url>
<user>${hibernate.connection.username}</user>
<password>${hibernate.connection.password}</password>
</connectionSource>
</appender>
</configuration>
If your properties aren't on the classpath you can use <property file="path/to/some.properties" /> instead.

jetty-env.xml with DataSource leads to failing WebAppContext on mvn jetty:run

I have a really simple webapp project with maven and jetty that has been working very well until now. But now I need to setup MySQL connection pooling with JNDI as the database connections always time out.
First of all here is the relevant content of my pom.xml:
<modelVersion>4.0.0</modelVersion>
...
<packaging>war</packaging>
...
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jetty-version>8.1.0.v20120127</jetty-version>
</properties>
<dependencies>
...
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.20</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty-version}</version>
<type>maven-plugin</type>
</dependency>
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty-version}</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
</configuration>
</plugin>
</plugins>
...
</build>
Now I created a jetty-env.xml in the folder /src/main/webapp/WEB-INF with the following content:
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<New id="project-db" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg>jdbc/db</Arg>
<Arg>
<New class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
<Set name="url">jdbc:mysql://www.example.com:3306/mydb</Set>
<Set name="username">dbuser</Set>
<Set name="password">dbpass</Set>
</New>
</Arg>
</New>
</Configure>
But the problem is that I can't even test if this connection works as the jetty-maven-plugin fails to start on the goal
mvn jetty:run
with the following error:
WARN:oejw.WebAppContext:Failed startup of context o.m.j.p.JettyWebAppContext
{/,file:/D:/documents/programmierung/workspace/battleships-trunk/src/main/webapp/}
,file:/D:/documents/programmierung/workspace/battleships-trunk/src/main/webapp/
java.lang.IllegalArgumentException: Object of class
'org.mortbay.jetty.plugin.JettyWebAppContext' is not of type
'org.eclipse.jetty.webapp.WebAppContext'.
Object Class and type Class are from different loaders.
So how can I get this to work? I'm forced to use Jetty version 8.x as I need WebSocket support and as the remote productive server will be running Jetty 8.
EDIT
Before Pavel Veller's answer I tried the following: Deployed the assembled war to the remote jetty8 server and got the same error only that the previous error now reads as follows:
java.lang.IllegalArgumentException: Object of class
'org.eclipse.jetty.webapp.WebAppContext' is not of type
'org.eclipse.jetty.webapp.WebAppContext'.
Object Class and type Class are from different loaders.
So it seems as if there are multiple class loaders conflicting.
EDIT2
As requested by Pavel I recreated the error with a simplified webapp which you can find here on Dropbox. It is a zipped eclipse maven project.
Try removing the dependency on jetty-maven-plugin- this dependency adds the plugin to the WAR, which you don't want.
If you need to use any classes from Jetty itself, add a dependency for the specific version of Jetty (rather than the plugin) with a scope of provided.
It looks like it's pulling jetty 6 from somewhere. The exception you're seeing seems to be coming from the code that parses jetty-env.xml (org.mortbay.jetty.plus.webapp.EnvConfiguration). The XMLConfiguration class compares the class you declare on the Configure element with the actual class of what it gets from getWebAappContext(). The latter is instance of org.mortbay.jetty.plugin.JettyWebAppContext in your case and you expect it to be org.eclipse.jetty.webapp.WebAppContext (which would be the parent class for JettyWebAppContext had they both come from the same "namespace").
It's hard to tell where that would be happening from but maybe inspect your .m2 and confirm you have the proper binaries for your jetty dependencies? It has got to be running not the version you expect it to run.
UPDATE. Jetty does the following when it loads the classes defined in the configuration:
first load with Thread.currentThread().getContextClassLoader() and
loop through all getParent() until all options are exhausted.
if not successful, attempt to load with the class loader that loaded
jetty core classes (XmlConfiguration.class.getClassLoader())
looping through all the parents as well.
If still not successful, do a Class.forName()
Report ClassNotFoundException if not successful.
you can see it in the code of org.mortbay.util.Loader(http://grepcode.com is a great resource for a quick look under the hood)
It does load the class in your case, but apparently not with the right class loader.
I would now assume you have an extra jetty JAR somewhere on your classpath that interferes with the order of things.
Had a same issue caused by :
<useTestClasspath>true</useTestClasspath> (true instead of false)
That put a extra jetty jar in the classpath...
Including the dependency scope solved the error for me.
<scope>provided</scope>
In the pom.xml it looks like this,
<!-- JETTY DEPENDENCIES -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${jetty.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${jetty.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<version>${jetty.version}</version>
<scope>provided</scope>
</dependency>
in the jetty dependencies and the errors went off. And btw, the jetty version I'm using is 9.3.7.v20160115.
I had the same issue and fixed it but can't figure out why.
By changing
org.eclipse.jetty.webapp.WebAppContext
to
org.eclipse.jetty.maven.plugin.JettyWebAppContext
it started to work for some reason, can't figure out exactly why. Clearly maven plugin has something to do with it?