lunes, 30 de enero de 2012

"Could not initialize class: sun.awt.X11GraphicsEnvironment" using JT400 AS/400 driver

If you get a "Could not initialize class: sun.awt.X11GraphicsEnvironment" exception when trying to create a JDBC pool to an AS/400 machine using JTOpen (JT400, com.ibm.as400.access.AS400JDBCDriver), is very probably you have wrong data related to your connection (bad user, bad password, etc.). This driver have a very odd behaviour which tries to show a graphical window when some errors occur (producing the error in headless environments). Try establishing the connection first with an universal JDBC client like DBVisualizer or write a Java class to make the connection manually to confirm your connection settings.

miércoles, 28 de diciembre de 2011

Diagnosing Java memory leaks (OutOfMemoryError)

  • First you have to get a Heap Dump.
  • To analize it, IBM Heap Analyzer is the way to go.
  • IBM Heap Analyzer's Tree View *is* the way to go.
  • Hopefully you'll have one big tree. Go for it!
  • Descend fast while the big percentage doesn't change. Ignore "interesting" objects if the percentage doesn't change under them.
  • If you find a ClassLoader in the way, ignore the history behind you. Keep descending.
  • Descend more.
  • Be aware of "infinite chains" of the same objects or "infinite chains" with patterns of the same objects.
  • Be aware of gaps in the percentage.
  • Keep in mind that the tree Heap Analzyer is just a way to show you the memory. You have thousands of ways to draw an analogous tree. Each point in the tree can have several "parents". Heap Analyzer is only showing you one of them.
References:

jueves, 22 de diciembre de 2011

Programmatically obtaining "Messages waiting for read" for OC4J 10g JMS memory topic using JMX

You have to configure your classpath with the following jars (I haven´t test which of them are extrictly necessary):
  • adminclient.jar
  • dms.jar
  • ejb.jar
  • javax77.jar
  • jms.jar
  • oc4jclient.jar
  • oc4j-internal.jar
  • optic.jar
  • pcl.jar

Although I'm working with OAS and not with OC4J standalone, I'll connect directly to the OC4J instance (not through OPMN). So I'll use this type of URL: service:jmx:rmi://[server]:[oc4j_rmi_port]. I just need to get the OC4J RMI port usign opmnctl -l.

Obtain the connection using the oc4jadmin credentials:

JMXServiceURL url = new JMXServiceURL(makeJmxUrl());
String[] creds = { "oc4jadmin", oc4jadminPassword };
Map<String, Object> env = new HashMap<String, Object>();
env.put(JMXConnector.CREDENTIALS, creds);
JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();


The JMS topic I'm trying to obtain the statistics from is one of the Oracle ESB 10g standard topics: ESB Java Deferred. I have several subscribers and each one of them has a corresponding MBean. The statistics are presented from each one of them, and not as totals for the topic. So, if for example, I want to get the "Messages waiting for read" for the topic, I have to obtain the value for each subscriber and add them. The wildarded URL to obtain the MBeans for the subscribes is as follows: oc4j:j2eeType=JMSStoreResource,*,JMSDestinationResource=\"Topic.ESB Deferred Topic\",JMSResource=\"JMS\",J2EEServer=standalone

ObjectName mbeanNameQueryPattern = new ObjectName("oc4j:j2eeType=JMSStoreResource,*,JMSDestinationResource=\"Topic.ESB Deferred Topic\",JMSResource=\"JMS\",J2EEServer=standalone");
Set<ObjectName> mbeansNames = mbsc.queryNames(mbeanNameQueryPattern, null);

Iterate over the MBeans to obtain their statistics: There are several statistics to choose (messageCommitted, messageRolledBack, messageCount -Messages waiting for read-, messageDequeued -Messages waiting for commit-, messageEnqueued, messageDiscarded, messageExpired, messagePagedIn, messagePagedOut, messageRecovered and pendingMessageCount), but right now I'm only getting this: messageCount.

long value = 0L;
Iterator mbeansNamesIter = mbeansNames.iterator();
while (mbeansNamesIter.hasNext()) {
    ObjectName mbeanName = mbeansNamesIter.next();
    JMSStoreStatsImpl jmsStats = (JMSStoreStatsImpl)mbsc.getAttribute(mbeanName, "stats");
    CountStatisticImpl countStatistic = (CountStatisticImpl)jmsStats.getStatistic(statisticName);
    value = value + countStatistic.getCount();
}

