Java приложение как служба windows

Введение

В общем, расскажу я вам сказку про Terracota’овский сервер.

В одной далёкой галактике

На одной из наших виртуалок на конторе, жила-была ВебСфера(прожорливая сволочь), которая голодала от недостатка места на жёстом диске и, как результат, приложения живущие на ней начинали сильно лагать, вследствие чего приходилось часто приходилось ребутать вирталку для нормальной жизни приложений на сфере. Но не одиноки мы во вселенной(возможно), тем не менее на Земле так точно не одни, так и на виртуалке кроме сферы жили и другие монстры, куда менее прожорливые, вроде Terracotta сервера и других приложений. Так вот,

вследствие перерождения галактики

перезагрузки виртуалки терракотовский сервак постоянно надо было поднимать, так как наши приложения хранящие данные в кластере не могли запуститься, потому ожидали коннекшена от лежачего сервака. Естественно, кому-то из команды постоянно приходилось запускать Терракотту вручную, что, в общем, то было утомительно:). Мною было принято решение

создать галактический отряд

windows сервис по поднятию сервера после перезагрузки виртуалки, что казалось задачей на 15 минут, и тут я наткнулся на

Дарта Вейдера

подводные камни. Хренова конечно, что из коробки в терракоте нет создания сервиса после установки.

К делу

Посмотрим, что у нас есть:

  1. Windows Server 2008 какой-то edition(с установленным Windows Resource Kit Tools).
  2. Установленная JDK6
  3. Terracotta
  4. Световые мечи

Чего не хватало:

  1. Пива
  2. srvany.exe – утилита, позволяющая запускать любую программу как службу, позволяя тем самым создавать пользовательские службы(странно но у меня на виртуалке этого файла не было). Скачаваем с инета.
  3. Знаний использования реестра.(Этот недостатот быстро отпадает)

Для начала скопируем скачанный srvany.exe в папки /bin с терракотой. В моём случае нехватало батника для создания сервиса, т.к. путь к терракоте содержал
пробелы. Если кто знает как в консоли прописывать пути без пробелов, прошу писать в комменты.
Сообственно createService.bat:
sc.exe create Terracotta binPath=“c:\Program Files\terracotta-3.2.1_1\bin\srvany.exe” type=own start=auto DisplayName=“Terracotta Server 3.2.1_1”
Думаю пояснений не требуется. Windows сервис требует данных о приложении в регистре. Создаём tcservice.reg:

REGEDIT4
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Terracotta\Parameters]
"Application"="\"C:\\Java\\jdk1.6.0_17\\bin\\java.exe\\"
"AppParameters"="-cp c:\\Program Files\\terracotta-3.2.1_1\\lib\\tc.jar -server -Xms4G –Xmx4G -XX:+HeapDumpOnOutOfMemoryError -Dtc.install-root=c:\\Program files\\terracotta-3.2.1_1 com.tc.server.TCServerMain"
"AppDirectory"="c:\\Program Files\\terracotta-3.2.1_1\\"

