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

Friday, June 13, 2014

Apache Ant tasks for JMX access

I wanted to invoke JMX operations from the Ant tasks. However finding usable ant tasks library as well as the usage was rather tricky. So let me share my experience to make things easier for others.

Ant tasks for JMX operations

I decided to follow Tomcat documentation and used ant tasks distributed with tomcat.

Just for the record the usage is not restricted to Tomcat deployed JMX mBeans. For me it worked for java process accessible via JConsole via Remote connection.

Retrieving the library

  1. As I wanted to get the latest version I used maven central repository “search by classname” feature and searched for: org.apache.catalina.ant.jmx.JMXAccessorTask (see the query)
  2. afterwards I went for the tomcat 8 jar file (called tomcat-catalina-ant-8.0.8.jar)
  3. and just copyied the latest available to my $ANT_HOME/lib dir.

Usage

I didn’t have a chance (or motivation?) to check all the tasks available, the full list of tasks available can be seen in the zipped file: org/apache/catalina/ant/jmx/antlib.xml, following were present for me:

<typedef
    name="open"
    classname="org.apache.catalina.ant.jmx.JMXAccessorTask" />
<typedef
    name="set"
    classname="org.apache.catalina.ant.jmx.JMXAccessorSetTask" />
<typedef
    name="get"
    classname="org.apache.catalina.ant.jmx.JMXAccessorGetTask" />
<typedef
    name="invoke"
    classname="org.apache.catalina.ant.jmx.JMXAccessorInvokeTask" />
<typedef
    name="query"
    classname="org.apache.catalina.ant.jmx.JMXAccessorQueryTask" />
<typedef
    name="create"
    classname="org.apache.catalina.ant.jmx.JMXAccessorCreateTask" />
<typedef
    name="unregister"
    classname="org.apache.catalina.ant.jmx.JMXAccessorUnregisterTask" />
<typedef
    name="equals"
    classname="org.apache.catalina.ant.jmx.JMXAccessorEqualsCondition" />
<typedef
    name="condition"
    classname="org.apache.catalina.ant.jmx.JMXAccessorCondition" />

out of these, I gave following a try:

org.apache.catalina.ant.jmx.JMXAccessorTask
org.apache.catalina.ant.jmx.JMXAccessorInvokeTask
org.apache.catalina.ant.jmx.JMXAccessorQueryTask

For the demonstration purposes I’m using Glassfish 4.0.

Example: Listing JMX MBeans

Let’s assume we want to retrieve the MBean by name (namely: java.lang:type=Memory). Please note username and password were not required for access (otherwise they should be specified via respective properties).

Noteworthy here is the resultproperty, which could hold array from which we could get a name. So having in ant build script:

<typedef 
    name="jmxQuery"
    classname="org.apache.catalina.ant.jmx.JMXAccessorQueryTask" />

<jmxQuery
    host="localhost"
    port="8686"
    echo="true"
    name="java.lang:type=Memory"
    resultproperty="memory" />

<echo>Retrieved MBeans count: ${memory.Length}</echo>
<echo>The 1.st one has name: ${memory.0.Name}</echo>

results for me in following output:

 [jmxQuery] memory.Length=1
 [jmxQuery] memory.0.Name=java.lang:type=Memory
     [echo] Retrieved MBeans count: 1
     [echo] The 1.st one has name: java.lang:type=Memory

Example: Invoking operation via JMX

Here is a 2 step approach required:

  1. connect to remote server via JMX and afterwards
  2. invoke the operation on the particular MBean.

For demonstration purposes, let’s assume we want to call garbage collection (via invoking operation: gc() on MBean named: java.lang:type=Memory)

Sample ant build file chunk does the job (please note ref property value that has to be the same across these 2 tasks):

<typedef 
    name="jmxOpen"
    classname="org.apache.catalina.ant.jmx.JMXAccessorTask" />

<typedef 
    name="jmxInvoke"
    classname="org.apache.catalina.ant.jmx.JMXAccessorInvokeTask" />

<jmxOpen
    host="localhost"
    port="8686"
    ref="glassfish"
    failOnError="true" />

<jmxInvoke
    name="java.lang:type=Memory"
    operation="gc"
    echo="true"
    delimiter=" "
    failOnError="true"
    ref="glassfish" />

Further information

For more details, I recommend reading the official Tomcat documentation as well as Javadocs.

Friday, June 6, 2014

Eclipse plugin for svn integration

I’ve found it tricky to install Eclipse plugin providing svn integration.

The problem is:

  • which plugin to choose,
  • which version of the plugin to choose as well as
  • which packages to install.

I’m running latest Eclipse (Kepler SR2) and plugin of my choice is subclipse.

The Eclipse plugin update site has to be chosen based on the svn version installed on the machine (check it running svn --version):

Following packages were required for installation (for me):

  • Subclipse (Required)
  • SVNKit Client Adapter (Not Required)
  • SVNKit Library

That’s it! As it covers my Eclipse/svn day-to-day workflow.

Tuesday, March 4, 2014

p6spy 2.0.0 is out!

After 8 years P6spy came to it’s next stable release!
You can get it here.

The last stable release happened (based on maven central repo) on 27-Dec-2005 (1.3 version). That is quite some time, so one would expect many things to happen in the meantime. Well the truth is that project was (half) dead for quite some time.

Changes

