Skip to content
Advertisement

Java Melody does not show any sql data on xampp tomcat8

On Xampp Tomcat on Windows 11, I am trying to monitor java-web-app with java melody.
However, sql data is not detected by java melody.
Could you figure out what i am missing?

I have created a library project, not to do same settings on every app
Here is the projects code…
pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.tugalsan</groupId>
    <artifactId>api-profile</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>net.bull.javamelody</groupId>
            <artifactId>javamelody-core</artifactId>
            <version>1.90.0</version>
        </dependency>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>api-url</artifactId>
            <version>${project.version}</version>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.java</include>
                    <include>**/*.gwt.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-source-plugin</artifactId>
                    <version>3.2.1</version>
                    <executions>
                        <execution>
                            <id>attach-sources</id>
                            <phase>package</phase>
                            <goals>
                                <goal>jar-no-fork</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
    <properties>
        <maven.compiler.source>15</maven.compiler.source>
        <maven.compiler.target>15</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

TGS_ProfileServletUtils.java:

package com.tugalsan.api.profile.client;

import com.tugalsan.api.url.client.parser.*;

public class TGS_ProfileServletUtils {

    final public static String SERVLET_NAME = "monitoring";//HARD-CODED IN LIB, THIS CANNOT BE CHANGED!
}

TS_ProfileMelodyUtils.java:

package com.tugalsan.api.profile.server.melody;

import java.sql.*;
import javax.sql.*;
import javax.servlet.*;
import javax.servlet.annotation.*;
import net.bull.javamelody.*;
import com.tugalsan.api.profile.client.*;

public class TS_ProfileMelodyUtils {

    @WebFilter(
            filterName = TGS_ProfileServletUtils.SERVLET_NAME,
            dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.ASYNC},
            asyncSupported = true,
            urlPatterns = {"/*"},
            initParams = {
                @WebInitParam(name = "async-supported", value = "true")
            }
    )
    final public static class MelodyFilter extends MonitoringFilter {

    }

    @WebListener
    final public static class MelodyListener extends SessionListener {

    }

    public static Connection createProxy(Connection con) {
        try {
            DriverManager.registerDriver(new net.bull.javamelody.JdbcDriver());
            return JdbcWrapper.SINGLETON.createConnectionProxy(con);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static DataSource createProxy(DataSource ds) {
        try {
            DriverManager.registerDriver(new net.bull.javamelody.JdbcDriver());
            return JdbcWrapper.SINGLETON.createDataSourceProxy(ds);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

a helper class

package com.tugalsan.api.sql.conn.server;

import java.io.Serializable;
import java.util.Objects;

public class TS_SQLConnConfig implements Serializable {

    public int method = TS_SQLConnMethodUtils.METHOD_MYSQL();
    public String dbName;
    public String dbIp = "localhost";
    public int dbPort = 3306;
    public String dbUser = "root";
    public String dbPassword = "";
    public boolean autoReconnect = true;
    public boolean useSSL = false;
    public boolean region_ist = true;
    public boolean charsetUTF8 = true;
    public boolean isPooled = true;

    public TS_SQLConnConfig() {//DTO

    }

    public TS_SQLConnConfig(CharSequence dbName) {
        this.dbName = dbName == null ? null : dbName.toString();
    }
}

On another api, this is how i create a pool
(I skipped some class files, unrelated to the question)

public static PoolProperties create(TS_SQLConnConfig config) {
        var pool = new PoolProperties();

        pool.setUrl(TS_SQLConnURLUtils.create(config));
        pool.setDriverClassName(TS_SQLConnMethodUtils.getDriver(config));
        if (TGS_StringUtils.isPresent(config.dbUser) && TGS_StringUtils.isPresent(config.dbPassword)) {
            pool.setUsername(config.dbUser);
            pool.setPassword(config.dbPassword);
        }
        var maxActive = 200;
        pool.setMaxActive(maxActive);
        pool.setInitialSize(maxActive / 10);
        pool.setJmxEnabled(true);
        pool.setTestWhileIdle(true);
        pool.setTestOnBorrow(true);
        pool.setTestOnReturn(false);
        pool.setValidationQuery("SELECT 1");
        pool.setValidationInterval(30000);
        pool.setTimeBetweenEvictionRunsMillis(30000);
        pool.setMaxWait(10000);
        pool.setMinEvictableIdleTimeMillis(30000);
        pool.setMinIdle(10);
        pool.setFairQueue(true);
        pool.setLogAbandoned(true);
        pool.setRemoveAbandonedTimeout(600);
        pool.setRemoveAbandoned(true);
        pool.setJdbcInterceptors(
                "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
                + "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;"
                + "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");
        return pool;
    }

WAY1:

        //I created datasource once, save it as a global variable inside a ConcurrentLinkedQueue.
        var pool_ds = new DataSource(create(config));

        //then for every connection need, i created an extra proxy like this.
        var pool_con = pool_ds.getConnection();
        var proxy_con = TS_ProfileMelodyUtils.createProxy(pool_con);

        //and close both of them later on

WAY1 RESULT: enter image description here

WAY2:

        //I created datasource once, save it as a global variable inside a ConcurrentLinkedQueue.
        var pool_ds = new DataSource(create(config));
        
        //then i created a proxy datasource, save it as a global variable too
        var dsProxy = TS_ProfileMelodyUtils.createProxy(ds);

        //then for every connection need, i did not create a proxy connection.
        var pool_con = pool_ds.getConnection();

        //and close connection later on

WAY2 RESULT: (same, nothing changed) enter image description here

WAY3:

        //I created datasource once, save it as a global variable inside a ConcurrentLinkedQueue.
        var pool_ds = new DataSource(create(config));
        
        //then i created a proxy datasource, save it as a global variable too
        var dsProxy = TS_ProfileMelodyUtils.createProxy(ds);

        //then for every connection need, i created an extra proxy like this.
        var pool_con = pool_ds.getConnection();
        var proxy_con = TS_ProfileMelodyUtils.createProxy(pool_con);

        //and close both of them later on

WAY3 RESULT: (same, nothing changed) enter image description here

Advertisement

Answer

I think i found the problem.

  • One should create connection from proxy_datasource not pool_datasource

    var pool_con = pool_ds.getConnection(); //WRONG
    var pool_con = proxy_ds.getConnection(); //RIGHT

  • And also, on creating statements,
    one should use proxy connections (proxy_con) to create statements, not main connection (pool_con)!

    I used way 3. And the results were singleton. I think java melody detects that it has a datasource already; and does not log twice.

full code: at github-profile
full code: at github-sql-conn

Advertisement