Thos are the related imports:

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import oracle.oc4j.admin.management.shared.statistic.CountStatisticImpl;
import oracle.oc4j.admin.management.shared.statistic.JMSStoreStatsImpl;

JVM must be started with this flag: -Djmx.remote.protocol.provider.pkgs=oracle.oc4j.admin.jmx.remote

If you want to make a "real time" desktop chart with the values, there's a very nice and easy alternative: VisualVM's charting API. Here is an example.


"Error creating managed object for class org.jboss.weld.servlet.WeldListener"

Following the Arun Gupta's Java EE 6 Hands-on Lab using Netbeans 7.0.1 and Glassfish 3.1.1, I found the following error, which prevented me from deploy the app: Error creating managed object for class org.jboss.weld.servlet.WeldListener.

I just restarted Glassfish, did a Clean and Build and the problem was gone :P

The Lab is a very good way to know several new cool Java EE 6 features.

miércoles, 28 de septiembre de 2011

"Oracle Web Services Inspection Language Configuration Assistant" failed ("Could not get DeploymentManager" deploying WSIL App)

Installing the 10.1.3.5 Oracle Application Server patch on an 10.1.3.1 installation, I got the following error in the "Configuration Assistants" step:

Configuration assistant "Oracle Web Services Inspection Language Configuration Assistant" failed
Buildfile: /ESB/webservices/lib/wsil-install.xml


The log windows didn't have any useful information so I took a look at the full installActions* log. This log didn't have also the concrete error but showed the complete Ant command being executed:

The command being spawned is: '/ESB/ant/bin/ant -buildfile /ESB/webservices/lib/wsil-install.xml  -logfile /ESB/cfgtoollogs/wsil.txt -DHOST=ESBDB -DOPMNPORT="6003" -DADMIN_USER=oc4jadmin -DOPMNINSTANCE=home -Denv.JAVA_HOME=/ESB/jdk -Denv.ANT_HOME=/ESB/ant -Denv.ORACLE_HOME=/ESB *Protected value, not to be logged*'

Luckily, this command had its own log file: /ESB/cfgtoollogs/wsil.txt.

This log had the following information:

[echo] Deploying WSIL App with JSSO disabled
[java] Failed at "Could not get DeploymentManager".
[java] This is typically the result of an invalid deployer URI format being supplied, the target server not being in a started state or incorrect authentication details being supplied.
[java] More information is available by enabling logging -- please see the Oracle Containers for J2EE Configuration and Administration Guide for details.

Watching other post (and other) I found this error occurs when there are errors in the arguments supplied in the deployment URL (OC4J instance, password, etc.). I looked the Ant script and found the OC4J instance being used to deploy the WSIL app was 'home', but I don't have an O4CJ instance called 'home'. My OC4J admin instance is called 'admin'.



I hardcoded the name of my real OC4J intance in the ANT buildfile, retried the action and the installation finished OK.



martes, 6 de septiembre de 2011

Configuración alternativa del Softphone (teléfono VoIP) de Une en Windows 7 (64 bits)

Hace poco estaba fuera de Colombia e intenté usar el Softphone de UNE en Windows 7 64bits para hacer llamadas "locales" en Medellín, pero no me fue posible. El software que ellos distribuyen es una versión preconfigurada de SJphone de SJ Labs. También descargué directamente la última versión de dicha página pero tampoco me fue posible. No recuerdo exáctamente el error y no guardé un pantallazo; creo que era "No active network interface". Intenté iniciarlo con compatibilidad a Windows XP, pero tampoco. He visto el softphone funcionando en otros sistemas Windows 7, pero en mi máquina no lo logré (depronto los otros eran 32 bits y la incompatibilidad es solo con 64 bits).

Afortunadamente me recomendaron otro programa bastante bueno y grátis para uso personal, llamado X-Lite.


Para configurarlo debes disponer solo de tu número telefónico de VoIP y tu contraseña. Suponiendo que te asignaron el número 1234567, la configuración sería la siguiente:

User ID: 1234567
Domain: une.net.co
Password:
Authorization name: toip1234567
Proxy SIP: epmvoip1.une.net.co