I can’t comment on full history since 1.3 release (since my interest in project started last summer), still I’ve noticed following:

  • project hosting was moved from sourceforge to github,
  • major part of the legacy code was refactored,
  • Java 6/7 JDBC API support introduced,
  • proxying via modified JDBC URLs only was implemented,
    So for for MySQL original url would be:

    jdbc:mysql://<hostname>:<port>/<database>

    the one proxied via p6spy would one:

    jdbc:p6spy:mysql://<hostname>:<port>/<database>

    without a need for any further configuration,

  • XA Datasource support has been introduced,
  • configuration via:
    • system/environment properties and
    • JMX properties
    • as an alternative to file configuration only
    • or even zero config use case supported,
  • slf4j support (more flexible as previously used log4j),
  • junit tests were migrated to junit 4 (well most of the old ones were failing anyway),
  • Continuous integration using Travis was setup providing testing on popular:
    • DB systems (namely: Oracle, DB2, PostgreSQL, MySQL, H2, HSQLDB, SQLite, Firebird, and Derby), see build status on: travis-ci as well as
    • application servers (namely: Wildfly 8, JBoss 4.2, 5.1, 6.1, 7.1, Glassfish 3.1, 4.0, Jetty 7.6, 8.1, 9.1, Tomcat 6, 7, 8, Resin 4, Jonas 5.3 and Geronimo 2.1, 2.2), see build status on: travis-ci.

Full changelog

For the full changelog, see issues fixed in: 2.0.0-alpha1 as well as 2.0.0.

Postgres and Oracle compatibility with Hibernate

There are situations your JEE application needs to support Postgres and Oracle as a Database.
Hibernate should do the job here, however there are some specifics worth mentioning.
While enabling Postgres for application already running Oracle I came across following tricky parts:

  • BLOBs support,
  • CLOBs support,
  • Oracle not knowing Boolean type (using Integer) instead and
  • DUAL table.

These were the tricks I had to apply to make the @Entity classes running on both of these.

Please note I’ve used Postgres 9.3 with Hibernate 4.2.1.SP1.

BLOBs support

The problem with Postgres is that it offers 2 types of BLOB storage:

  • bytea - data stored in table
  • oid - table holds just identifier to data stored elsewhere

I guess in the most of the situations you can live with the bytea as well as I did. The other one as far as I’ve read is to be used for some huge data (in gigabytes) as it supports streams for IO operations.

Well, it sounds nice there is such a support, however using Hibernate in this case can make things quite problematic (due to need to use the specific annotations), especially if you try to achieve compatibility with Oracle.

To see the trouble here, see StackOverflow: proper hibernate annotation for byte[]

All- the combinations are described there:

annotation                   postgres     oracle      works on
-------------------------------------------------------------
byte[] + @Lob                oid          blob        oracle
byte[]                       bytea        raw(255)    postgresql
byte[] + @Type(PBA)          oid          blob        oracle
byte[] + @Type(BT)           bytea        blob        postgresql

where @Type(PBA) stands for: @Type(type="org.hibernate.type.PrimitiveByteArrayBlobType") and @Type(BT) stands for: @Type(type="org.hibernate.type.BinaryType").

These result in all sorts of Postgres errors, like:

ERROR: column “foo” is of type oid but expression is of type bytea

or

ERROR: column “foo” is of type bytea but expression is of type oid

Well, there seems to be a solution, still it includes patching of Hibernate library (something I see as the last option when playing with 3.rd party library).

There is also a reference to official blog post from the Hibernate guys on the topic: PostgreSQL and BLOBs. Still solution described in blog post seems not working for me and based on the comments, seems to be invalid for more people.

BLOBs solved

OK, so now the optimistic part.

After quite some debugging I ended up with the Entity definition like this :

@Lob
private byte[] foo;

Oracle has no trouble with that, moreover I had to customize the Postgres dialect in a way:

public class PostgreSQLDialectCustom extends PostgreSQL82Dialect {

    @Override
    public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
    if (sqlTypeDescriptor.getSqlType() == java.sql.Types.BLOB) {
      return BinaryTypeDescriptor.INSTANCE;
    }
    return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
  }
}

That’s it! Quite simple right? That works for persisting to bytea typed columns in Postgres (as that fits my usecase).

CLOBs support

The errors in misconfiguration looked something like this:

org.postgresql.util.PSQLException: Bad value for type long : ...

So first I’ve found (on String LOBs on PostgreSQL with Hibernate 3.6) following solution:

@Lob
@Type(type = "org.hibernate.type.TextType")
private String foo;

Well, that works, but for Postgres only.

Then there was a suggestion (on StackOverflow: Postgres UTF-8 clobs with JDBC) from to go for:

@Lob
@Type(type="org.hibernate.type.StringClobType")
private String foo;

That pointed me the right direction (the funny part was that it was just a comment to some answers). It was quite close, but didn’t work for me in all cases, still resulted in errors in my tests.

CLOBs solved

The important was @deprecation javadocs in the org.hibernate.type.StringClobType that brought me to working one:

@Lob
@Type(type="org.hibernate.type.MaterializedClobType")
private String foo;

That works for both Postgres and Oracle, without any further hacking (on Hibernate side) needed.

Boolean type

Oracle knows no Boolean type and the trouble is that Postgres does. As there was also some plain SQL present, I ended up In Postgres with error:

ERROR: column “foo” is of type boolean but expression is of type integer

I decided to enable cast from Integer to Boolean in Postgres rather than fixing all the plain SQL places (in a way found in Forum: Automatically Casting From Integer to Boolean):

