AppDynamics Pro – basics

The goal of this ticket is to present and explain the basic notions of the AppDynamics Pro product.

  • Node – a node is the basic unit of processing that AppDynamics monitors. A node is instrumented by an AppDynamics agent.
  • Tier – a tier represents an instrumented service or multiple services that perform the exact same functionality. It represents a more logical view of the application.A tier is composed of one or multiple nodes.
  • Application – multiple tiers gathered together.
  • Business Transaction – represents a distinct logical user activity. The entire application traffic is organized in Business Transactions.
  • Transaction Snapshot -set of diagnostic data, taken at a certain point in time, for a specific Business Transaction across all the tiers though which the transaction has passed. The Transaction Snapshots are triggered periodically (every 10 minutes) or automatically for the slow and error business transactions.
  • Metrics -application performance informations sent from the App Server Agents and Machine Agents to the controller.
  • Baselines – set of metrics within a time range.
  • Baseline Deviations – degree of deviation from baseline at any given point in time and by default are calculated by a number of standard deviations above the average.
  • Service Endpoint – performance metrics focused on a particular service or set of services independent of business transactions.
  • Health Rule – defines a condition or set of conditions in terms of metrics. The condition compares the performance metrics that AppDynamics collects with some static or dynamic threshold that you define. If performance exceeds the threshold, a health rule violation event is triggered. There are two types of thresholds: Warning and Critical.
  • Diagnostic Session – the goal is to collect extra Transaction Snapshots for one or more Business Transactions for a period of time.
  • Events – emitted when the application state change. Eight type of events:
    • Health rules violation
    • Too many slow transactions
    • Too many errors
    • Code problems
    • Application changes
    • JVM and CLR (.NET) Crashes
    • AppDynamics Config Warnings
    • Discovery (new application, tier or done discovered)
  • Errors – AppDynamics treat as errors the following events:
    • unhandled exceptions
    • HTTP error codes from 400 to 505 (the error codes to catch are configurable)
    • Error or Fatal logging events (Log4j or java.util.logging)
  • Information Points – collects metrics outside the context of Business Transactions and across several Business Transactions. For me it looks similar with the Service Endpoints.
  • Data Collectors – collects extra-information at the Business Transaction level like application code arguments, return values, and variables and displays the information in the Call Drill Down panels. There are two types of Data Collectors : method invocation date collectors and HTTP data collectors.

How to use an external JavaScript file in a BIRT report

In a recent assignment I had to write some custom Java Script code to treat some table cells from an Eclipse BIRT report.

This ticket explains the setting of an external Java Script file in a BIRT report.

Define the resources folder for your BIRT project.

First step is to define the resources folder for your BIRT project. Go to the project properties -> Report Design ->Resource (as shown in the following screenshot). In our case the BIRT project is a (Java) Maven project so all the external resources are in the folder src/ressources.

BIRTProjectResourceSetting

Add the external Java Script file(s) to the BIRT report

In the property editor of the BIRT report, define the external resource files (in the following screenshot the “CustomFunctions.js” was added an external JavaScript file).

BIRTReportPropertyEditor

After adding the JS file, the rptdesign file the will look something like :

<report xmlns="http://www.eclipse.org/birt/2005/design" version="3.2.23" id="1">
 <property name="createdBy">Eclipse BIRT Designer Version 4.3.1.v201309091055 Build <4.3.1.v20130917-1035></property>
    <list-property name="includeScripts">
       <property>CustomFunctions.js</property>
     </list-property>
....

Use the custom JavaScript functions in the report

In the BIRT expression builder, use the custom JavaScript function (as in the following screenshot):

BIRTExpressionBuilder

Update the BIRT web viewer

When the war file will be created, the src/ressources content will be copied under the folder WEB-INF/classes so, the BIRT web viewer servlet should be instructed where to find the resources folder under using a context parameter:

 <!-- Resource location directory. Defaults to ${birt home} -->
 <context-param>
 <param-name>BIRT_RESOURCE_PATH</param-name>
 <param-value>WEB-INF/classes</param-value>
 </context-param>

Generating Excel files with Apache POI – Removed Feature: Format from /xl/styles.xml part (Styles)

The problem

Some (big) Excel files generated using Apache POI cannot be correctly open by Excel (none of the styles applied to the cells are rendered). The error message shown by Excel is the following one :

Removed Feature: Format from /xl/styles.xml part (Styles)
Repaired Records: Cell information from /xl/worksheets/sheet1.xml part
Cell information from /xl/worksheets/sheet2.xml part
Repaired Records: Cell information from /xl/worksheets/sheet3.xml part

The cause