И запускаем его. Не знаю почему, да и в общем то времени на разборку не было, но скрипт у меня не запускался, а данные в регистр не попадали:(. Поэтому делаем всё ручками. Запускаем regedit, заходим по пути HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Terracotta\Parameters и создаём там строковые параметры типа Application с указанием путей типа С:\\Java\\jdk1.6.0_17\\bin\\java.exe Также можно применить дополнительные параметры, если терракота работает не с дефолтовыми настройками:

"AppParameters"="-cp c:\\ Program Files \\terracotta-3.2.1_1\\lib\\tc.jar -server –Xms512M –Xmx512M -XX:+HeapDumpOnOutOfMemoryError -Dtc.install-root=c:\\terracotta\\terracotta-3.2.1_1 com.tc.server.TCServerMain -f c:\\ Program Files \\my-tc-config.xml -n Server1"

Всё сделали. Тестим заходим в Панель Управления -> Администрирование –> Службы, ищем сервис с названием Terracotta Server 3.2.1_1. Запускаем. Провеяем порты и видим, что приложение стартануло, если нет, проверьте правильность указания путей. Надо бы ещё убедиться что приложение встанет после перезагрузки виртуалки. Значит, что делаем?

Выключаем сервер из розетки

перезагружаем виртуалку – видим, что сервер поднялся автоматически. Ура. Таким макаром можно любое Java приложение сделать как windows сервис.

Пройдите тест, узнайте какой профессии подходите

Работать самостоятельно и не зависеть от других

Работать в команде и рассчитывать на помощь коллег

Организовывать и контролировать процесс работы

Быстрый ответ

Чтобы преобразовать ваше Java-приложение в службу Windows, вы можете использовать инструмент Apache Commons Daemon’s prunsrv. Для этого выполните следующую команду:

Замените myAppPath на путь к вашему приложению, ВашОсновнойКласс на имя вашего основного класса и добавьте методы startService и stopService для управления жизненным циклом службы. С помощью prunsrv.exe вы сможете управлять службой: запускать, останавливать и удалить её.

Кинга Идем в IT: пошаговый план для смены профессии

Доступные инструменты

В вашем распоряжении множество инструментов для создания службы. Для систем на базе Windows рекомендуется использовать Procrun из пакета Apache Commons Daemon, а для Unix-систем подходит Jsvc.

Руководство по созданию службы

Если не хотите вносить изменения в существующие методы приложения, создайте отдельный загрузочный класс, который будет взаимодействовать с Procrun, принимая команды start и stop.

Настройка и управление

WinRun4J предоставляет возможности для детализированной настройки: вы сможете задавать собственные иконки и отслеживать состояние вашей службы через системный трей.

Визуализация

Ваше Java-приложение превращается в автономную службу Windows с помощью мощного инструмента Apache Procrun.

Подготовка вашего Java-приложения к работе в качестве службы

Чтобы преобразовать ваше приложение в службу, выполните следующие действия:

  • Упакуйте приложение в .jar файл.
  • Настройте Procrun таким образом, чтобы он запускал ваш .jar файл при необходимости.
  • Ищете вдохновение? Обратите внимание на успешные проекты, такие как Tomcat, или изучите Java Service Wrapper и WinRun4J.

Выбор наиболее надежного решения для долгосрочной работы

Выбирайте решение, которое обеспечит стабильность и надежность вашей службы в долгосрочной перспективе:

  • YAJSW на GitHub характеризуется стабильной работой и регулярными обновлениями.
  • WinRun4J предлагает на выбор удобные инструменты мониторинга.

Полезные материалы

  1. Daemon – Daemon: Java based daemons or services — официальная документация Apache по созданию нативных служб на основе Java-приложений.
  2. GitHub – yajsw/yajsw: Mirror of YAJSW repository — GitHub-репозиторий с надежным решением для создания обертки Java-сервиса.
  3. WinRun4J — гибко настраиваемый Java Service Wrapper.
  4. Download Java Service Wrapper — Скачайте Tanuki Wrapper для повышения защищенности и управляемости вашего программного обеспечения.
  5. WrapperSimpleApp Integration (Windows) — пошаговое руководство интеграции Tanuki Java Service Wrapper.
  6. How to create a windows service from java app – Stack Overflow — обсуждение на форуме Stack Overflow, где знаниями делится профессиональное сообщество.
  7. Daemon – Daemon: Procrun — подробная документация для освоения Procrun.

In this blog post, I show you how to install a Java application with WinSW as a Windows service.
WinSW is an executable binary, which can be used to wrap and manage any custom process as a Windows service.

Demo ¶

First, we need a demo application. I will use a simple Quarkus application for this purpose.
You can install any Java application as a service. Usually, you install applications that run continuously, like an HTTP server in this case.

To bootstrap a Quarkus application, run this command:

mvn io.quarkus:quarkus-maven-plugin:2.5.1.Final:create -DprojectGroupId=com.testlab -DprojectArtifactId=testservice -DclassName="com.testlab.testservice.GreetingResource" -Dpath="/hello"
cd testservice

We will use the application as is, with just a small change. I want to create a fat JAR, a JAR with all dependent libraries included.
You can package your application in any way you want. In this case, I prefer the fat JAR installation because I only have to copy one file.

Open src\main\resources\application.properties and insert the following property:

quarkus.package.type=uber-jar

Now you can package the application with .\mvnw.cmd package. You will find the JAR
in the target folder: testservice-1.0.0-SNAPSHOT-runner.jar.

Preparation ¶

You can proceed in different ways. I usually create a new folder where I copy all the files needed to
run the application as a service. Copy the JAR from the target folder into this directory.

Java ¶

Next, I download the Java Runtime and also copy it into this folder. This is optional. Your service can access
a globally installed Java. But I prefer to have everything contained in one folder and not have to worry about someone updating
or removing the globally installed Java.

I usually download Java from Adoptium. On the release page, you will find the ZIP file with the JDK for Windows.

Download the ZIP file and unzip it into the install folder. I unzip it into the java subfolder, so the java.exe
is accessible with this path java\bin\java.exe.

WinSW ¶

Open the release page of the WinSW project and download the executable suitable for your platform.
https://github.com/winsw/winsw/releases

For this demo installation, I will download WinSW.NET461.exe. WinSW runs on Windows with .NET Framework 2.0, 4.0, or 4.6.1. If you need to install
the service on a Windows system without the .NET framework, download the core variant WinSW-x64.exe for 64-bit or WinSW-x86.exe for 32-bit systems.

Copy the executable into the folder where your JAR resides. Rename the WinSW executable to any name you like.
For this example, I will rename it to testservice.exe. Create an XML file with the same base name: testservice.xml.
Make sure that the EXE and XML files are located in the same folder.

Open the XML file and paste the following code into it:

<service>
  <id>testservice</id>
  <name>Test Service</name>
  <description>This is a test service.</description>
  <executable>"%BASE%\java\bin\java"</executable>
  <arguments>-jar "%BASE%\testservice-1.0.0-SNAPSHOT-runner.jar"</arguments>
  <logmode>rotate</logmode>
  <stopparentprocessfirst>true</stopparentprocessfirst>
</service>

Check the executable path and arguments. %BASE% is an environment variable that points to the directory where the WinSW executable is located.
If you want to start the application with a Java that is on the %PATH%, just use <executable>java</executable>.

Relevant here is <stopparentprocessfirst>. This tells WinSW to shut down the parent process first. In our case, this is useful
because the main process opens a console (java), which can respond to Ctrl+C and will gracefully shutdown the child process (the Java application).

Check out this wiki page to learn more about all the supported options:
https://github.com/winsw/winsw/blob/master/doc/xmlConfigFile.md

Directory structure ¶

The directory structure of my install folder:

testservice.exe
testservice.xml
testservice-1.0.0-SNAPSHOT-runner.jar
java
  bin
    java.exe
    ...
  conf
  legal
  lib
  ...

Installation ¶

With everything in place, you can install the Windows service with this command:

testservice.exe install

The WinSW command supports the following options:

  • install: Install the service
  • uninstall: Uninstall the service
  • start: Start the installed service
  • stop: Stop the service
  • restart: Restart the service
  • status: Show the current service status (NonExistent, Started, Stopped)

The service by default is installed with start mode Automatic. That means Windows starts
the service when it boots up. You can change that with the <startmode> configuration in the XML file.

  <startmode>Manual</startmode>

To test the installation, open http://localhost:8080 in a browser. You should see the default start page of Quarkus.
To test if the graceful shutdown works, stop the service:

testservice stop

Open the file testservice.out.log.

2020-05-06 05:30:52,501 INFO  [io.quarkus] (main) Profile prod activated. 
2020-05-06 05:30:52,501 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]
2020-05-06 05:30:54,801 INFO  [io.quarkus] (main) testservice stopped in 0.032s

