blue_cowdawg has asked for the wisdom of the Perl Monks concerning the following question:

The day I discovered Inline::Java I was very happy. Now for some of these Java projects I am working on I can reuse the code I wrote in Java from Perl. Hmmm.. was this what they meant by "write once run everywhere?" Probably not, but hey!

Here's something I ran into. I have some Java classes that are implemented as singletons. Mostly to do with database access and persisted objects. These classes follow the following pattern:

package com.schooner.test; public class JumpClass { private static JumpClass instance = null; private JumpClass(){ } public static synchronized JumpClass getInstance(){ if ( instance == null ) { instance = new JumpClass(); } return instance; } }
For those that don't know what singleton behavior is I can sum it up by saying that a singleton gets created once and does not get re-instatiated so you have exactly one copy of it in memory.

So, now I want to access it from Perl. From Java I would do something like:

import com.schooner.test.JumpClass; | | Waving of hands.... | JumpClass j = JumpClass.getInstance(); | |
and in doing so j now points to the one and only instance of JumpClass in memory and I can do stuff with it. Pretty handy when you want to open a connection to a database and not open too many handles to it from the same application.

So now I try and do the analog of that from Perl. Here's what I'm talking about:

#!/usr/bin/perl -w use strict; use Data::Dumper; use Inline ( Java => 'STUDY', STUDY => [ qw / com.schooner.test.JumpClass / ], AUTOSTUDY => 1, CLASSPATH=> '.' ); my $jc = JumpClass::getInstance();
Right? WRONG!

When I attempt to run that I get:

Undefined subroutine &JumpClass::GetInstance called at jtest.pl line 4 +2.
Huh? It is so!

So I decide to get clever and I do the following:

my $jc=main::com::schooner::test::JumpClass::getInstance();
That should work... right? WRONG! That yeilds:
Can't call method "__validate_prototype" on an undefined value at (eva +l 11) line 45.

OK... what is a defrocked Saint of a Perl guy supposed to do?

Another bit of cleverness, but it is ugly in my opinion....

#!/usr/bin/perl -w use strict; use Data::Dumper; use Inline ( Java => 'STUDY', STUDY => [ qw / com.schooner.test.JumpClass / ], AUTOSTUDY => 1, CLASSPATH=> '.' ); use Inline ( Java => qq( import com.schooner.test.JumpClass; public class SingletonWrapper { public SingletonWrapper(){} public JumpClass getInstance(){ JumpClass j = JumpClass.getInstance(); return j; } } ), CLASSPATH => "." ); my $jc =(new SingletonWrapper())->getInstance(); # print Dumper($jc); #my $jc=main::com::schooner::test::JumpClass::getInstance(); print Dumper($jc);
That worked! Here's the result:
$VAR1 = bless( {}, 'main::com::schooner::test::JumpClass' );

OK: So what is the right way to do this? Is this a bug? Is this a feature? Why can't I access the singleton (or other public methods/values) directly?

Thoughts?


Peter L. Berghold -- Unix Professional
Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg

Replies are listed 'Best First'.
Re: Accessing a Java singleton class from a Perl script using Inline::Java
by Joost (Canon) on Nov 05, 2005 at 14:56 UTC
    I haven't tested this at all, but it seems to me that:
    my $jc=main::com::schooner::test::JumpClass::getInstance();
    Is wrong: it's not a method call. You should probably use:
    my $jc=main::com::schooner::test::JumpClass->getInstance();

    Note the -> arrow. That will ensure amongst other things that the "class" will be passed to the getInstance() method.

    edit: you can also leave off the "main::" part of the package.

          Note the -> arrow. That will ensure amongst other things that the "class" will be passed to the getInstance() method.

      Thanks Joost! You were on the money! That was the one thing I didn't think of last night!