< Sergii Kostenko's blog

Migration from JEE to JakartaEE

30 September 2019

As you probably know Java EE was moved from Oracle to the Eclipse Foundation where will evolve under the Jakarta EE brand. Sept. 10, 2019 Jakarta EE Full Platform and Web Profile specifications was released by Eclipse Foundation during JakartaOne Livestream. Few days later Wildfly declared that WildFly 17.0.1 has passed the Jakarta EE 8 TCK and certification request has been approved by the Jakarta EE Spec Committee. So, now WildFly is a Jakarta EE Full platform compatible implementation.

Let's do migration of typical gradle EE project to the Jakarta EE and look how hard is it. Current JakartaEE version 8.0.0 is fully compatible with JavaEE version 8.0, that means no need to change project sources, just update dependency from javax:javaee-api:8.0 to jakarta.platform:jakarta.jakartaee-api:8.0.0

updated build.gradle:

apply plugin: 'war'
dependencies {
    providedCompile "jakarta.platform:jakarta.jakartaee-api:8.0.0"
}

That is it! Application builds and works well under WF17.0.1

Source code of demo application available on GitHub

Comments


Wildfly JMX connection problems (so slow and terminates)

19 August 2019

JMX (Java Management Extensions ) - is a technology that provide us possibility to monitoring applications (application servers) by MBeans (Managed Bean) objects.
List of supported MBeans can be obtained by JConsole tool that already included to JDK. As JMX does not provide strong defined communication protocol, - implementations can be different depends on vendor.
For example, to connect to Wildfly Application Server you need to use included in distribution jconsole.sh script:

<WFLY_HOME>/bin/jconsole.sh

or add <WFLY_HOME>/bin/client/jboss-client.jar to classpath:

jconsole J-Djava.class.path=$JAVA_HOME\lib\tools.jar;$JAVA_HOME\lib\jconsole.jar;jboss-client.jar

By default, Wildfly uses timeout = 60s for remote JMX connections, after that connection will terminated:
jconsole terminated connection
To change default timeout value, use org.jboss.remoting-jmx.timeout property:

./jconsole.sh -J-Dorg.jboss.remoting-jmx.timeout=300

But increasing timeouts, is not always good solution. So, lets search for the reason of slowness. To construct list of MBeans, jconsole recursively requests ALL MBeans, that can be extremely slow in case many deployments and many loggers. (Reported issue: WFCORE-3186). Partial solution here is reducing count of log files by changing rotating type from periodic-size-rotating-file-handler to size-rotating-file-handler.

Other reason of extremely slowness can be Batch subsystem (JBeret). Last one stores a lot of working information in their tables (in memory or on remote DB, depends on configuration). If this tables big enough - it can negative affect performance of server. So, if you, no need for this data then just cleanup this stuff periodically. (for example, every redeploy in case you do it often enough):

TRUNCATE TABLE PARTITION_EXECUTION CASCADE;
TRUNCATE TABLE STEP_EXECUTION CASCADE;
TRUNCATE TABLE JOB_EXECUTION CASCADE;
TRUNCATE TABLE JOB_INSTANCE CASCADE;  

From other point of view, obtaining ALL MBeans is not good decision as well. So, just use tooling that allows to find MBeans by path.

Comments


Jakarta EE application multi module gradle template

08 August 2019

In this post i will share simple and useful gradle template to organize multi module Jakarta EE application. We will implement typical one which consists from REST controller (module1) and some main logic (module2). Big picture of our application architecture is:

EE multi module application

So, lets do initialization of project with next gradle template:
settings.gradle:

rootProject.name = 'ee-application-multi-module-gradle-template'
include 'module1'
include 'module2:module2-api', 'module2:module2-core'

root build.gradle:

defaultTasks 'clean', 'build'
subprojects {
    ext.libraryVersions = [
        javaee                  : '8.0',
    ]
    defaultTasks 'clean', 'build'
    repositories {
        jcenter()
    }
}

Above, we described initial application structure, where module1 is flat sub project for our controller and module2 is our main logic which consists from API and Core sub projects. As controller will use main logic API and we decided to separate application to modules (that means no big enterprise archive) - our sub projects should be simple enough:

