Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Remote JMX connection through Firewall and jump host

1. The application to monitor must first be started with jmxremote enabled with the following command line parameters.

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=6786 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false

2. Setup an ssh pipe forwarding local port to ssh port on remote host via jump box.

$ # ssh –L local_port:remote_host_address:22 jumphost_address
$ ssh –L 20000:10.229.10.144:22 artemis.corp.tnsi.com

3. Create a dynamic ssh tunnel which acts as a SOCKS proxy.

$ ssh -p 20000 -D 6786 localhost 

4.
a. Configure Java VisualVM to use a SOCKS Proxy
i. select: Tools->Options->Network->Manual proxy settings
ii. Enter localhost and the port created in the dynamic port forward in step 3.
b. Add a remote host being the destination host running the java application
i. Right click Remote, select “Add Remote Host”
ii. Enter the address of the destination host
c. Next, right click destination remote host icon and select “Add JMX Connection”
i. Enter the address of destination host together with jmx registry port number



5. Connecting JConsole to the remote java application also requires directing it to the SOCKS proxy.

C:\Program Files\Java\jdk1.7.0_11\bin>jconsole.exe -J-DsocksProxyHost=proxy_host_address -J-DsocksProxyPort=proxy_port service:jmx:rmi:///jndi/rmi://localhost:jmxregistry_port/jmxrmi

e.g. 
C:\Program Files\Java\jdk1.7.0_11\bin>jconsole.exe -J-DsocksProxyHost=localhost -J-DsocksProxyPort=6786 service:jmx:rmi:///jndi/rmi://localhost:6786/jmxrmi


Thanks to David O'Connor for figuring this out.

AJP Test Tool

Here is a link to a brief Perl script which is useful to quickly check whether a Tomcat server is listening on its AJP port.
http://www.joedog.org/2012/06/ajp-functional-test

Another option may be this tool, but I haven't tested this and there is no documentation available.
https://github.com/espenhw/ajp-client

As an aside, the best description of the AJP protocol I've seen so far can be found here:
http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html

Naming of netty worker threads

One of the slightly annoying quirks in Netty is the fact that OIO worker names are not meaningful.

Here is some sample code to fix this:

/* give worker threads a meaningful name such as "OIO-worker-2" */
try {
    ThreadRenamingRunnable.setThreadNameDeterminer(
        new ThreadNameDeterminer() {
            public String determineThreadName(String currentThreadName,
                                                String proposedThreadName) throws Exception {
          
                StringBuffer sb = new StringBuffer(WORKER_THREADNAME_PREFIX);
                sb.append(currentThreadName.substring(currentThreadName.lastIndexOf('-')));
                return sb.toString();
            }
        });         
} catch (Exception e) {
         
    /* fall back to default thread name, e.g. pool-X-thread-X */
    ThreadRenamingRunnable.setThreadNameDeterminer(ThreadNameDeterminer.CURRENT);
}

Run Java Programs from Cygwin

The java exe is a Windows program, so it expects a Windows style classpath.

This will not work:

 [cygwin] release $ java -cp "bin/*:lib/*" com.tnsi.tap.Versin
java.lang.NoClassDefFoundError: com/tnsi/tap/Versin
Caused by: java.lang.ClassNotFoundException: com.tnsi.tap.Versin
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClassInternal(Unknown Source)
Could not find the main class: com.tnsi.tap.Versin.  Program will exit.
Exception in thread "main"  [cygwin] release $


Use a semicolon instead:

 [cygwin] release $ java -cp "bin/*;lib/*" com.tnsi.tap.Version
TNSPay Retail Gateway - TokenisationAdapter 1.0.0.1 23Nov2011
 [cygwin] release $

Simple HTTP Request

Simple code sample that executes a HTTP GET using apache HttpClient

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

public String executeGet(String url) throws ClientProtocolException, IOException {
  
    HttpClient httpClient = new DefaultHttpClient();
    HttpGet httpGet = new HttpGet(url);
    HttpResponse response = httpClient.execute(httpGet);
  
    HttpEntity entity = response.getEntity();
    return EntityUtils.toString(entity);
}

JUnit handle expected Exception

This code sample shows to handle expected exceptions. This requires JUnit 4.7+

import com.some.ClassUnderTest;

import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class TestClass {

    ClassUnderTest fixture;

    @Before
    public void setUp() throws Exception {

    }

    @Rule
    public ExpectedException exception = ExpectedException.none();

    @Test
    public final void testCodeThatThrowsException() throws Exception {
  
        exception.expect(IllegalArgumentException.class);
        exception.expectMessage("Found illegal argument");
        fixture.methodThatThrowsException();
    }
}

EvoSuite - Automated Test Case Generation

EvoSuite is a tool that examines Java byte code and automatically creates a Junit test suite.

Download from here: http://www.st.cs.uni-saarland.de/evosuite/index.html

Use from command line as follows:
$ # create build/libs/RefactoringExperiment.jar
$ java -jar lib/evosuite-20110908.jar -setup build/libs/RefactoringExperiment.jar
$ java -jar lib/evosuite-20110908.jar -assertions -generateSuite

Evosuite works on bytecode, so the easiest way to use it is to create a jar containing all source code to be tested, then use that as part of the java command.

