I am trying to have a java program that is built with maven to run on a docker-compose scenario and hot reload as I make changes.
I added trava-jdk libvm on top of the original libvm and added the hotswapagent lib on the proper place. It gives me what I want when I run java -version
Starting HotswapAgent '/usr/local/openjdk-11/lib/hotswap/hotswap-agent.jar'
HOTSWAP AGENT: 10:18:24.771 INFO (org.hotswap.agent.HotswapAgent) - Loading Hotswap agent {1.4.0} - unlimited runtime class redefinition.
HOTSWAP AGENT: 10:18:24.992 INFO (org.hotswap.agent.config.PluginRegistry) - Discovered plugins: [JdkPlugin, Hotswapper, WatchResources, ClassInitPlugin, AnonymousClassPatch, Hibernate, Hibernate3JPA, Hibernate3, Spring, Jersey1, Jersey2, Jetty, Tomcat, ZK, Logback, Log4j2, MyFaces, Mojarra, Omnifaces, ELResolver, WildFlyELResolver, OsgiEquinox, Owb, Proxy, WebObjects, Weld, JBossModules, ResteasyRegistry, Deltaspike, GlassFish, Vaadin, Wicket, CxfJAXRS, FreeMarker, Undertow, MyBatis]
openjdk version "11.0.5" 2019-10-15
OpenJDK Runtime Environment 18.9 (build 11.0.5+10)
Dynamic Code Evolution 64-Bit Server VM 18.9 (build 11.0.5+5-202001261315, mixed mode)
My dockerfile to achieve that is the one below
FROM maven:latest
WORKDIR /tmp
RUN wget https://github.com/TravaOpenJDK/trava-jdk-11-dcevm/releases/download/dcevm-11.0.5%2B5/java11-openjdk-dcevm-linux.tar.gz
RUN tar -xvf java11-openjdk-dcevm-linux.tar.gz
RUN mv dcevm-11.0.5+5 /dcevm
WORKDIR /dcevm
RUN rm /usr/local/openjdk-11/lib/server/libjvm.so
RUN cp /dcevm/lib/server/libjvm.so /usr/local/openjdk-11/lib/server/
RUN cp -r /dcevm/lib/hotswap /usr/local/openjdk-11/lib/
Now I find myself a little lost on how to apply the hot reload on the Ide and properly run the code.
In case you are wondering why I need such a hack I have an IoT environment that has E2E tests and I wanted to be able to quickly iterate on new tests or failing tests without needing to recompile or restart containers.
I don't have an experience of working with this concrete hotswap agent, but in general to answer your question:
When you build the docker image, you are supposed to run your own application after all (via maven, with java -jar or in any other way) So, When you start the application process, you're supposed to make the application ready for remote debugging:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9999
You should expose a debug port in docker so that the IDE will connect to that port on host machine and it will be routed to port 9999 in docker container.
Make sure the application is running
In IDE create "Remote Debug configuration, in IntelliJ: Run/Debug Configurations -> Remote -> create new configuration and specify the host and exposed port that you've created during the step 2. You're supposed to be able to connect and place breakpoints in the code that will interact with IDE
If you do some change in some source file, right click and compile it while you're connected to remote debugging session.
If the change can be done, it will use hotswap at this point and will "upload" the new bytecode to the remote process right inside the docker in this case and will apply this changes without a reload.
By default JVM already provides Hotspot capabilities, but this library, I believe should provide more flexible/powerful options.
There is project HotswapDocklands dedicated to runnig HotswapAgent+dcevm in Docker. It is using mapping of in-Docker /extra_class_path directory to directory out of Docker. Then all modifications done on any file inside extra_class_path are "hotspapped" using extraClassPath to dcevm. To attach debugger you have to run dcevm with jdwp and expose debugger port from Docker.
Related
I just take over a project which is a java servlet application, I just figured out the way running the application is mvn jetty:run by using history. The previous only developer just quit suddenly, and there's no document. I have to create production server and deploy the application.
I have no previous Java experiences, so have not idea how to do it. Should I install nginx or apache and run the application like PHP? Or I just do something like nodejs ?
Jetty is a Java Servlet container/server (with many more features).
There's no need for another server.
You have a few choices on how to start Jetty.
Standalone server using the jetty-home (or the older jetty-distribution) tarballs.
In this mode you unpack the jetty-home tarball (this will become the ${jetty.home} directory), create a new directory for your configuration / deployment (this will become the ${jetty.base} directory), and then run Jetty against this ${jetty.base} directory.
There are many many examples online of how to do this.
From the official Jetty documentation at https://www.eclipse.org/jetty/documentation/current/
To various examples here on stackoverflow.
# Grab the tarball
[~]$ curl -O https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-home/9.4.30.v20200611/jetty-home-9.4.30.v20200611.tar.gz
# Unpack the tarball
[~]$ tar -zxvf jetty-home-9.4.30.v20200611.tar.gz
# Make a {jetty.base} directory to house your configuration
[~]$ mkdir myappbase
[~]$ cd myappbase
# Since this is a new {jetty.base}, lets initialize it with a
# few common modules
[myappbase]$ java -jar ../jetty-home-9.4.30.v20200611/start.jar \
--add-to-start=http,deploy
INFO : webapp transitively enabled, ini template available with --add-to-start=webapp
INFO : server transitively enabled, ini template available with --add-to-start=server
INFO : security transitively enabled
INFO : servlet transitively enabled
INFO : http initialized in ${jetty.base}/start.ini
...(snip)...
INFO : deploy initialized in ${jetty.base}/start.ini
MKDIR : ${jetty.base}/webapps
INFO : Base directory was modified
# Lets see what we have now
[myappbase]$ ls -F
start.ini webapps/
# Copy your webapp into place
[myappbase]$ cp ~/Projects/mywebapp.war webapps/
# See this Jetty Configuration
[myappbase]$ java -jar ../jetty-home-9.4.30.v20200611/start.jar --list-config
# Run Jetty
[myappbase]$ java -jar ../jetty-home-9.4.30.v20200611/start.jar
Embedded Jetty
This means you have initialized everything entirely in code, from the Server object, to the ServerConnector, to the WebAppContext (or the ServletContextHandler) and are issuing a Server.start(); to make the Server execute.
This is probably the more common usage of Jetty, we find far more users on this approach then the standalone approach.
For development using the jetty-maven-plugin
This is what you have discovered already.
In a maven project with <packaging>war</packaging> you can execute the various jetty-maven-plugin goals to do various things with that maven project during development time.
NOTE: This mode is not suitable for production!
jetty:run is the jetty-maven-plugin and the run goal.
See: https://www.eclipse.org/jetty/documentation/current/jetty-maven-plugin.html
Alternate environments where Jetty is embedded.
This mode is seeing increasing use, and if your application is using libraries like Spark or SpringBoot then you are essentially using Jetty under the covers, and have no need for a separate server installation / configuration, it's all done within the API/SDK of that library.
Built a new Windows Server 2016 to act as a target for jenkins orchestrated builds. We are not supposed to use oracle java anymore, so I got coretta openJDK. OpenJDK does not support javaws any more. The executable does not ship with it. I have seen some scripted workarounds, but they do not work and are poorly written to boot.
What are we supposed to use to launch slave agents on Windows machines?
There are several ways to implement this but since this is a windows server you can follow steps on https://github.com/kohsuke/winsw/blob/master/doc/installation.md#winsw-installation-guide to install jenkins slave as service without javaws.
I believe #Mike was referring to: Install Slave as a Windows service (cmd version), which does not need JNLP/javaws.
OR, under Jenkins 2 (we are using 2.121.1 plus WMI Windows Agents (aka windows-slaves:1.4), there is now an option to "Let Jenkins control this Windows slave as a Windows service", essentially in the same fashion as a Linux node.
You must have an Admin account (and password). We had to follow the guidance to edit registry when "Windows agents fail to start via DCOM" (Guidance is for Server 2012) to remotely manage the service. So far, seems to be working OK, YMMV. So far, seems to be working OK, no "subtle probelms"; YMMV.
For entries:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Wow6432Node\CLSID{72C24DD5-D70A-438B-8A42-98424B88AFB8}
HKEY_CLASSES_ROOT\CLSID{76A64158-CB41-11D1-8B02-00600806D9B6}
(There are several matches for the keys; just change the two locations indicated)
Launch 'regedit' (as Administrator)
Find (Ctrl+F) the following registry key: "{72C24DD5-D70A-438B-8A42-98424B88AFB8}" in
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Wow6432Node\CLSID\
Right click and select 'Permissions'
Change owner to administrators group (Advanced...).
Change permissions for administrators group. Grant Full Control.
Change owner back to TrustedInstaller (user is "NT Service\TrustedInstaller" on local machine)
Repeat the steps 1-6 for HKEY_CLASSES_ROOT\CLSID{76A64158-CB41-11D1-8B02-00600806D9B6}
Restart Remote Registry Service (Administrative Tools / Services)
For me the easiest and best working solution to launch Windows Jenkins Agents without JNLP was to run in the command prompt java -jar agent.jar ... command. The command parameters should be grabbed from the url of the agent:
http://your_jenkins_url/computer/your_agent_name_or_ip/
I downloaded the agent.jar on my PC, moved it to a desired directory, launched the Command Prompt from the dir where the agent.jar was moved and executed the proposed command with the appropriate parameters.
In my case:
java -jar agent.jar -jnlpUrl http://your_jenkins_url/computer/your_agent_name_or_ip/slave-agent.jnlp -secret 76986574e97c2b635c7076740dc93326eaaf5a3ad30573144915489a1ccfee44 -workDir "D:\jenkins"
This was one of the proposed approaches in the docs here - https://www.jenkins.io/doc/administration/requirements/upgrade-java-guidelines/
Java Web Start Java Web Start has been removed in Java 11. When a
Jenkins controller is running on Java 11, the Java Web Start button
will no longer appear in the Web UI. Agents for a Java 11 Jenkins
server can’t be launched from a *.jnlp file downloaded to a web
browser.
There are no plans to replace this functionality. Connect agents to
Jenkins on Java 11 with plugins like SSH Build Agents Plugin, with
operating system command line calls to java -jar agent.jar, or by
using containers.
I am using java 1.8 and spring-boot-starter-parent 1.5.6.RELEASE and swagger2 2.6.1. We run the application in the VM using the following command,
nohup java -jar myApplication.jar &
My application is getting stopped when the VM is stopped. So manually I need to start my application. I don't want to do that manually. I need to restart my application programmatically or any script will do this that is also fine for me.
How do I restart my application when VM is started??
Kindly provide your inputs.
In a Linux distribution which uses systemd (official docs here) (such as Debian, Ubuntu, or Fedora), creating a service is simple:
We'll need to create a service file which tells systemd how to start your application. Create a file in /etc/systemd/system named something like myApplication.service containing these lines:
[Unit]
Description="A description of what my application does"
[Service]
ExecStart=/path/to/java -jar /path/to/your/myApplication.jar
[Install]
WantedBy=multi-user.target
(Derived from an example in the docs.)
Then run systemctl enable myApplication.service as root to enable it, which will make it run on boot.
There's lots more you can learn; the docs for systemd are quite good. You might take a look at the blog story which introduced systemd as well, as that provides something of a "sales pitch" for what it can do.
I have a custom instance running on Windows Server 2016 where I need to monitor my Java processes.
I setup Stackdriver, installed the monitoring agent and followed this guide for JVM monitoring https://cloud.google.com/monitoring/agent/plugins/jvm
However no matter what I do I can not see any of my processes when setting up an Alerting policy within Stackdriver's console.
There are 2 steps in the guide I am unsure how to follow:
On your VM instance, download jvm-sun-hotspot.conf from the GitHub configuration repository and place it in the directory
/opt/stackdriver/collectd/etc/collectd.d/
Where exactly do I place the .conf file?
Edit the downloaded configuration file and replace JMX_PORT by the port on which your JVM is configured to allow JMX connections.
How do I get the port?
Sorry if this seems obvious but I'm pretty new to this.
Thanks in advance for your help.
All the steps and instructions on the JVM plugin page have instructions relevant for linux, and windows is not even mentioned there. So it could be quite possible that the JVM plugin is supported only on linux.
Since your code is already running on a JVM, you might want to consider if it is possible to move your application from a Windows VM to a linux VM.
Enabling the JVM monitoring plugin
Java Virtual Machines are monitored via JMX.
On your VM instance, download jvm-sun-hotspot.conf from the GitHub
configuration repository and place it in the directory
/opt/stackdriver/collectd/etc/collectd.d/:
(cd /opt/stackdriver/collectd/etc/collectd.d/ && curl -O https://raw.githubusercontent.com/Stackdriver/stackdriver-agent-service-configs/master/etc/collectd.d/jvm-sun-hotspot.conf)
Edit the downloaded configuration file and replace JMX_PORT by the
port on which your JVM is configured to allow JMX connections.
After adding the configuration file, restart the monitoring agent by
running the following command:
sudo service stackdriver-agent restart
Information on other plugin configuration options can be found at
collectd.org.
I want to deploy a a project to ec2. It was modify in Intellij which used MAVEN. It work perfect in Intellij. Below is the configuration of Intellij.
I have tried command line like java, javac. These kind of comment lines are all failed. I am wondering there must some way to convert Intellij configuration to command lines. I was relying too much on IDE. XD. Now I am regreted.
EC2 is the amazon cloud service for instances. If you aren't very experienced with it - the easiest you can do is to hire a machine with your fav operating system - for example Windows and use remote desktop to log in it and just do your normal IDE setup and run your app. You will have your app running on your instance and it will be working, even it is done the hard way. I will get downvotes for that, but it will work as a Swiss watch.
It depends from the kind of EC2 instance you're using.
For me would be simpler if it was a Linux instance.
I'll connect via ssh and git clone my project there from my bitbucket/github repository.
Then I'll use Maven, and there are many different options to run your project with Maven.
As suggested in the comments you could use the exec plugin.
But even in this way you'll have a list of problems to overcame.
For example your linux instance does not came with an preinstalled Java Runtime.
You have to install at least Java and Maven (choose ubuntu distro, so you can do easily with a package manager like apt-get).
Or, for example, another not easy task is connect via ssh to a Linux instance.
AWS generates a key.pem file that you have to use in order to successfully connect to your instance.
ssh -i .ssh/your-key-file.pem username#your-ec2-instance-address
And again, AWS does not tell you the name of the default user you must use to connect to your EC2 instance (if you choose ubuntu distro the username is ubuntu).
And again, when you save your-key-file.pem in your computer it must have the right permission
-rw-------# 1 freedev staff 1692 Apr 21 09:46 /Users/freedev/.ssh/your-key-file.pem
or your ssh client wont read it.
...looking back it was really a long way make a deploy on a EC2 instance.
I have solved it by myself.
Use mvn package to generated jar file for maven project.
nohup java xx.jar debug.xml & use this to run jar in shell. By using this command line, when exit (abort remote connection), the process / command will not get killed.
Command line jcmd is used to check running process pid.