Answering my own post, how sad is that?
Anyway after a fairly short night and several hours banging
my head against this one.
Compiling gateway classes for idiots (on windows)
So this is not straight forward if, like me, you are a Java
novice and the Coldfusion docs aren't actually that helpful.
So here goes….
I had a problem with the SocketGateway, the app sending us
messages objected to the "Welcome to the ColdFusion Socket Gateway
Connected to Socket XXXXXXX" message that you get when you
initially connect to the socket.
So I looked at the
C:\CFusionMX7\gateway\src\examples\socket\SocketGateway.java file
and found 2 lines of code that looked like prime suspects.
out.println("Welcome to the ColdFusion Socket Gateway" +
"\r\nConnected to Socket " + this.getName());
out.print("> ");
So I figured I could comment those out like this.
// removed to prevent initial hello
//
// out.println("Welcome to the ColdFusion Socket Gateway" +
"\r\nConnected to Socket " + this.getName());
// out.print("> ");
I decided not to change the actual SocketGateway.java file. I
created a new directory called silentsocket alongside the socket
directory and copied the java file over. I renamed it
SilentSocketGateway.java so I wouldn't corrupt the original. So its
final path ended up like this
C:\CFusionMX7\gateway\src\examples\silentsocket\SilentSocketGateway.java.
At this point I am feeling really smug, but there's a lot
more pain to come.
For one thing you have to have a Java compiler installed not
just a runtime.
Given some past experiences and the advice found on
http://www.rickroot.com/blog/1/2006/02/Compiling-Custom-Event-Gateways-For-Dummies.cfm
(a very good but unfortunately Unix oriented posting) I downloaded
the oldest version of the Java SDK I could find. Version 1.4.2.12.
Installing this is pretty straight forward. It installs into
a directory called C:\j2sdk1.4.2_12
Now I cheated and altered the PATH environment variable so I
could access the javac compiler form anywhere. The PATH environment
variable is a list of directories that Windows searches when you
type something on the command line. It will look in the current
directory first and then all the directories that are in the PATH
environment variable until it finds something that matches what you
typed and it will then run that program (or batch file if that's
what it is)
So I did this by starting a command line window Start Menu
-> Run type CMD and press return.
You will probably get booted to your default user directory
F: in my case.
So I changed to C by typing
C:
I then typed
SET PATH=%PATH%;C:\j2sdk1.4.2_12\bin
Which basically appends the Java SDK bin directory to the end
of the PATH environment variable. Note there are no spaces other
than the one between SET and PATH
so now if I type
javac
I get some thing back explaining the syntax as javac on its
own doesn't do much.
Now unfortunately when you compile java files, if they use
other java files you have to provide a classpath that javac can
search to find anything it might need. Like the PATH environment
varibale CLASSPATH is an enviroment variable. I set mine up like
this based on the posting on Rick Roots blog.
SET
CLASSPATH=C:\CFusionMX7\lib\cfusion.jar;C:\CFusionMX7\lib\log4j.jar;C:\CFusionMX7\runtime\lib\jrun.jar;C:\CFusionMX7\gateway\lib\examples.jar;C:\j2sdk1.4.2_12\lib\tools.jar
Now this looks odd compared to most path based environment
variables because it has files in it. JAR files are basically like
ZIP archives, they contain lots of other files inside them. By
adding the JAR files like this you get all the things that have
been compiled and zipped up. I know the Java bods amongst you are
screaming that its not zipping but its an analogy I understand and
probably as much as I need to know.
So I have my PATH set and my CLASSPATH set and away we go.
Well not quite so fast.
There's a problem that we will hit later. I'm going to skip
round all the things that don't work and explain what does work and
what you need to watch out for.
When you register your new gateway type in the Coldfusion
administrator. You have to fill in several fields.
The problem lies in the Java Class field. I spent several
hours copying files into directories, restarting the Coldfusion
service and then trying to get it to pick up my new socket. And all
I got was an error message saying
Unable to find or load Gateway class <whatever class you
think you are using>
Now having Read Rick Roots blog posting I realised I had to
change a few other bits of my SilentSocketGateway.java file
First Off right at the top I had to change the package to
package examples.silentsocket;
I then had to find the class declaration and constructor
functions and change those to be a new class name. Basically
changing SocketGateway to SilentSocketGateway.
so
/**
* Socket gateway.
* <p/>
* This gateway listens on a socket and passes the strings
read to the target CFC.
*
* @author Jim Schley
*/
public class SocketGateway implements Gateway
became
/**
* Socket gateway.
* <p/>
* This gateway listens on a socket and passes the strings
read to the target CFC.
*
* @author Jim Schley
*/
public class SilentSocketGateway implements Gateway
and
/**
* constructor with config file
*/
public SocketGateway(String id, String configpath)
became
/**
* constructor with config file
*/
public SilentSocketGateway(String id, String configpath)
Now Coldfusion doesn't want a java file it doesn't even want
a compiled class file. It wants a JAR file which as I mentioned is
like a zip of a set of files.
The problem that you tend to get is that the JAR needs to now
about the package path prefix and have the packaged files inside it
stored with the right names.
Now I don't understand java packages in any meaningful way
but I did get the always remember package = path message from
several bits of docs on the web.
I also got the whole java files to class files to jar files
thing into a real mess a couple of times. So to make my life easy I
created a classes folder right next to examples folder in
C:\CFusionMX7\gateway\src directory
I then compiled my java files to class files like this
Javac -d classes
examples\silentsocket\SilentSocketGateway.java
I ran this command while in the C:\CfusionMX7\gateways\src
directory as that means the path I am compiling is the same as the
package identifier I altered in the SilentSocketGateway.java file.
So at my command line I typed
CD C:
CD CfusionMX7
CD gateway
CD src
to make sure I was in the right directory when I ran the
javac command.
This creates a set of folders in the
C:\CfusionMX7\gateway\src\classes directory that reflect the
package structure.
I ended up with the files shown, quite where the other 3
turned up from I don't know. I am guessing they are supporting
classes.
So now to compile the JAR file.
In order for the jar file to know about the package path you
need to compile it form the right place. To be safe I included my
own manifest file. Well I tried it about 15 times without one and
it didn't work so I eventually resrted to using a manifest file
I created a file called manifest.txt in the
C:\CfusionMX7\gateway\src\classes directory
It's content was this
Main-Class: examples/silentsocket/SilentSocketGateway
Its very important to make sure you have a return after the
Main-Class line otherwise it doesn't work.
I changed into the classes directory using
CD classes
And then built the jar file with this command
jar -cfvm SilentSocketGateway.jar manifest.txt
examples/silentsocket/*.class
Notice that the path to the class files is once again the
same as the package path, that's why we are doing this form the
C:\CfusionMX7\gateway\src\classes directory
You should get some feedback about what it is adding, the V
switch stands for verbose.
And that will give you a SilentSocketGateway.jar file in the
C:\CfusionMX7\gateway\src\classes directory.
Stop Coldfusion by stopping the Coldfusion MX 7 Application
Server service.
Copy the SilentSocketGateway.jar file to the
C:\CfusionMX7\gateway\lib directory.
Restart Coldfusion by starting the Coldfusion MX 7
Application Server service.
You have to start and stop the service as it only picks up
the jar files in the C:\CfusionMX7\gateway\lib directory when the
server starts up.
Now you can login to the Coldfusion Admin and add your
gateway type
I set my Java Class to be
examples.silentsocket.SilentSocketGateway made up of the package
element form the SilentSocketGateway.java file and the name of the
actual class.
This seems to work.
Missing out the manifest file, compiling either the JAR file
or the class files from any directory where the path to either the
SilentSocketGateway.java or SilentSocketGateway.class files is not
examples/silentsocket delivers a working class or jar file, but
Coldfusion will refuse the Java Class when you try and add the new
type with the message.
Unable to find or load Gateway class <whatever class you
think you are using>
Lot of credit to Rick Root who did all the hard legwork on
this long before I stuck my nose in.