update pg_cast set castcontext = 'i' where oid in ( select c.oid from pg_cast c inner join pg_type src on src.oid = c.castsource inner join pg_type tgt on tgt.oid = c.casttarget where src.typname like 'int%' and tgt.typname like 'bool%');

Please note you should run the SQL update by user with provileges to update catalogs (probably not your postgres user used for DB connection from your application), as I’ve learned on Stackoverflow: Postgres - permission denied on updating pg_catalog.pg_cast.

DUAL table

There is one more specific in the Oracle I came across. If you have plain SQL, in Oracle there is DUAL table provied (see more info on Wikipedia on that) that might harm you in Postgres.

Still the solution is simple. In Postgres create a view that would fill the similar purpose. It can be created like this:

create or replace view dual as select 1;

Conclusion

Well that should be it. Enjoy your cross DB compatible JEE apps.

Tuesday, December 17, 2013

Liquibase - implementing custom type.

There are some things to keep in mind while implementing custom type in liquibase. Let's see how to create one.

Existing database types

Well, this might be the biggest advantage of using/hacking the open source projects. You have a chance to see how are things done. This is useful to find your inspiration, the places that require modifications and the hooks to existing system.

Classes worth checking for our purposes are in the package:
liquibase.datatype.core
You can browse them directly on github.

Sample custom BlobType implementation

Let's assume we're about to modify BlobType. Our implementation could look like this:
package liquibase.datatype.core;

import liquibase.database.Database;
import liquibase.database.core.PostgresDatabase;
import liquibase.datatype.DataTypeInfo;
import liquibase.datatype.DatabaseDataType;
import liquibase.datatype.LiquibaseDataType;

@DataTypeInfo(name = "blob", aliases = { "longblob", "longvarbinary", "java.sql.Types.BLOB",
    "java.sql.Types.LONGBLOB", "java.sql.Types.LONGVARBINARY", "java.sql.Types.VARBINARY",
    "varbinary" }, minParameters = 0, maxParameters = 0, priority = LiquibaseDataType.PRIORITY_DATABASE)
public class BlobTypeTest extends BlobType {
  
  public DatabaseDataType toDatabaseDataType(Database database) {
    // handle the specifics here, you can go for the per DB specifics, let's assume Postgres
    if (database instanceof PostgresDatabase) {
       // your custom type here
    }
    // use defaults for all the others
    return super.toDatabaseDataType(database);
  }

}

Specifics to keep in mind

There are some specifics that should be considered:
  • DataType priority is important

    To make sure our type will be considered in favor to default implementation. We're going for:
    priority = LiquibaseDataType.PRIORITY_DATABASE
    
    where the default one (in the supertype) is:
    priority = LiquibaseDataType.PRIORITY_DEFAULT
    
    This just means that our implementation should be considered in favor to default one.

    See method:
    liquibase.datatype.DataTypeFactory.register()
    
    implementation for details.
  • DataType registration considers specific packages to be scanned only

    We have more options here, but our stuff should go to any of these:
    • any of those listed in jar/MANIFEST.MF property:
      Liquibase-Package
      
      Where the default set in the liquibase-core-3.0.8.jar is:
      Liquibase-Package: liquibase.change,liquibase.database,liquibase.parse
       r,liquibase.precondition,liquibase.datatype,liquibase.serializer,liqu
       ibase.sqlgenerator,liquibase.executor,liquibase.snapshot,liquibase.lo
       gging,liquibase.diff,liquibase.structure,liquibase.structurecompare,l
       iquibase.lockservice,liquibase.ext
      
    • comma separated custom package list provided via system property called:
      liquibase.scan.packages
      
    • if all of the above are empty, note the fallback package list is used. As implementation says:
      if (packagesToScan.size() == 0) {
      	addPackageToScan("liquibase.change");
      	addPackageToScan("liquibase.database");
      	addPackageToScan("liquibase.parser");
      	addPackageToScan("liquibase.precondition");
      	addPackageToScan("liquibase.datatype");
      	addPackageToScan("liquibase.serializer");
      	addPackageToScan("liquibase.sqlgenerator");
      	addPackageToScan("liquibase.executor");
      	addPackageToScan("liquibase.snapshot");
      	addPackageToScan("liquibase.logging");
      	addPackageToScan("liquibase.diff");
      	addPackageToScan("liquibase.structure");
      	addPackageToScan("liquibase.structurecompare");
      	addPackageToScan("liquibase.lockservice");
      	addPackageToScan("liquibase.ext");
      }
      

    See method:
    ServiceLocator.setResourceAccessor()
    
    implementation for details.

    Well, as you might have noticed, I'm lazy enough as I went for the already registered package:
    liquibase.datatype.core
    
    so it worked once my implementation is on the classpath.
That should be it.

Debugging ant task