We see that the application shutdown gracefully because of the testservice stopped log entry.

Note that WinSW creates by default three log files:

  • <service>.out.log: Console output from the application (System.out.println)
  • <service>.err.log: Error output from the application (System.err.println)
  • <service>.wrapper.log: Log output from WinSW itself

That concludes this tutorial about installing any Java applications as a Windows Service.
Optionally, you could try and create a native image of your application with
GraalVM.
The service installation does not change much. You don’t need the JRE
anymore and have to change <executable> accordingly.

Join the DZone community and get the full member experience.

Join For Free

I recently needed to run a Java program as a Windows service and opted for Commons-daemon procrun. This wrapper is used by both Tomcat and JBoss Wildfly to wrap their servers — but it took a bit of figuring out how to get my application running.

This post sets out an example of using procrun to wrap a Java process.

Download

I downloaded procrun from here. The download contains three different version of the procrun.exe:

  • 32 bit: This is the default architecture.
  • amd64: 64-bit AMD architecture.
  • ia64: 64-bit Intel Itanium architecture.

You need to use the right version for your JVM and chipset

Code

The code is based on the EchoServer and EchoClient examples from Oracle.

EchoServer

import java.net.*; 
import java.io.*;   
public class EchoServer {     
  public static void main(String[] args) throws IOException {
    if (args.length != 1) {
      System.err.println("Usage: java EchoServer <port number>");
      System.exit(1);         
    }           

    int portNumber = Integer.parseInt(args[0]); 
    try (ServerSocket serverSocket = new ServerSocket(Integer.parseInt(args[0]));
         Socket clientSocket = serverSocket.accept(); 
         PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
         BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        ) {
      String inputLine;             
      while ((inputLine = in.readLine()) != null) {
        out.println(inputLine);             
      }         
    } catch (IOException e) {
      System.out.println("Exception caught when trying to listen on port " + portNumber + " or listening for a connection");   
      System.out.println(e.getMessage());         
    }
  }
}

