Skip to content

Commit

Permalink
Merge pull request #144 from IQSS/101-124-java-tools
Browse files Browse the repository at this point in the history
101 124 java tools
  • Loading branch information
poikilotherm committed Jan 20, 2020
2 parents 5bbd285 + 0f81c5c commit fa04513
Show file tree
Hide file tree
Showing 16 changed files with 219 additions and 1 deletion.
9 changes: 9 additions & 0 deletions docker/dataverse-k8s/glassfish-dev/Dockerfile
Expand Up @@ -19,9 +19,18 @@ RUN mvn package -DskipTests
FROM iqss/dataverse-k8s
LABEL maintainer="FDM FZJ <forschungsdaten@fz-juelich.de>"

ENV JREBEL_LIB=/opt/dataverse/jrebel/lib/libjrebel64.so
RUN wget --no-verbose -O "${HOME_DIR}/jrebel.zip" http://dl.zeroturnaround.com/jrebel-stable-nosetup.zip && \
unzip -q "${HOME_DIR}/jrebel.zip" -d "${HOME_DIR}"

# Copy files for the application
COPY --chown=glassfish:glassfish --from=builder /target/dataverse-*.war ${HOME_DIR}/dvinstall/dataverse.war
COPY --chown=glassfish:glassfish dataverse/scripts/api/data ${HOME_DIR}/dvinstall/data
COPY --chown=glassfish:glassfish dataverse/scripts/api/*.sh ${HOME_DIR}/dvinstall/
COPY --chown=glassfish:glassfish dataverse/scripts/database/reference_data.sql ${HOME_DIR}/dvinstall/
COPY --chown=glassfish:glassfish dataverse/conf/jhove/* ${HOME_DIR}/dvinstall/

# Copy across docker scripts
COPY --chown=glassfish:glassfish docker/dataverse-k8s/bin/* docker/dataverse-k8s/glassfish/bin/* docker/dataverse-k8s/glassfish-dev/bin/* ${SCRIPT_DIR}/
RUN mkdir -p ${SCRIPT_DIR}/init.d && \
chmod +x ${SCRIPT_DIR}/*
52 changes: 52 additions & 0 deletions docker/dataverse-k8s/glassfish-dev/bin/init_0_enabledev.sh
@@ -0,0 +1,52 @@
#!/bin/bash

set -e

###### ###### ###### ###### ###### ###### ###### ###### ###### ###### ######
# This script enables different development options, like a JMX connector
# usable with VisualVM, JRebel hot-reload support and JDWP debugger service.
# Enable it by adding env vars on startup (e.g. via ConfigMap)
###### ###### ###### ###### ###### ###### ###### ###### ###### ###### ######

# 0. Init variables
ENABLE_JMX=${ENABLE_JMX:-0}
ENABLE_JDWP=${ENABLE_JDWP:-0}
ENABLE_JREBEL=${ENABLE_JREBEL:-0}
JDWP_PORT=${JDWP_PORT:-9009}

# 1. if any options need to be set, start the server...
if [ "x${ENABLE_JMX}" = "x1" ] || [ "x${ENABLE_JDWP}" = "x1" ] || [ "x${ENABLE_JREBEL}" = "x1" ]; then
echo "Starting application server..."
asadmin start-domain
fi

# 2. Enable JMX (metrics + performance)
if [ "x${ENABLE_JMX}" = "x1" ]; then
echo "Enabling JMX Remote on port 4000/4001. Remember you need to connect to localhost, e.g. via port-forwarding."
asadmin create-jvm-options "\-Dcom.sun.management.jmxremote"
asadmin create-jvm-options "\-Dcom.sun.management.jmxremote.port=4000"
asadmin create-jvm-options "\-Dcom.sun.management.jmxremote.rmi.port=4001"
asadmin create-jvm-options "\-Dcom.sun.management.jmxremote.ssl=false"
asadmin create-jvm-options "\-Dcom.sun.management.jmxremote.authenticate=false"
asadmin create-jvm-options "\-Djava.rmi.server.hostname=127.0.0.1"
fi

# 3. Enable JDWP (debugger)
if [ "x${ENABLE_JDWP}" = "x1" ]; then
echo "Enabling JDWP debugger, listening on port ${JDWP_PORT} of this container/pod."
asadmin create-jvm-options "\-agentlib\:jdwp=transport=dt_socket,server=y,suspend=n,address=${JDWP_PORT}"
fi

# 4. Enable JRebel (hot-redeploy)
if [ "x${ENABLE_JREBEL}" = "x1" ] && [ -s "${JREBEL_LIB}" ]; then
echo "Enabling JRebel support with enabled remoting_plugin option."
asadmin create-jvm-options "\-agentpath\:${JREBEL_LIB}"
asadmin create-jvm-options "\-Drebel.remoting_plugin=true"
fi

# 5. Stop the server
# 1. if any options need to be set, start the server...
if [ "x${ENABLE_JMX}" = "x1" ] || [ "x${ENABLE_JDWP}" = "x1" ] || [ "x${ENABLE_JREBEL}" = "x1" ]; then
echo "Stopping application server..."
asadmin stop-domain
fi
Expand Up @@ -22,7 +22,7 @@ for alias in rserve doi db
do
if [ -f ${SECRETS_DIR}/$alias/password ]; then
cat ${SECRETS_DIR}/$alias/password | sed -e "s#^#AS_ADMIN_ALIASPASSWORD=#" > /tmp/$alias
asadmin $ASADMIN_OPTS create-password-alias --passwordfile /tmp/$alias ${alias}_password_alias
asadmin create-password-alias --passwordfile /tmp/$alias ${alias}_password_alias
rm /tmp/$alias
else
echo "WARNING: Could not find 'password' secret for ${alias} in ${SECRETS_DIR}. Check your Kubernetes Secrets and their mounting!"
Expand Down
1 change: 1 addition & 0 deletions docs/conf.py
Expand Up @@ -51,6 +51,7 @@
'sphinx.ext.graphviz',
'sphinxcontrib.plantuml',
'sphinxcontrib.contentui',
'sphinxcontrib.images',
'recommonmark'
]

Expand Down
Binary file added docs/development/img/jdwp-idea-breakpoint.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/development/img/jdwp-idea-config.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/development/img/jdwp-idea-connect.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/development/img/jdwp-idea-port.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/development/img/jmx-port.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/development/img/jmx-visualvm-memory.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/development/img/jmx-visualvm-overview.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/development/img/jmx-visualvm-threads.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/development/img/jrebel-idea.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/development/index.rst
Expand Up @@ -19,6 +19,7 @@ Please prepare your environment first:

./prepare
./mail
./javatools



Expand Down
154 changes: 154 additions & 0 deletions docs/development/javatools.rst
@@ -0,0 +1,154 @@
======================
Java Development Tools
======================

When developing with Java, you will want to use some tooling for deeper
analysis of failures, hot-redeploys of the application, etc.

Please step through the different tools below to learn how you can use them
when using a (local) Kubernetes deployment as a part of your development
workflow.

These functionality is only enabled in the development flavors of :doc:`/images/dataverse-k8s`.
You should not (and cannot) enable this in production.

.. seealso:: If you need to swap out your production pod, take a look at `telepresence <https://www.telepresence.io/>`_.

Metrics and Performance with VisualVM
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

On startup, when the environment variable ``ENABLE_JMX=1``, the application
server is configured to listen on port ``4000`` and ``4001`` for JMX & RMI traffic
from ``localhost``. This cannot be changed.

You might set this variable in any way you like. On Kubernetes, the easiest way
is likely to be via the Dataverse ``ConfigMap`` (see also :doc:`/day1/config`):

.. code-block:: yaml
# [...]
data:
ENABLE_JMX: "1"
You will need to port-forward this to your host. Example:

.. code-block:: shell
kubectl port-forward deployment/dataverse 4000 4001 8080
A well known tool for memory, thread and sample analysis is `VisualVM <https://visualvm.github.io/>`_.
After installing and activating the port forwarding, connect VisualVM to
the running JMX service like this:

.. code-block:: shell
visualvm --openjmx localhost:4000
.. thumbnail:: img/jmx-port.png
:group: jmx
:title: Port forwarding with kubectl
:width: 24%
.. thumbnail:: img/jmx-visualvm-overview.png
:group: jmx
:title: VisualVM: overview of connected JVM
:width: 24%
.. thumbnail:: img/jmx-visualvm-memory.png
:group: jmx
:title: VisualVM: memory of connected JVM
:width: 24%
.. thumbnail:: img/jmx-visualvm-threads.png
:group: jmx
:title: VisualVM: threads of connected JVM
:width: 24%





Debugging with JDWP
^^^^^^^^^^^^^^^^^^^

On startup, when the environment variable ``ENABLE_JDWP=1``, the application
server is configured to listen on port ``${JDWP_PORT}`` defaulting to 9009.

You might set this variables in any way you like. On Kubernetes, the easiest way
is likely to be via the Dataverse ``ConfigMap`` (see also :doc:`/day1/config`):

.. code-block:: yaml
# [...]
data:
ENABLE_JDWP: "1"
JDWP_PORT: "9009"
You will need to port-forward this to your host. Example:

.. code-block:: shell
kubectl port-forward deployment/dataverse 9009 8080
Then configure your IDE to connect to the remote debugger. Below is an example
for IntelliJ IDEA:

.. thumbnail:: img/jdwp-idea-port.png
:group: jdwp
:title: Port forwarding with kubectl
:width: 24%
.. thumbnail:: img/jdwp-idea-config.png
:group: jdwp
:title: Remote debugger configuration in IntelliJ IDEA
:width: 24%
.. thumbnail:: img/jdwp-idea-connect.png
:group: jdwp
:title: Remote debugger in IntelliJ IDEA connected
:width: 24%
.. thumbnail:: img/jdwp-idea-breakpoint.png
:group: jdwp
:title: Remote debugger at work
:width: 24%



Hot-Reploy of evolving parts with JRebel
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

On startup, when the environment variable ``ENABLE_JREBEL=1``, the application
server is configured to enable JRebel support on deployment.

You might set this variable in any way you like. On Kubernetes, the easiest way
is likely to be via the Dataverse ``ConfigMap`` (see also :doc:`/day1/config`):

.. code-block:: yaml
# [...]
data:
ENABLE_JREBEL: "1"
Once your application server is up, JRebel communicates with the IDE extensions
via the very same port that you use to access Dataverse in the browser. Please
follow their instructions to configure your IDE plugin.

Below is an example using IntelliJ IDEA and its JRebel Plugin, syncing via
a ``kubectl port-forward`` from localhost into the cluster:

.. thumbnail:: img/jrebel-idea.png
:title: JRebel in Dataverse Pod enabled in IntelliJ IDEA.

.. danger::

You will need to raise the RAM limit of the pod when enabling this.
Dev default 1 GiB RAM is not sufficient, 1.5 GiB (= 750 MiB heap) is bare
minimum. You might need to add more RAM to your Kubernetes cluster, depending
on your setup.

.. important::

Please be aware that you will need a JRebel license to use this timesaving
feature. Good products have a reasonable price. You have been warned.
https://www.jrebel.com/products/jrebel

.. seealso::

In the future, when Dataverse runs on Java JDK 11, one might take a look at
http://hotswapagent.org. There are only outdated DCEVM patches for JDK 8,
so this is currently not an alternative.
1 change: 1 addition & 0 deletions docs/requirements.txt
Expand Up @@ -2,3 +2,4 @@ sphinxcontrib-plantuml==0.17.1
sphinx_materialdesign_theme==0.1.11
recommonmark==0.6.0
sphinxcontrib-contentui==0.2.3
sphinxcontrib-images==0.8.0

0 comments on commit fa04513

Please sign in to comment.