It's allways good idea to debug once playing around with the custom changes in the 3.rd party code.
As I went for ant task, just addopted ANT_OPTS variable. In my case (as I'm on linux) following worked:
export ANT_OPTS="-Xdebug -agentlib:jdwp=transport=dt_socket,server=y,address=8000"
remote debugging was possible afterwards.

To check if custom type is registered, check in the debug session the constructor:
DataTypeFactory.DataTypeFactory()
local variable "classes" contents after line:
classes = ServiceLocator.getInstance().findClasses(LiquibaseDataType.class);
to see all the types found.

That should provide you the basics on liquibase types hacking.

Monday, December 16, 2013

Oracle JDK 1.7.0_u45 incompatibility with Glassfish 3.x (Corba)

Q: Did you give a try to Glassfish 3.1.x with latest stable JDK (1.7.0_u45)?
A: Well, you might be interested in possible trouble there.

After quite some debugging of weird error happening, namely:
Caused by: java.lang.ArrayIndexOutOfBoundsException: -1636631191
at java.util.HashMap.put(HashMap.java:498)
at java.util.HashSet.add(HashSet.java:217)
...
I ended up creating: https://java.net/jira/browse/GLASSFISH-20927 (Btw, it was quite weird, but I'm not allowed to add attachments in their jira :)
The problem seems to be in internals of the HashSet -> HashMap. Where Corba doesn't seem to set the expected reference to EMPTY_TABLE in case of empty Set. Let's see how they proceed with the analysis.

Tuesday, September 3, 2013

EJB 3.1 - Local and Remote business interfaces must differ

Have you ever seen something like this?
Exception during lifecycle processing
java.lang.IllegalStateException: The interface XYZ cannot be both a local and a remote business interface
 at com.sun.enterprise.deployment.archivist.Archivist.readAnnotations(Archivist.java:518)
 at com.sun.enterprise.deployment.archivist.Archivist.readAnnotations(Archivist.java:446)
 at com.sun.enterprise.deployment.archivist.Archivist.readRestDeploymentDescriptors(Archivist.java:419)
 at com.sun.enterprise.deployment.archivist.Archivist.readDeploymentDescriptors(Archivist.java:396)
 at com.sun.enterprise.deployment.archivist.Archivist.open(Archivist.java:271)
 at com.sun.enterprise.deployment.archivist.Archivist.open(Archivist.java:280)
 at com.sun.enterprise.deployment.archivist.ApplicationArchivist.readModulesDescriptors(ApplicationArchivist.java:611)
 at com.sun.enterprise.deployment.archivist.ApplicationArchivist.openWith(ApplicationArchivist.java:229)
 at com.sun.enterprise.deployment.archivist.ApplicationFactory.openWith(ApplicationFactory.java:232)
 at org.glassfish.javaee.core.deployment.DolProvider.processDOL(DolProvider.java:188)
 at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:222)
 at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:96)
 at com.sun.enterprise.v3.server.ApplicationLifecycle.loadDeployer(ApplicationLifecycle.java:878)
 at com.sun.enterprise.v3.server.ApplicationLifecycle.setupContainerInfos(ApplicationLifecycle.java:818)
 at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:374)
 at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219)
 at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:527)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:523)
 at java.security.AccessController.doPrivileged(Native Method)
 at javax.security.auth.Subject.doAs(Subject.java:356)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl$2.execute(CommandRunnerImpl.java:522)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:546)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1423)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1500(CommandRunnerImpl.java:108)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1762)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1674)
 at org.glassfish.admin.rest.resources.admin.CommandResource.executeCommand(CommandResource.java:396)
 at org.glassfish.admin.rest.resources.admin.CommandResource.execCommandSimpInMultOut(CommandResource.java:234)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:606)
 at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
 at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:125)
 at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:152)
 at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:91)
 at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:346)
 at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:341)
 at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:101)
 at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:224)
 at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
 at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
 at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
 at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
 at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
 at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
 at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:198)
 at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:946)
 at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:331)
 at org.glassfish.admin.rest.adapter.JerseyContainerCommandService$3.service(JerseyContainerCommandService.java:165)
 at org.glassfish.admin.rest.adapter.RestAdapter.service(RestAdapter.java:181)
 at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:246)
 at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
 at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
 at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
 at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
 at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
 at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
 at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
 at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
 at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
 at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
 at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
 at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
 at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
 at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
 at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
 at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
 at java.lang.Thread.run(Thread.java:724)
Caused by: The interface XYZ cannot be both a local and a remote business interface
 at org.glassfish.ejb.deployment.annotation.handlers.AbstractEjbHandler.setBusinessAndHomeInterfaces(AbstractEjbHandler.java:471)
 at org.glassfish.ejb.deployment.annotation.handlers.StatelessHandler.setEjbDescriptorInfo(StatelessHandler.java:143)
 at org.glassfish.ejb.deployment.annotation.handlers.AbstractEjbHandler.processAnnotation(AbstractEjbHandler.java:270)
 at com.sun.enterprise.deployment.annotation.factory.SJSASFactory$LazyAnnotationHandler.processAnnotation(SJSASFactory.java:148)
 at org.glassfish.apf.impl.AnnotationProcessorImpl.process(AnnotationProcessorImpl.java:344)
 at org.glassfish.apf.impl.AnnotationProcessorImpl.process(AnnotationProcessorImpl.java:375)
 at org.glassfish.apf.impl.AnnotationProcessorImpl.processAnnotations(AnnotationProcessorImpl.java:289)
 at org.glassfish.apf.impl.AnnotationProcessorImpl.process(AnnotationProcessorImpl.java:195)
 at org.glassfish.apf.impl.AnnotationProcessorImpl.process(AnnotationProcessorImpl.java:134)
 at com.sun.enterprise.deployment.archivist.Archivist.processAnnotations(Archivist.java:626)
 at com.sun.enterprise.deployment.archivist.Archivist.readAnnotations(Archivist.java:462)
 ... 69 more
where XYZ would be the name of the interface referred as Local and Remote from some stateless session bean.

Well, once I did migration to Glassfish 4.0 I've noticed that. The message is quite clear, however the question is why that would be a problem. As having one interface serving as Local as well as Remote for stateless session EJB is quite common practice I think.

Root cause

The JBoss forum message pointed me to the right direction.