EchoClient

The client is changed to take a shutdown parameter:

import java.io.*; 
import java.net.*;   
public class EchoClient {     
  public static void main(String[] args) throws IOException {
    if (args.length != 3) {             
      System.err.println("Usage: java EchoClient <host name> <port number>");  
      System.exit(1);
    }

    String hostName = args[0];         
    int portNumber = Integer.parseInt(args[1]);         
    String shutdown = args[2];           

    try (Socket echoSocket = new Socket(hostName, portNumber);             
         PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true); 
         BufferedReader in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));             
         BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) {
      String userInput;             
      if (shutdown != null && !"".equals(shutdown)) { 
        userInput = shutdown;             
      }             

      while ((userInput = stdIn.readLine()) != null) {
        out.println(userInput);                 
        System.out.println("echo: " + in.readLine());  
      }         
    } catch (UnknownHostException e) {
      System.err.println("Don't know about host " + hostName); 
      System.exit(1);         
    } catch (IOException e) {
      System.err.println("Couldn't get I/O for the connection to " +  hostName);
      System.exit(1);         
    }
  }
}

Prunssrv

I’ve also created a simple class to stop and start the server:

import java.net.*; 
import java.io.*; 
public class Prunssrv {
  public static void prunsrvStartServer(String[] args) throws Exception {
    String[] newArgs = new String[1];         
    newArgs[0] = System.getProperty("prunsrv.port"); // -Dprunsrv.port=8080         
    EchoServer.main(newArgs);     
  }          

  public static void prunsrvStopServer(String[] args) throws Exception { 
    String[] newArgs = new String[2];         
    newArgs[0] = System.getProperty("prunsrv.server"); // -Dprunsrv.server=localhost         
    newArgs[1] = System.getProperty("prunsrv.port"); // -Dprunsrv.port=8080         
    newArgs[1] = "shutdown";                  
    EchoClient.main(newArgs);     
  } 
}

Putting it all together:

  1. Add the above classes and procrun.exe to a directory – C:\procrun
  2. Compile – javac *.java
  3. Create Archive – jar cvf simpleechoserver.jar *.class *.jar

Service.bat

You don’t need to create a service.bat file, but it’s cleaner and simpler. Store this in your code directory.

@echo off 
setlocal 

set SERVICE_NAME=SimpleEchoServer 
set PR_INSTALL=%~dp0%prunsrv.exe 
set PR_DESCRIPTION="Simple Echo Server Service" 