The root cause is that Excel can handle only a limited number of cell styles by workbook; Excel 2010 for example can handle 4000 cell style by workbook (see Excel specifications and limits).

The solution

The solution is quite simple (in theory). You have to limit the number of unique instances of org.apache.poi.ss.usermodel.CellStyle used in your workbook. For this you can use the POI utility class org.apache.poi.ss.util.CellUtil.

GenericSignatureFormatError while deploying SOAP web services

This ticket will present some problem that I encountered using  JAXB.

Environment

  • OS: Windows 7
  • Servlet container : Tomcat 7.X
  • JRE: Sun Java 1.6.0_11
  • JAXB version: 2.2.1

Stack trace

Trying to deploy a web application containing (SOAP) web services  failed with the following stack trace:

WSSERVLET11: failed to parse runtime descriptor: 
java.lang.reflect.GenericSignatureFormatError
at sun.reflect.generics.parser.SignatureParser.error(SignatureParser.java:103)
at sun.reflect.generics.parser.SignatureParser.parseSimpleClassTypeSignature(SignatureParser.java:262)
at sun.reflect.generics.parser.SignatureParser.parseClassTypeSignatureSuffix(SignatureParser.java:270)
at sun.reflect.generics.parser.SignatureParser.parseClassTypeSignature(SignatureParser.java:244)
...
 at com.sun.xml.ws.transport.http.DeploymentDescriptorParser.parse(DeploymentDescriptorParser.java:147)
 at com.sun.xml.ws.transport.http.servlet.WSServletContextListener.contextInitialized(WSServletContextListener.java:124)
...

Cause of the exception

One of the web services had as return value a list of enums. The enum was defined something like :

public enum Season { WINTER, SPRING, SUMMER, FALL }

(no default constructor).

In order to fix the problem it must add a no parameter contructor; something like:

public enum Season { 
WINTER, SPRING, SUMMER, FALL 
 Season() {}
}

How to deploy from Ant to Tomcat through SSL