The thing is that EJB 3.1 specs (implemented in Glassfish 4.0) section 4.9.7 says:
The same business interface cannot be both a local and a remote business interface of the bean.
For those interested, see the full specs on: http://download.oracle.com/otndocs/jcp/ejb-3.1-fr-eval-oth-JSpec/

Solution

OK, but how to fix it? I recommend you to read Adam Bien's suggestion.

Basically, the idea might be the analogy to package protection present in java and easy solution can be creation of extra interface that would inherit existing one and be used as Local. Possibly having Local suffix.

Saturday, May 25, 2013

debugging fornax-oaw-m2-plugin maven plugin

Question: Do you need to debug maven plugin: fornax-oaw-m2-plugin ?
If so, go on reading.

You can find the basic info at their home page:
However remote debugging topic is not covered there.
The problem with maven plugins might be, that sometimes it's not enough to debug maven run itself (as described in my previous post).

However merging information from the previous links with common remote debugging options I came to solution that simply works for me:

<build>
  <plugins>
    <plugin>
      <groupId>org.fornax.toolsupport</groupId>
      <artifactId>fornax-oaw-m2-plugin</artifactId>
      <version>2.1.1</version>
      <type>pom</type>
      <configuration>
        <!-- [BEGIN] debugging related section -->
        <jvmSettings>
          <jvmArgs>
            <jvmArg>-Xdebug</jvmArg>
            <jvmArg>-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8100</jvmArg>
            <jvmArg>-Xnoagent</jvmArg>
            <jvmArg>-Djava.compiler=NONE</jvmArg>
          </jvmArgs>
        </jvmSettings>
        <!-- [END] debugging related section -->
      </configuration>
      <executions>
        <execution>
          <phase>generate-sources</phase>
          <goals>
            <goal>run-workflow</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
Please note that port to remotely connect to with debugger is 8100 in my sample. Feel free to adapt it based on your setup.