REM Service log configuration 
set PR_LOGPREFIX=%SERVICE_NAME% 
set PR_LOGPATH=%~dp0%\ 
set PR_STDOUTPUT=%~dp0%\stdout.txt 
set PR_STDERROR=%~dp0%\stderr.txt 
set PR_LOGLEVEL=Debug   

REM Path to java installation 
set PR_JVM=%JAVA_HOME%\jre\bin\server\jvm.dll 
set PR_CLASSPATH=simpleechoserver.jar   

REM Startup configuration 
set PR_STARTUP=auto 
set PR_STARTMODE=jvm 
set PR_STARTCLASS=Prunssrv 
set PR_STARTMETHOD=prunsrvStartServer   

REM Shutdown configuration 
set PR_STOPMODE=jvm 
set PR_STOPCLASS=Prunssrv 
set PR_STOPMETHOD=prunsrvStopServer 
set PR_STOPTIMEOUT=120   

REM JVM configuration 
set PR_JVMMS=256 
set PR_JVMMX=1024 
set PR_JVMSS=4000 

REM JVM options 
set prunsrv_port=8080 
set prunsrv_server=localhost 
set PR_JVMOPTIONS=-Dprunsrv.port=%prunsrv_port%;-Dprunsrv.server=%prunsrv_server% 

REM current file 
set "SELF=%~dp0%service.bat" 

REM current directory 
set "CURRENT_DIR=%cd%"   

REM start - This takes the input from installService and places it between x's 
REM       - if there are none then you get xx as a null check 
if "x%1x" == "xx" goto displayUsage 
set SERVICE_CMD=%1 
REM ahift moves to next field 
shift 
if "x%1x" == "xx" goto checkServiceCmd 
:checkServiceCmd 
if /i %SERVICE_CMD% == install goto doInstall 
if /i %SERVICE_CMD% == remove goto doRemove 
if /i %SERVICE_CMD% == uninstall goto doRemove 
echo Unknown parameter "%SERVICE_CMD%" 
:displayUsage 
echo. 
echo Usage: service.bat install/remove 
goto end 
:doRemove 
echo Removing the service '%PR_INSTALL%' '%SERVICE_NAME%' ... 
%PR_INSTALL% //DS//%SERVICE_NAME% 
if not errorlevel 1 goto removed 
echo Failed removing '%SERVICE_NAME%' service 
goto end 
:removed 
echo The service '%SERVICE_NAME%' has been removed 
goto end 
:doInstall 
echo Installing the service '%PR_INSTALL%' '%SERVICE_NAME%' ... 
%PR_INSTALL% //IS//%SERVICE_NAME% 
goto end 
:end 
echo Exiting service.bat ... 
cd "%CURRENT_DIR%"

Key Points

  • All the Procrun fields are marked with PR_ — you can also feed these fields directly to procrun.exe using the ++ or — notation in the procrun notes, but I think this way is cleaner and easier to maintain.
  • The key ones are the start/stop fields.
  • PR_JVMOPTIONS: Allows us to pass system properties to the Windows Service
  • Installing and removing:
    %PR_INSTALL% //IS//%SERVICE_NAME%
    %PR_INSTALL% //DS//%SERVICE_NAME%
  • There are other “//” options defined in the notes

Running service.bat

You may need to run this as administrator:

C:\procrun>service.bat Usage: service.bat install/remove Exiting service.bat ...

To install:

service.bat install

And uninstall:

service.bat remove

You can then test:

java EchoClient localhost 8080 hello echo: hello ...

If you go to your Windows Services, you will now see SimpleEchoServer with stop/start/restart options

Prunmgr.exe

The final trick is to use prunmgr. This the procrun manager and allows you to see the procrun operating parameters. To get started, go to your copy of prunmgr.exe and rename or copy it to the SERVICE_NAME in your batch file:

set SERVICE_NAME=SimpleEchoServer

So:

C:\procrun>copy prunmgr.exe SimpleEchoServer.exe

You then run the SimpleEchoServer.exe as administrator.

Java (programming language)