module1 build.gradle:

apply plugin: 'war'
dependencies {
    compile project(':module2:module2-api')
    providedCompile "javax:javaee-api:${libraryVersions.javaee}"
}

module2:module2-api:

apply plugin: 'java'
dependencies {
}

module2:module2-core:

apply plugin: 'war'
dependencies {
    compile project(':module2:module2-api')
    providedCompile "javax:javaee-api:${libraryVersions.javaee}"
}

Actually, that's it!
Now we can implement our controller like:

@Path("/")
@Stateless
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class TestEndpoint {

    @EJB(lookup = TestService.TEST_SERVICE_JNDI)
    TestService testService;

    @GET
    @Path("/test")
    public Response test() {
        SomethingDto something = testService.doSomething();
        return Response.ok().entity(something.getMessage()).build();
    }

In turn, main logic API contents from Interface and DTO:
TestService.java:

public interface TestService {

  String TEST_SERVICE_NAME = "test-service";
  String TEST_SERVICE_JNDI ="java:global/module2-core/" + TEST_SERVICE_NAME;

  SomethingDto doSomething();
}

SomethingDto.java:

public class SomethingDto implements Serializable{
  ...
}

In the end, main logic Core contents from the logic that implements API:
TestServiceImpl.java

@Remote(TestService.class)
@Stateless(name = TestService.TEST_SERVICE_NAME)
public class TestServiceImpl implements TestService {

    @PersistenceContext
    EntityManager entityManager;

    @Override
    public SomethingDto doSomething() {
        TestEntity entity = entityManager.find(TestEntity.class, Long.MAX_VALUE);
        return new SomethingDto("Hello Jakarta EE world!");
    }
}

Described Jakarta EE application architecture allows us enjoy all power of EE with absolutely transparent inter module interactions and, the same time, stay close to micro service design - as we have no limits with using one container for all modules.

Source code of this demo available on GitHub

Comments


How to catch 'kill' signals in java

07 August 2019

You can send different signals to your application using kill -l command. By default kill will sent TERM signal. Java by default catches some types of signals, for example

kill -3 <PID>

will dump Java stack traces to the standard error stream.

Also, you can catch signal inside your application, like

public class App {
    public static void main(String... s) throws Exception {

        Signal.handle(new Signal("HUP"), signal -> {
            System.out.println(signal.getName() + " (" + signal.getNumber() + ")");
        });

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1000l);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

List of available signals you can get by executing kill -l:

kostenko@kostenko:~$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX

Notice! Not all signals can be catched in application, some of them reserved by OS. For example, if you will try to handle kill -SIGKILL (kill -9) , then you get:

Exception in thread "main" java.lang.IllegalArgumentException: Signal already used by VM or OS: SIGKILL
	at java.base/jdk.internal.misc.Signal.handle(Signal.java:173)
	at jdk.unsupported/sun.misc.Signal.handle(Signal.java:157)

Comments


Wildfly. Configure load balancing metrics

06 August 2019

Previously i wrote about Wildfly domain mode cluster and load balancing from the box. But what if we would like to do balancing depends on specific server behavior ?

Wildfly subsystem mod_cluster provide us several predefined metric types to determine best request balancing:

As well you also can configure weight (impact of a metric respect to other metrics) and capacity properties;
Below is example, how to change default based on CPU balancing to balancing based on busyness + CPU:

/subsystem=modcluster/mod-cluster-config=configuration/dynamic-load-provider=configuration/load-metric=cpu:remove()
/subsystem=modcluster/mod-cluster-config=configuration:add-metric(type=busyness,weight=2)
/subsystem=modcluster/mod-cluster-config=configuration:add-metric(type=cpu,weight=1)

If predefined types is not enough, - you can provide custom-load-metric by implementing org.jboss.modcluster.load.metric.impl.AbstractLoadMetric. To possibility of using your custom metric,- you need to copy packaged JAR to modcluster module and update module.xml. Now you can use your custom metric with your configuration like

 <custom-load-metric class="org.kostenko.examples.wldfly.modcluster.MyBalancingMetric">  

Comments