In this we'll provide a quick tour showing how to develop a simple "Hello World!" application using Smalltalk/X and Java. You will need to properly install following:
Smalltalk/X jv-branch. Strictly speaking, this is not necessary and you may use eXept's Smalltalk/X, however, at the time of writing this document, eXept's Smalltalk/X does not come with up-to date STX:LIBJAVA, Mercurial support and other tweaks.
JDK 6 or 7. We recommend using OpenJDK 7 on Linux and Zulu 7 on Windows[1].
Apache Ant. An Apache Ant is used to batch-compile Java sources.
Mercurial. We'll use Mercurial as source code management for the "Hello World!" project.
This simple application will consist of two classes:
A Java class
that will actually print a greeting to standard output
(when run as standalone application from console) or to Transcript
(when executed within a Smalltalk/X IDE, i.e., from
workspace).jv.demos.helloworld_1.core.HelloWorld
A Smalltalk class
that will serve as an entry point when application is run
standalone. This one will initialize STX:LIBJAVA (as it's not
initialized by default) and fire the Java code.HelloWorldStartup
We'll package both classes together into a single Smalltalk/X package named jv:demos/helloworld_1.
Before we start, we have to initialize STX:LIBJAVA. For details, refer to Section 1.3, “Initializing Java”, for now, just execute in workspace:
JavaVM boot.
Once the STX:LIBJAVA is booted, create a Java class. In a class browser, select
→ → . In the browser's code pane, a template of Java class definition appears. In our case, the new class's source code may look like:Line 1: A Java package to which the class belongs. It's name could have any value, but we strongly recommend to use a Smalltalk/X package name as prefix for Java package. It makes the code easier to understand.
Line 7: An annotation which actually tells the Smalltalk/X IDE to which Smalltalk/X package the class belongs to. WIthout this annotation, Smalltalk/X IDE would not know so when later on you commit the package from the browser, the Java class will not be commited - which is not what you want!
Once you accept the code, the Java class is compiled and loaded into a running system. Now you should be able to use it from a workspace. Open one and evaluate:
helloworld := JAVA jv demos helloworld_1 core HelloWorld new. helloworld greet.
The first line instantiates the
class from Smalltalk. You may alternatively instantiate it as
follows:HelloWorld
helloworld := (Java classForName:'jv. demos.helloworld_1.core.HelloWorld') new
.
The second line invokes the
method. You may also invoke the greet()
method as simply as:greet(String)
helloworld greet: 'Haya'
.
Now let's define an application startup class:
StandaloneStartup subclass:#HelloWorldStartup instanceVariableNames:'' classVariableNames:'' poolDictionaries:'' category:'Hello World'
And it's
method - this is the application entry point:#main:
main:argv | helloworld | JavaVM booted ifFalse:[ JavaVM boot. ]. helloworld := JAVA jv demos helloworld_1 core HelloWorld new. helloworld greet. Smalltalk isStandAloneApp ifTrue:[ Smalltalk exit: 0 ].
First, the STX:LIBJAVA has to be initialized. We do it
conditionally only if it's not already. Strictly speaking, this is
not necessary as when a standalone application starts., STX:LIBJAVA
is not initialized, however, doing so allows to test the
method from running IDE.#main:
Second, load the Java class
and invoke its jv.demos.helloworld_1.core.HelloWorld
method.greet()
Third, exit the application. We do it conditionally for the
very same reason - you don't want your Smalltalk IDE to terminate
when testing the
method.#main:
Don't forget to move class
to package jv:demos/helloworld_1 (menu
→ → ).HelloWorldStartup
The initialal code has been developed so now it's time to commit
it to Mercurial repository. If you're not familiar with Mercurial under
Smalltalk/X, you may want to read stx:libscm
User Guide. In the following text, let's assume the Mercurial
repository for the package is located at
/home/user/SmalltalkXProjects/jv/demos/helloworld_1
(or C:\Users\user\SmalltalkXProjects\jv\demos\helloworld_1 on
Windows
)
To commit the package, switch browser to package mode (menu
→ ) and commit (menu → → ).If the menu item (default)" then something is wrong with the Mercurial setup - check stx:libscm User Guide.
does not show the text "Once the commit dialog appears, fill in the commit message and click to
button.Now the code has been commited to the repository. Let's check it from command line:
$ cd /home/user/SmalltalkXProjects/jv/demos/helloworld_1
$ hg log
changeset: 0:2fc9b3286e10
tag: tip
user: Jan Vrany <jan.vrany@fit.cvut.cz>
date: Sun Jun 14 08:14:54 2015 +0100
summary: First shot on a cool "Hello World!" app
$
Before loading the package into freshly started Smalltalk/X IDE you have to manually update Mercurial working copy to desired revision. When a package is commited from Smalltalk/X, the working copy in Smalltalk/X package path is not updated to the commited revision[2]. So you have to update the working copy by hand:
$ cd /home/user/SmalltalkXProjects/jv/demos/helloworld_1
$ hg up
17 files updated, 0 files merged, 0 files removed, 0 files unresolved
$
Now the working copy should be updated to just-commited revision. To load the package back into freshly started Smalltalk/X IDE, load the package as usual:
Smalltalk loadPackage: 'jv:demos/helloworld_1'.
If there's no error while loading (there should not be), you may want to try whether it works as expected. Evaluate:
HelloWorldStartup main
You should see text "Hello world!" in Transcript window. You
should be able to see
class in a system browser window. Now you can change classes
further and once done with it, commit and load it back using the same
process. jv.demos.helloworld_1.core.HelloWorld
Adding Java libraries (.jar) into a Smalltalk
package. In short, you have to create
ivy.xml
file for the Apache Ivydependency
manager. You may take a file from STX:LIBJAVA and modify it to fit
your needs: https://bitbucket.org/janvrany/stx-libjava/src/tip/libs/java/ivy.xml?at=default
Packaging Smalltalk/X application with Java code. The RuntimePackager has not yet been fixed to support Java code.
[2] The main reason is that for binary-compiled classes the sources are not loaded in the memory but loaded from the .st files found in package path on demand. A method contains only offset into this file. Of the file is changed the offset changes and therefore the source shown in the browser will be wrong. To take safe side, stx:libscm (Mercurial) never updates the working copy. This may change in a future.