Published at DZone with permission of Martin Farrell, DZone MVB.

See the original article here.

Opinions expressed by DZone contributors are their own.

Related

Introduction

One project required the development of a Windows service that could perform a number of actions using the Windows API, Websocket and standard Java tools. The article below gives the description of the steps that have been taken to create such a service.

The need for the Windows service arose because of the necessity to have a software with the following features:

  • it should be constantly running,
  • it should be run by a system user,
  • it should automatically start when the system starts,
  • it should be difficult to be terminated by an ordinary user.

Creating a minimalized JRE version

As GraalVM still does not support creation of executable files for Windows, it was decided to take advantage of other capabilities offered by the Java ecosystem, specifically, creation of a minimalized JRE version.

In order to create the minimized JRE version, first it is needed to know the dependencies on certain packages that will be included in the JRE.

First of all, it is necessary to create the “fat jar” file with all dependencies.

Then run the jdeps -s <path to jar file> command to get a list of all dependencies. For example:

jdeps -s application.jar
application.jar -> java.base
application.jar -> java.datatransfer
application.jar -> java.desktop
application.jar -> java.logging
application.jar -> java.net.http
application.jar -> java.sql
application.jar -> java.xml
application.jar -> jdk.unsupported
application.jar -> not found

After that, create your version of JRE with these dependencies:

jlink –module-path <path to the jmods folder, which is located in jdk> –add-modules

java.base, java.datatransfer, java.desktop, java.logging, java.net.http, java.sql, java.xml, jdk.unsupported –strip-debug –compress 2 –no-header-files –no-man-pages –output <name of the folder that will contain the generated JRE>

Note that the listed packages for –add-modules option should be separated by a comma with no spaces between them. The other options are responsible for compressing and removing files and other information that is not useful for software execution.

After performing these actions, the JRE will take around 30 mb instead of hundreds.

Creating a Windows service from any application

Java does not have standard services creation tools, so third-party tools were studied and WinSW has been selected because it is free and easy to use.

services banner

WinSW

WinSW is a utility that allows to start and wrap any process as a Windows service. In order to start working with it, you need to download executable and configuration files through this link https://github.com/kohsuke/winsw/releases.

Place these two files in the directory. Rename the executable file at your discretion and give the same name to the configuration file, then place the application’s jar file and the created JRE in this directory.

Write a minimum configuration in the configuration file:

<configuration>
<!– ID of the service. It should be unique across the Windows system–>
<id>service id</id>
<!– Display name of the service –>
<name>name</name>
<!– Service description –>
<description>Description</description>
<!– Path to the executable, which should be started –>
<executable>jre\bin\java.exe</executable>
<arguments>-jar application.jar</arguments>
</configuration>

jre\bin\java.exe – the relative path inside our folder to our JRE executable file.

After these actions, you can install the service by running the command as the administrator:

winsw.exe install

The list of commands is available here.

Interaction between Java and Windows API

To use Windows functions (such as creating a new process or adding registry keys) we used JNA in our application.

JNA (Java Native Access) provides Java software with easy access to libraries written in another language without writing anything but Java code. JNA allows calling directly native functions using natural Java method invocation. Most methods require no special handling or configuration; no boilerplate or generated code is required.

Connecting and working with JNA is very easy, you need to download the jar file or connect the dependency to a project builder, which is Maven in our case:

<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.0.0</version>
</dependency>

In our project we used JNA to achieve the following goals: disable and enable the task manager 1) through the Ctrl+Shift+Esc combination, and 2) in the menu available by the Ctrl+Alt+Del combination.

To achieve these goals, we used the Advapi32Util class (an easy-to-use wrapping around the advapi32.dll library) and the WinReg interface with useful constants which provide functionality to make changes to the Windows registry (Figure 1. TaskManager class with enable() and disable() methods to modify the task manager registry keys).

Task manager