After using the configuration in your run, you should get to point where plugin run gets suspended and waits for remote debugger to connect (to find out how to remotelly debug, see some existing tutorial, like this one: http://java.dzone.com/articles/how-debug-remote-java-applicat).

That's it. Enjoy your debugging session.

This post is from pb's blog.

Wednesday, March 27, 2013

Glassfish: showing jndi tree

To list the jndi tree entries in the glassfish use:

$GLASSFISH_HOME/glassfish/bin/asadmin list-jndi-entries

Monday, February 18, 2013

Java web start: running unsigned jars

Q: Did you ever need to run unsigned jar files referred from jnlp (java web start)?

There is a simple (but dangerous) way.
There might be various reasons such a bad thing (bad from the security point of view), but most probably to speed up development (as jars signing is quite time intensive process).

Depending if you have jdk/jre installed add to the file (in my case jdk installed):
$JAVA_HOME/jre/lib/security/javaws.policy
following:
grant {
    permission java.security.AllPermission;
};
Since now on you should be able to run even unsigned code started using javaws command.

Maven: listing dependencies

Q: Did you ever try to find out all the dependencies in the maven project (even transitive ones)?
A: maven-dependency-plugin should help here.

Following is the command I use to find out:
mvn dependency:tree -Dverbose

Thursday, February 14, 2013

Glassfish: default keystore and truststore

Q: Do you need to use keystores/truststores of the glassfish OSE?

There are 2 files you should be interested in (please note domain1 used by me):
  • $GLASSFISH_HOME/domains/domain1/config/cacerts.jks - truststore - holding all the public keys
  • $GLASSFISH_HOME/domains/domain1/config/keystore.jks - keystore - holding all the private keys

The default alias used for the secured http-listeners is called: s1as.

To examine the contents


To list truststore contents use:
keytool -list -v -storepass changeit -keystore $GLASSFISH_HOME/domains/domain1/config/keystore.jks
keytool -list -v -storepass changeit -keystore $GLASSFISH_HOME/domains/domain1/config/cacerts.jks
Please note that you need to adapt path to keystores, depending on domains used as well as password you have configured for glassfish to protect the keystore/truststore.

Digging deeper


Default keys are generated during domain creation via asadmin's create-domain command.

Implementation is present in (in my case I refer to version 3.1.1): https://svn.java.net/svn/glassfish~svn/tags/3.1.1/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/KeystoreManager.java
see methods:
createKeyStore()
createTrustStore()

Glassfish: sources

Where are all those sources of the glassfish that one can use for addapting the behavior/studing the way it operates?

I've found following link for svn access:
https://svn.java.net/svn/glassfish~svn

Therefor as in my case if I need 3.1.1 version I can obtain it simply via:
svn co https://svn.java.net/svn/glassfish~svn/tags/3.1.1/ glassfish_3.1.1

Tuesday, February 5, 2013

Java Web Start: debugging

Have you ever been in a need to debug JWS application?

One way to do the trick is to adapt environment variable: JAVAWS_VM_ARGS

As I'm running linux and need this in my daily work, I added following to my .bashrc file:
export JAVAWS_VM_ARGS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=9010,server=y,suspend=n -XX:MaxPermSize=128m"

Some notes:
  • suspend=n - this makes sence for me, as I'm not waiting for debugger to connect. To make sure I connect only once I'm interested. And app won't get stuck
  • -XX:MaxPermSize=128m - is not related to debugging but rather to memory, feel free to remove/adapt to your needs

After jws runs, I can connect from eclipse to port configured, in my case: 9010 (use the one that fits your environment) and remotely debug the app.

That's it. Easy, right?

There are however also some disadvatages of my simple solution.
Major one is that I can have only one JWS instance running at time. As there is a port conflict (same ons is in use for every one), but I can live with that.

Glassfish: Exception while shutting down application container : java.lang.NullPointerException

OK, this one is one of the crazy ones :)
Have you ever seen exception like this in your glassfish server logs during ear deployment?
[#|2013-02-05T08:08:40.769+0100|SEVERE|glassfish3.1.1|javax.enterprise.system.tools.admin.org.glassfish.deployment.admin|_ThreadID=90;_ThreadName=Thread-2;|Exception while shutting down application container|#]

[#|2013-02-05T08:08:40.938+0100|SEVERE|glassfish3.1.1|javax.enterprise.system.tools.admin.org.glassfish.deployment.admin|_ThreadID=90;_ThreadName=Thread-2;|Exception while shutting down application container : java.lang.NullPointerException|#]
Well I did, today. And as I've googled, noone could ever get some more meaningfull stacktrace out of it. Sounds like a nightmare. So where the problem could be?

In development following rule usually works for me:
If you can't get any meaningful information on the problem you're facing and googling didn't help, think of what has been changed since the last success. 
(Well this doesn't seem to be always applicable, but most of the time it is)

This rule was also worked for another guy facing similar exception.

Well in my case too many things changed, but I had backup of the last successfully built artifact. Comparing it with the latest one I've found out that I forgot to include commons-pool dependency in my ear file. So finally following did the trick for me:
<dependency>
 <groupId>commons-pool</groupId>
 <artifactId>commons-pool</artifactId>
 <version>1.6</version>
 <scope>runtime</scope>
</dependency>
As I introduced for client-server communication spring remoting (as a corba alternative) where pooling is used.

So hey, that wasn't so bad although exception handling of glassfish didn't show something useful! I tought I'll be stuck here for at least a day :)

Friday, December 14, 2012

jumpstart with eclipse, maven and tomcat (web/app server)

Q: What is the quick way to setup Eclipse war (possibly ear) project built with maven? 

A: In short: Eclipse + wtp + m2e + m2e-wtp

Sometimes from idea to it's realization is not an easy way.

If you're in a need to quickly setup java war project and you like the tools I do: maven, eclipse and tomcat (or any other server of your choice) following might be useful to jumpstart realizing your ideas.

My requirements

I've searched for a solution that would enable me to:
- use eclipse for application development
- manage server lifecycle directly from eclipse and
- use maven as a build tool.

My choice

Following has been found and based on the short project I've tested it with, it worked very well:
- eclipse - no doubts here (it's my favorite IDE for java development)
- wtp - fits me best for the server management directly from eclipse
- m2e - maven eclipse integration (as I'm in love with maven)
- wtp-m2e - wtp m2e integration (this one I've been missing in the puzzle, but only until today)

As  the last one mentioned was new to me the following video convicted me that it's something I need:

 
(the video is reffered on the official site as well)

After the initial project setup (depicted on the video) right clicking on the project and choosing "Run/Debug As" -> "Run/Debug on Server" does the job of publish and run/debug.

And once you change your project contents automatic republish happens in the background as well.

Sounds like the initial infrastructure setup time for my next project can be the question of seconds rather that hours.

Friday, November 30, 2012

My fedora java 7 update

Today I've migrated to java 7 (Oracle version), as our development environment has been "java 7 enabled".

The transition was "rather" smooth, I just had to follow following description: http://fedorasolved.org/Members/zcat/using-sun-java-instead-of-openjdk

When I mentioned "rather", it was not due to description present on the mentioned site :). After I rebooted I could not login to my xfce (or gnome,...), login screen was shown again even after correct password input.

The problem was caused by my laziness. I didn't really read what I copy/pasted :)

After switching to text mode (Ctrl+Alt+F<X>) I've observed some EOF reported problem right after login. And my bash didn't behave :) I had to provide full path when invoking commands.

When thinking of what I've changed, file: /etc/profile.d/sunjava.sh started to be suspicious, after opening it via:
/usr/bin/sudo /usr/bin/vi /etc/profile.d/sunjava.sh
(yes, path didn't work for me somehow :)

my suspect changed to culprit when seeing the content:
export JAVA_HOME=/usr/java/default
export PATH=\$JAVA_HOME/bin:\$PATH
EOF
after fixing it to:
export JAVA_HOME=/usr/java/default
export PATH=$JAVA_HOME/bin:$PATH
and doing the reboot afterwards, via:
/usr/bin/sudo /usr/bin/reboot
all started to work as expected.

So it seems trivial things might become challenges in my hands :)
Now I see why I became a programmer rather than a doctor :)

Friday, November 23, 2012

Maven java.lang.ClassNotFoundException: org.codehaus.plexus.classworlds.launcher.Launcher

Have you ever faced exception like this?
Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/plexus/classworlds/launcher/Launcher
Caused by: java.lang.ClassNotFoundException: org.codehaus.plexus.classworlds.launcher.Launcher
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Could not find the main class: org.codehaus.plexus.classworlds.launcher.Launcher.  Program will exit.
My use case was that I had installed maven3 and afterwards tried to use maven2. All the environment variables updates have been setup in:
~/.bashrc
However once trying to use maven2 exception appeared (Even in the new terminal session).
Solution was found based on advice present in: http://cyntech.wordpress.com/2011/03/09/maven-2-error/

Running command:
which mvn
revealed the problem, as I still had in my $PATH the maven3 binary. Even if I appended the maven2, it was there on the later position => maven3 was to be used, but with changed $M2_HOME (reffering to maven 2).

Fixing the $PATH did the job for me.

This might not be your case, therefor as a general sum up of possible root causes, I recommend checking: http://stackoverflow.com/questions/6198677/java-lang-noclassdeffounderror-org-codehaus-plexus-classworlds-launcher-launche

Friday, November 16, 2012

Glassfish 3.1.1 OSE with Hibernate Validator 4.3.0.Final

Goal: Use hibernate validator 4.3.0.Final with Glassfish 3.1.1 OSE.

Lately I came across an issue, that I wasn't able to use the latest stable hibernate validator (hiberante validator 4.3.0.Final) with Glassfish 3.1.1 OSE.

Problem is that older version is beeing used as a glassfish module (glassfish/modules/bean-validator.jar). If you check the contents of the package (in MANIFEST.MF) you'd see that version 4.1.0.Final is beeing used.

OK, so how to deal with that? I've found out that I'm not the only one having issue here.
http://stackoverflow.com/questions/10548931/how-to-upgrade-the-hibernate-validator-4-3-0-final-to-the-glassfish-3-1-2

Suggestion gave me some motivation, as it seems to be possible to achieve :)

As I'm using ear, the simple solution provided in answer was not feasable for me (as it was a war case). OK, let's see how far we can get. There are multiple references (finally I ended up with the following 2 links):
I read the later one, as it seemd like a good idea to learn creating modules deployable to glassfish, however even if I created maven osgi bundle it neither contained all the dependencies required nor the descriptor seemed to be OK. Sounds like a wrong way for me then.

Going back to the 1.st link, I found following svn repository and tried to build things: https://svn.java.net/svn/glassfish~svn/trunk/external/source-build
However only once it has been achieved (and the way there was quite long) I realized that this just rebuilds the hibernate validator with it's dependencies, and that is of course not needed, as these are already built and available in public maven repositories :).

OK, going via next steps in the article, I ended up with the following solution:
  1. checked out glassfish sources
    svn co https://svn.java.net/svn/hk2~svn/branches/hk2-gf-3.1.1/
    
  2. updated bean-validation related pom, see my diff:
    Index: pom.xml
    ===================================================================
    --- pom.xml (revision 4105)
    +++ pom.xml (working copy)
    @@ -54,9 +54,10 @@
              maven-bundle-plugin and hk2-maven-plugin together -->
         <packaging>jar</packaging>
         <properties>
    -      <hibernate-validator.version>4.2.0.Final</hibernate-validator.version>
    +      <hibernate-validator.version>4.3.0.Final</hibernate-validator.version>
           <javax.validation.version>1.0</javax.validation.version>
           <slf4j.version>1.6.1</slf4j.version>
    +      <jboss-logging.version>3.1.0.CR2</jboss-logging.version>
         </properties>
         <name>Validation API (JSR 303) version ${javax.validation.version}, Hibernate Validator version ${hibernate-validator.version} and its dependencies repackaged as OSGi bundle</name>
     
    @@ -89,7 +90,7 @@
                             <Embed-Dependency>
                                 <!-- Only specify root artifacts that need to be embedded, everything else
                                      will be pulled in automatically based on Private-Package settings. -->
    -                            *; artifactId=hibernate-validator|slf4j-api|slf4j-jdk14; inline=true
    +                            *; artifactId=hibernate-validator|jboss-logging|slf4j-api|slf4j-jdk14; inline=true
                             </Embed-Dependency>
                             <Export-Package>
                                  <!-- 
    @@ -105,7 +106,7 @@
     
                             <Private-Package>
                                  <!-- Have a private copy of external non-standard dependencies -->
    -                             org.slf4j.*; com.googlecode.jtype.*; org.joda.time.*; org.jsoup.*
    +                             org.jboss.logging.*; org.slf4j.*; com.googlecode.jtype.*; org.joda.time.*; org.jsoup.*
                             </Private-Package>
     
                             <Import-Package>
    @@ -117,6 +118,12 @@
                                    which is a JPA 2 class.
                                -->
                                org.slf4j; org.slf4j.spi; org.slf4j.helpers; version=${slf4j.version}; resolution:=optional,
    +                           org.jboss.logging; version=${jboss-logging.version}; resolution:=optional,
    +                           org.apache.log4j;resolution:=optional,
    +                           org.jboss.logmanager;resolution:=optional,
    +                           com.ibm.uvm.tools;resolution:=optional,
    +                           com.sun.jdmk.comm;resolution:=optional, 
    +                           javax.jmdns;resolution:=optional,
                                javax.persistence.*; version="2.0"; resolution:=optional,
                                *
                            </Import-Package>
    @@ -263,6 +270,13 @@
             </dependency>
     
     
    + <dependency>
    +  <groupId>org.jboss.logging</groupId>
    +  <artifactId>jboss-logging</artifactId>
    +  <version>${jboss-logging.version}</version>
    +            <optional>true</optional>
    + </dependency>
    +
             <!-- We bundle jdk binding inside this OSGi bundle -->
             <dependency>
                <groupId>org.slf4j</groupId>
    
  3. built:
    cd hk2-gf-3.1.1/external/bean-validator
    mvn clean install
    
  4. copied to glassfish modules and removed old one:
    rm ${GLASSFISH_HOME}/glassfish/modules/bean-validator.jar
    cp hk2-gf-3.1.1/external/bean-validator/target/bean-validator-1.1.15-SNAPSHOT.jar ${GLASSFISH_HOME}/glassfish/modules/
    
  5. done :)

Issues? well, we'll see later, during testing :) But very first try worked perfectly.

Comments? Feel free to share, as I'm not the osgi expert (yet :)), so some of my updates might ... let's say won't make too much sense.

Monday, June 25, 2012

let me introduce you project Lombok

Problem: Have you ever been in a situation, when you tough that creating all those boring equals(), hashCode(), toString() methods is quite time consuming and maintaining these is error prone?
Solution: If so, read on :) Project Lombok might be the answer.