Here is a gradle task that first creates a jar containing everything in src/main/java, then runs setup and generateSuite.
apply plugin: 'java'
task evosuite (dependsOn: jar) << {
    ant {
  
        java(jar: evosuiteJar, fork:true) {
            arg(value: "-setup")
            arg(value: "build/libs/RefactoringExperiment.jar")
        }
  
        java(jar: evosuiteJar, fork:true) {
            arg(value: "-assertions")
            arg(value: "-generateSuite")
        }
    }
}
To run the setup and generateSuite tasks from a bash script, use the following snippet. The -mem parameter is not documented, and only available from evosuite-20110929.jar onwards. It specifies the amount of memory available for the the JVM that runs the test generation. Using -Xmx... has no effect on that JVM.
# EvoSuite setup
java -cp ~/lib/evosuite.jar de.unisb.cs.st.evosuite.EvoSuite -setup build/libs/$project.jar

# run with criterion branch
java -cp ~/lib/evosuite.jar de.unisb.cs.st.evosuite.EvoSuite -assertions -criterion branch -generateSuite -mem 3000

# run with criterion mutation
java -cp ~/lib/evosuite.jar de.unisb.cs.st.evosuite.EvoSuite -assertions -criterion mutation -generateSuite -mem 3000

The paper introducing EvoSuite is here: http://www.st.cs.uni-saarland.de/publications/files/li-ssbse-2011.pdf

Maven OutOfMemoryError and MAVEN_OPTS


Running out of memory is something that happens frequently during a Maven build. Here is some sample output from running mvn package:

[INFO] Processing PDFs
[INFO] Processing PDF: /Users/tom/Books/jenkins-the-definitive-guide-book/hudsonbook-pdf/src/main/resources/hudson-book-cover.pdf
[INFO] Processing PDF: /Users/tom/Books/jenkins-the-definitive-guide-book/hudsonbook-pdf/target/book.pdf
[ERROR] Java heap space -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/OutOfMemoryError
mbp:jenkins-the-definitive-guide-book tom$


There is a big fat Java heap space error at the top of the error message.
To fix this, simply increase the available memory in the MAVEN_OPTS environment variable. In other words, before you run the mvn package command, set or modify MAVEN_OPTS with the -Xmx... switch. The following code snippet shows how to do this in Linux/Unix and Windows.

# Unix
export MAVEN_OPTS="-Xmx512m -XX:MaxPermSize=128m"


# Windows
set MAVEN_OPTS=-Xmx512m -XX:MaxPermSize=128m

Java: file download

One way to create a downloadable file in a Java webapp

/* set required headers */
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=DownloadFile.csv"); 

/* stream the file into a byte array */
byte[] downloadFile = buildDownloadFile();

/* write directly to the client */
OutputStream os = response.getOutputStream();
os.write(downloadFile, 0, downloadFile.length);
os.flush();
os.close();


Simple filter in a Java webapp


Define a filter in web.xml:

<filter>
<filter-name>SimpleFilter</filter-name>
<display-name>SimpleFilter</display-name>
<description>log filter</description>
<filter-class>com.filtertest.SimpleFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SimpleFilter</filter-name>
  <servlet-name>simple</servlet-name>
<!--  <url-pattern>/request.go</url-pattern>-->
       <dispatcher>REQUEST</dispatcher>
       <dispatcher>FORWARD</dispatcher>
</filter-mapping>

Make sure the FORWARD dispatcher is defined, otherwise only the original request URL will be used to determine if the filter should be invoked. In other words, if FORWARD is missing, any HTTP requests that were forwarded to this resource will not invoke the filter.

Implement a doFilter(…) method in the com.filtertest.SimpleFilter class as follows:

log.info("Filter invoked");
 // pass the request along the filter chain
 chain.doFilter(request, response);
}

Log4j configuration

Basic log4j configuration in an Eclipse project:

  • save log4j.properties in /src folder, or in /src/main/resources for a Maven project. After building, it will end up in /bin. The goal is to have this file in the classpath
  • Add log4j.jar to build path

Contents of log4j.properties

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%6r [%t] %-5p %c{1} - %m%n

log4j.logger.com.my.class=DEBUG

Add a file appender:

# FileAppender
log4j.appender.FA=org.apache.log4j.RollingFileAppender
log4j.appender.FA.layout=org.apache.log4j.PatternLayout
log4j.appender.FA.layout.ConversionPattern=%6r %-5p %m%n
log4j.appender.FA.File=/var/log/myapp.log

# classes in package com.tnsi use INFO level
# output is logged to FA
log4j.logger.com=DEBUG

Root logger to console and a file appender only for com.my.class classes:

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.NULL=org.apache.log4j.varia.NullAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c{1}:%M - %m%n
log4j.appender.A1.Threshold=INFO

log4j.appender.F1=org.apache.log4j.RollingFileAppender
log4j.appender.F1.layout=org.apache.log4j.PatternLayout
log4j.appender.F1.layout.ConversionPattern=%m%n
log4j.appender.F1.File=/var/log/application.log
log4j.appender.F1.Threshold=DEBUG

log4j.logger.org.apache=INFO,NULL
log4j.logger.com.my.class=DEBUG,F1

Java stack trace and heap dump analysis

Take a stack trace like this:
$ jmap -dump:file=tc_jmap.dat 9607

First parameter is the output file name, last is process id Start jhat to browse the stack trace
$ jhat -J-Xmx512m -port 8080 tc_jmap.dat

Or use Eclipse MAT (Memory Analyzer Tool) - Memory Analysis perspective.