Y listo.

Como yo estaba en un lugar con un límite muy bajo de cuota de navegación (usando un móden móvil), modifiqué los codecs disponibles para dejar solo unos de menor calidad, pero de menor consumo de ancho de banda. Si el ancho de banda esto no es una limitante, esto no es necesario ya que la calidad es muy buena con los predefinidos.

Antes:



Después:



Ver también Configuración del Softphone (teléfono VoIP) de Une en iPad (o iPhone).

miércoles, 31 de agosto de 2011

"package javax.xml.bind.annotation does not exist" using CXF's DynamicClientFactory in OC4J 10.1.3.x

I'm using CXF 2.4.2 and DynamicClientFactory in OC4J 10.1.3.4 (and 10.1.3.5).

When DynamicClientFactory tries to compile the dinamycally generated Java sources, the following errors occur:

INFO: Created classes: XXX, YYY, ...
 C:\..\org.apache.cxf.endpoint.dynamic.DynamicClientFactory@12f767-1314800629516-src\...\XXX.java:4: package javax.xml.bind.annotation does not exist
 import javax.xml.bind.annotation.XmlAccessType;
                                  ^
 C:\..\org.apache.cxf.endpoint.dynamic.DynamicClientFactory@12f767-1314800629516-src\...\YYY.java:4: package javax.xml.bind.annotation does not exist
 import javax.xml.bind.annotation.XmlAccessType;
                                  ^
I dug into the DynamicClientFactory code and found that setupClasspath, the method which sets the Classpath for the javac compilation iterates between the supplied ClassLoader (or the Context ClassLoader if none is supplied) and the SystemClassLoader extrating the ClassPath paths for each one; this extraction is done only if the ClassLoader in turn is an instance of URLClassLoader. In OC4J, the ClassLoaders are usually instances of oracle.classloader.PolicyClassLoader (which is not an instance of URLClassLoader). For this reason, the Classpath for the compilation is not correctly set.

There was a reported bug (CXF-2549) which gives a solution for Weblogic. I didn't find a good similar solution for OC4J to send a patch.

I found the necessary compilation libraries are the JAXB ones. What I did, before calling createClient, was to set a new URLClassLoader which include the JAXB jars:

URL[] jaxbUrls = null;

jaxbUrls = new URL[]{
  new URL("file:/C:/.../jaxb-api-2.2.1.jar"),
  new URL("file:/C:/.../jaxb-impl-2.2.1.1.jar"),
  new URL("file:/C:/.../jaxb-xjc-2.2.1.1.jar")
};

ClassLoader currentCL = Thread.currentThread().getContextClassLoader();

URLClassLoader urlCL = new URLClassLoader(jaxbUrls, currentCL);

client = dcf.createClient(xxx, yyy, urlCL, zzz);

The compilation is now succesful.

DynamicClientFactory internally creates another URLClassLoader which includes the newly generated classes and set it as the current thread's Context Class Loader; for this reason, when working with DynamicClientFactory in a multithreaded environment, there are some gotchas relating the ClassLoaders, but I thing this is material for another post.

EDIT: I found a better way to initialize the JAXB jars URL's array:

import oracle.classloader.PolicyClassLoader;
import oracle.classloader.SharedCodeSource;

Class someJaxbClazz = Class.forName("javax.xml.bind.annotation.XmlAccessType");
PolicyClassLoader jaxbClazzClassLoader = (PolicyClassLoader)someJaxbClazz.getClassLoader();
SharedCodeSource[] sharedCodeSources = jaxbClazzClassLoader.getCodeSources(false);

for(SharedCodeSource sharedCodeSource : sharedCodeSources) {
    URL location = sharedCodeSource.getLocation();
    if(location.toString().toLowerCase().contains("jaxb")) {
        System.out.println("JAXB jar URL found->" + location);
    }
}

In my case, it printed somethig like:

JAXB jar URL found->file:/C:/.../cxf/2.4.2/jaxb-api-2.2.1.jar
JAXB jar URL found->file:/C:/.../cxf/2.4.2/jaxb-impl-2.2.1.1.jar
JAXB jar URL found->file:/C:/.../cxf/2.4.2/jaxb-xjc-2.2.1.1.jar

:-)