Yesterday, while searching for some solution on this (with having in mind the tutorial of spring roo I've read quite some time ago where these could be handled by AOP using annotations) I've found as a possible solution project Lombok:
http://projectlombok.org

Lombok demo and features list
I really like their demo video, if you want an introduction to this project, make sure you watch it:
http://projectlombok.org/
And there is also quite nice feature list available: 
http://projectlombok.org/features/index.html

Encouragement
OK, so what's next? Am I brave enough to go for it? While doubing it I've found out I'm not the only one:
http://stackoverflow.com/questions/3852091/is-it-safe-to-use-project-lombok

That gave me some encouragement. So let's go and try it.

I have some small open source project, so let me show you my code prio and after the change to give you an overview (or rather motivation :)).

Code snippets comparison
See:
  • eclipse generated methods:
    // eclipse generated methods way
    public class Schedule implements Serializable {
    
    ...
    
     @Override
     public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((bgImage == null) ? 0 : bgImage.hashCode());
      result = prime * result + (blank ? 1231 : 1237);
      result = prime * result + (clear ? 1231 : 1237);
      result = prime * result + (live ? 1231 : 1237);
      result = prime * result + ((name == null) ? 0 : name.hashCode());
      result = prime * result
        + ((presentations == null) ? 0 : presentations.hashCode());
      return result;
     }
    
     @Override
     public boolean equals(Object obj) {
      if (this == obj)
       return true;
      if (obj == null)
       return false;
      if (getClass() != obj.getClass())
       return false;
      Schedule other = (Schedule) obj;
      if (bgImage == null) {
       if (other.bgImage != null)
        return false;
      } else if (!bgImage.equals(other.bgImage))
       return false;
      if (blank != other.blank)
       return false;
      if (clear != other.clear)
       return false;
      if (live != other.live)
       return false;
      if (name == null) {
       if (other.name != null)
        return false;
      } else if (!name.equals(other.name))
       return false;
      if (presentations == null) {
       if (other.presentations != null)
        return false;
      } else if (!presentations.equals(other.presentations))
       return false;
      return true;
     }
    
     @Override
     public String toString() {
      return "Schedule [presentations=" + presentations + ", bgImage="
        + bgImage + ", name=" + name + ", blank=" + blank + ", clear="
        + clear + ", live=" + live + "]";
     }
    
    }
    
  • Lombok way:
    // lombok way
    @ToString
    @EqualsAndHashCode
    public class Schedule implements Serializable {
    
    ...
    
    }
    
  • manually written ones with Equals/ToString/HashCode Builders:
    // manual way using Equals/ToString/HashCode Builders
    public class Schedule implements Serializable {
    
    ...
    
     @Override
     public int hashCode() {
      return new HashCodeBuilder()
      .append(this.getPresentations())
      .append(this.getBgImage())
      .append(this.getName())
      .append(this.isBlank())
      .append(this.isClear())
      .append(this.isLive())
      .toHashCode();
     }
    
     @Override
     public boolean equals(Object obj) {
      if ( !(obj instanceof Schedule) ) return false;
      Schedule castOther = (Schedule) obj;
      return new EqualsBuilder()
       .append(this.getPresentations(), castOther.getPresentations())
       .append(this.getBgImage(), castOther.getBgImage())
       .append(this.getName(), castOther.getName())
       .append(this.isBlank(), castOther.isBlank())
       .append(this.isClear(), castOther.isClear())
       .append(this.isLive(), castOther.isLive())
       .isEquals();
     }
    
     @Override
     public String toString() {
      return new ToStringBuilder(this)
      .append("\n presentations", this.getPresentations())
      .append("\n bgImage", this.getBgImage())
      .append("\n name", this.getName())
      .append("\n blank", this.isBlank())
      .append("\n clear", this.isClear())
      .append("\n live", this.isLive())
      .append("\n")
      .toString();
     }
    
    }
    
So as obvious from the samples, instead of writing/maintaining the code you can rather just annotate. (Btw. if there were no lombok way, I'd go for Builders way => manual writing + maintaining).

Integration
The great thing is that there is a simple integration with maven (that is the build tool of my choice). See instructions:
http://projectlombok.org/mavenrepo/index.html
Moreover integration with Eclipse seems really straitforward too (all the autocompletition as well as Outline view work as expected or rather unexpectedly well).

Some more motivation
To encourage lazy developers (like me) even more, there are things available for:
- getters and setters (@Getter, @Setter)
- logging (depending on your logging library: @CommonsLog, @Log, @Log4j, @Slf4j)
- there is even more, but for the rest I might not be brave enough ( yet :))

Behind the scenes
OK, sounds nice, but how it works internally?
In fact lombok generates expected methods/fields to the target class. So the nice thing is that you don't need it during runtime/deployment. Once compiled, classes will contain the stuff.

How do you guys feel about it? Would you give it a try? Or do you have some other approach on this? Feel free to share your ideas/feelings.