Figure 1. TaskManager class with enable() and disable() methods to modify the task manager registry keys.
  • Create a new process on behalf of a specific Windows user. For this purpose we used the CreateProcessAsUser() method of the Advapi32 interface. The following parameters should be transferred to the method:
  • hToken – a handle to the primary token that represents a user for whom we start the process.
  • lpApplicationName – the name of the module to be executed.
  • lpCommandLine – the command line to be executed.
  • lpProcessAttributes – a pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new process object and determines whether child processes can inherit the returned handle to the process.
  • lpThreadAttributes – a pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new thread object and determines whether child processes can inherit the returned handle to the thread.
  • bInheritHandles – if this parameter is TRUE, each inheritable handle in the calling process is inherited by the new process. If the parameter is FALSE, the processes are not inherited.
  • dwCreationFlags – the flags that control the priority class and create the process.
  • lpEnvironment – a pointer to an environment block for the new process. If the parameter is NULL, the new process uses the environment of the calling process. An environment block consists of a null-terminated block of null-terminated strings. Each string is in the following form: name = value \ 0.
  • lpCurrentDirectory – the full path to the current directory for the process. The string can also specify a UNC (universal naming convention) path.
  • lpStartupInfo – a pointer to a STARTUPINFO or STARTUPINFOEX.lpProcessInformation structure – a pointer to a PROCESS_INFORMATION structure that receives identification information about the new process.
Windows user

Figure 2. A method for creating a new process for the specific Windows user.
  • Receive an active user token, as it is necessary to create a process from the specific user.
Java windows service

Working with processes

For working and tracking processes on Windows, we used the ProcessHandle class added to Java 9. ProcessHandle allows receiving and make various manipulations with processes. In particular, when solving the task, it was required to collect PIDs of processes, filter processes based on the name and abort necessary processes.

Working with processes

Figure 3. ProcessHandler class with takeSnapshot() method for taking a snapshot of current processes and closeNewProcesses() method for termination of processes different from the snapshot.

Interaction with other system components

WebSocket

For Java there is a standard API for working with WebSocket.

<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>

But just the API was not enough, so one of its implementations Tyrus was chosen to run the code.

<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-server</artifactId>
<version>1.14</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly-server</artifactId>
<version>1.14</version>
</dependency>

Then you can create a minimalistic server and specify handlers (EndPoints).

var server = new Server(
“localhost”,
8080,
“/endpoints”,
null,
EndPoint1.class,
EndPoint2.class,
…);
try {
server.start();
Thread.currentThread().join();
} catch (Exception e) {
log.error(“Ooops! “, e);
} finally {
server.stop();
log.info(“Finally…”);
}

A handler skeleton is looking as follows:

@ServerEndpoint(value = “endpoint/url”)
public class SampleEndpoint {

@OnOpen
public void onOpen(Session session) throws IOException {
// Called when a new connection is initialized
}

@OnMessage
public void onMessage(Session session, Message message) throws IOException {
// Called when a message from the client is received
}

@OnClose
public void onClose(Session session) throws IOException {
// Called when a connection is closed
}

@OnError
public void onError(Session session, Throwable throwable) {
// Called when errors appear
}
}

HTTP Client

The release of the 11th version of Java brought us a convenient HTTP client, so there is no need for third-party clients.

To create a client instance, you need to use a builder. In the simplest case:

var client = HttpClient .newBuilder() .build()

After that, you need to create a request, for example:

var request = HttpRequest.newBuilder()
.uri(URI.create(“https://myserver.com”))
.timeout(Duration.ofMillis(1000))
.header(“Content-Type”, “application/json”)
.POST(bean.toJSON())
.build();

Then this request can be used for sending to the server:

var response = client.send(closeSession(sessionId, token),
HttpResponse.BodyHandlers.ofString())

Conclusion

Due to the modular organization of Java 9 and higher, WinSW utility, updated Process API for interaction with operating system processes and JNA (Java Native Access) library, which provides Java programs with easy access to native libraries, we were able to create a Windows service using Java language which was also used for the server part implementation. As the result, this allowed us not to introduce a new language into the development process.

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Как изменить размер открываемого окна в windows
  • Установить javascript бесплатно для windows 10
  • Как вернуться к стандартным настройкам windows
  • Как убрать браузер edge из автозапуска на windows 10
  • Windows 7 professional sp1 original by