Problem: Deploy a war using the Ant to Tomcat. The Ant task should be something like this (where ${tomcat-manager-url} is something like httpS://targetServer:port/manager/text):

<target name="deploy" description="Deploy application to tomcat">
<echo>deploying from local source</echo>
<deploy url="${tomcat-manager-url}" username="${tomcat-manager-username}" password="${tomcat-manager-password}" path="/${deployed-application-name}" war="file:///${project-workspace}/${war.name}" />
</target>

Solution: The basic idea is to add the server certificate to the keystore from witch the deployment will be done and use this this certificate to talk with the server through SSL.

Step 1: Get and save the server certificate to the disk.

Step 2: Add the server certificate to the keystone truststore of the system from which Ant will deploy the application.
C:\>keytool -importcert -keystore keystoreFile -trustcacerts -alias targetServer
-file full path to the certificate file

Step 3: Execute the ant script script with the following system properties:
-Djavax.net.ssl.keyStoreType=jks
-Djavax.net.ssl.keyStore=Full path to the keystore file
-Djavax.net.ssl.keyStorePassword=keystore password
-Djavax.net.ssl.trustStore=Full path to the keystore file
-Djavax.net.ssl.trustStorePassword=keystore password

Problems: Some errors that can appear and how to solve them.

Problem: PKIX path building failed. The full error message is:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target

Solution: The executed Ant script cannot find the keystore passed as parameter in the Step 3

Problem: No name matching “serverName” found. The full error message is:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching serverName found

Solution: The server name on which the deployment is made should be the same as the FQDN(Fully Qualified Domain Name) of the certificate. The FQDN of the certificate is something like serverName.foo.org; the server name on which the deployment is made by Ant should be exactly the same.

aoplib4j-0.0.4 is out !

A new version of the aoplib4j is out. The library contains (only one) new aspect for transform a test assertion into a verify (see TransformAssertToVerifyForTests) and some other minor changes (see here).

 

A strange NullPointerException inside Beehive

This entry is a small analysis of a stange NullPointerException that we had on our production servers when the server started and the first client tried to connect. I have no idea what provoked this exception but maybe someone will have a hint.

Environment

Code biopsy

This is the stack trace:

java.lang.NullPointerException
at org.apache.beehive.netui.pageflow.AutoRegisterActionServlet.process(AutoRegisterActionServlet.java:622)
at org.apache.beehive.netui.pageflow.PageFlowActionServlet.process(PageFlowActionServlet.java:158)
at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
...

The code of the AutoRegisterActionServlet.java around the line 622 is:
//
// Try to select the appropriate Struts module and delegate to its RequestProcessor.
//
ModuleConfig moduleConfig = InternalUtils.selectModule( modulePath, request, servletContext );
// If this module came from an abstract page flow controller class, send an error.
ControllerConfig cc = moduleConfig.getControllerConfig();//622 line
if (cc instanceof PageFlowControllerConfig && ((PageFlowControllerConfig) cc).isAbstract()) {
InternalUtils.sendDevTimeError( "PageFlow_AbstractPageFlow", null, HttpServletResponse.SC_NOT_FOUND,
request, response, servletContext,
new Object[]{ modulePath } );
return;
}

The most logical conclusion is that the moduleConfig variable is null and moduleConfig.getControllerConfig will throw the NullPointerException.
Now, let’s take a look at how the moduleConfig variable is computed; the code of the InternalUtils#selectModule is:

/**
* Set the given Struts module in the request, and expose its set of MessageResources as request attributes.
*
* @param prefix the prefix of the desired module.
* @param request the current HttpServletRequest.
* @param servletContext the current ServletContext.
* @return the selected ModuleConfig, or
null if there is none for the given module prefix.
*/
public static ModuleConfig selectModule( String prefix, HttpServletRequest request, ServletContext servletContext )
{
ModuleConfig moduleConfig = getModuleConfig( prefix, servletContext );
if ( moduleConfig == null )
{
request.removeAttribute( Globals.MODULE_KEY );
return null;
}
// If this module came from an abstract page flow controller class, don’t select it.
ControllerConfig cc = moduleConfig.getControllerConfig();
if (cc instanceof PageFlowControllerConfig && ((PageFlowControllerConfig) cc).isAbstract()) {
return moduleConfig;
}
// Just return it if it’s already registered.
if ( request.getAttribute( Globals.MODULE_KEY ) == moduleConfig ) return moduleConfig;
request.setAttribute( Globals.MODULE_KEY, moduleConfig );
MessageResourcesConfig[] mrConfig = moduleConfig.findMessageResourcesConfigs();
Object formBean = unwrapFormBean( getCurrentActionForm( request ) );
for ( int i = 0; i < mrConfig.length; i++ )
{
String key = mrConfig[i].getKey();
MessageResources resources = ( MessageResources ) servletContext.getAttribute( key + prefix );
if ( resources != null )
{
if ( ! ( resources instanceof ExpressionAwareMessageResources ) )
{
resources = new ExpressionAwareMessageResources( resources, formBean, request, servletContext );
}
request.setAttribute( key, resources );
}
else
{
request.removeAttribute( key );
}
}
return moduleConfig;
}

The first problem that we see is that the InternalUtils#selectModule method can return a null but the AutoRegisterActionServlet#process never verifies this case.
As we can see the moduleConfig variable is computed by the getModuleConfig variable and is never nullified afterward inside the method, so we go deeper into the code to see how the getModuleConfig method computes the moduleConfig variable.
The code of the InternalUtils#getModuleConfig is :

/**
* Get the Struts ModuleConfig for the given module path.
*/
public static ModuleConfig getModuleConfig( String modulePath, ServletContext context )
{
return ( ModuleConfig ) context.getAttribute( Globals.MODULE_KEY + modulePath );
}

The moduleConfig object is retrieved from the ServletContext and if no attribute exists under the name Globals.MODULE_KEY + modulePath then a null object is returned (see ServletContext#getAttribute javadoc). The full name of attribute will be org.apache.struts.action.MODULEmodulePath (to see what can be the value of the modulePath variable, go to the next section).

Struts modules and Beehive

Now, let’s take a look at the meaning of the org.apache.struts.config.ModuleConfig interface. The ModuleConfig is the API representation of a Struts-module(Beehive uses under the hood the Struts framework).
A Struts module is a Struts configuration file and a set of corresponding actions, form beans, and Web pages. A Struts application consists of one module by default but may contain more than one module.
The Beehive framework will create dynamically a Struts module for every executed page flow controller.
For example when the https://&#8230;./login url is called, the login.LoginController class will be instantiated and used to treat the request and Beehive will automatically create an instance of org.apache.struts.config.ModuleConfig and store it into the ServletContext under the name org.apache.struts.action.MODULE/login. Normally, the Struts module is created just before the first use of the page flow controller.
My supposition is that the org.apache.struts.config.ModuleConfig objects are singletons (one instance by controller) and are created and added by Beehive into the ServletContext only one time (first time when a controller is used).

Some kind of conclusion

So, the source of the NullPointerException is due to a missing Struts module (which, of course should never happen). Maybe the Beehive had a problem creating the Struts modules or maybe some “mysterious” process just removed all the objects from the ServletContext.
It is possible to monitor the ServletContext “traffic” (what objects are added/removed/updated) by implementing a ServletContextAttributeListener; the problem of this solution is his intrusiveness (a new class should be added to the web application and the application must be redeployed).