Using the jxAPI With Java
This page is about the legacy SOAP-based jxAPI that is no longer updated or recommended for use in new projects. The documentation in this section may be outdated or inaccurate, and is provided for reference purposes only.
Journyx recommends using the REST-based API for new projects in most cases. However, at the current time, there are certain object types that are not available through the REST API.
Requirements
To use the jxAPI, you will need:
- A Journyx installation
- JDK v1.3 or newer
- Apache Axis for Java (http://ws.apache.org/axis/)
- A JAXP 1.1 compatible XML parser (such as Xerces-J, available from http://xml.apache.org/)
Since the jxAPI is for clients only, you do not need an application server or servlet engine for Axis, and you may safely ignore the parts of its installation document that cover server deployment. For jxAPI development, you simply need to add the Axis jar files to the CLASSPATH when building and running your application.
Other standards-compliant Java SOAP client libraries should work with the jxAPI, but only Apache Axis has been tested.
Activating the jxAPI
Before you can use the jxAPI to communicate with a Journyx server, it must be activated on that server. Log in to the server as an administrator, and check the administration menu for a "jxAPI Preferences" link. Some versions of Journyx that support the jxAPI don't have this link; if it isn't there, visit the following URL, replacing the hostname and port with the proper values for your Journyx server:
http://hostname:port/jtcgi/jxapipref.pyc
Check the "jxAPI Active" checkbox and submit the form. Activating the jxAPI may take a few seconds even on a lightly loaded server, so please be patient. Once the activation is complete, take note of the jxAPI WSDL URL shown on this screen, as you will need it later.
Building WSDL Stubs
The jxAPI is represented in Java by a package of classes, the source code for which you must generate with the Axis WSDL2Java utility. The WSDL2Java utility is included in the Axis libraries, and you can run it from the command line with:
java org.apache.axis.wsdl.WSDL2Java (WSDL URL)
The WSDL2Java utility will produce the source code for a Java package called "jxapi_pkg" in the current directory. Your client applications that use the jxAPI must include this package.
The generated package is specific to the jxAPI version supported by the server, and you do not need to regenerate it unless you want your client to use features supported by a newer version of the jxAPI.
Connecting
The first step in using the jxAPI is to obtain an object that represents a
connection to the server, by instantiating a Jxapi_ServiceLocator
object and
calling its getjxapi
method to create a Jxapi_Port
object. For example:
import jxapi_pkg.*
import java.net.URL
public Jxapi_Port connect(String server) throws Exception {
Jxapi_Service svc = new Jxapi_ServiceLocator();
if (server == "default") {
return svc.getjxapi();
} else {
return svc.getjxapi(new URL("http://"+server+"/jtcgi/jxapi.pyc"))
}
}
(Note that in all code examples in this document, boilerplate such as class definitions will be omitted.)
If you do not provide a parameter to the getjxapi
method, the library will
connect to the server from which you generated the jxapi_pkg
package.
Otherwise, you may provide the URL of the jxAPI SOAP interface of a specific
server, which is usually http://server:port/jtcgi/jxapi.pyc
.
The Jxapi_Port
object is a proxy for the entire jxAPI; calls to its methods
will be translated automatically to jxAPI operations.
Error Handling
Because Java is strongly type checked, attempts to call jxAPI methods with
improper or incomplete arguments will be caught on the client side before the
server is contacted. Most other possible errors will result in an
org.apache.axis.AxisFault
exception being thrown in the client. This single
Java exception may correspond to many different kinds of server-side error, from
bad passwords to data validation errors and more. If your code catches an
AxisFault
exception you can use its methods (getFaultString()
, for example)
to examine the error report provided by the server.
Data Types
In the jxAPI Reference, data types are referred to by generic names such as "string" and "number". These correspond to specific Java types:
- a jxAPI "integer" is a
java.math.BigInteger
- a jxAPI "long" is also a
java.math.BigInteger
- a jxAPI "float" is a
double
- a jxAPI "string" is a
java.lang.String
- a jxAPI "boolean" is a
boolean
- a jxAPI "list" is a Java array
- a jxAPI "record" or "structure" is a Java object
Authentication
Nearly all parts of the jxAPI require authentication, just as using Journyx from the web interface does. Authentication in the jxAPI is session-based; your application "logs in" with a user name and password, and receives a session key which must then be passed back to the server with every method call. For example:
Jxapi_Port port;
String skey;
port = connect("default"); // From previous example
skey = port.login("joe", "joespass", 1);
The third parameter to the login
method determines whether to keep any
existing sessions for this user. If it is 0, all other sessions for the user,
including web logins, will be automatically terminated; if it is 1, they will be
ignored.
With only a few exceptions, every method in the jxAPI takes the session key as a parameter. The jxAPI cannot be used to bypass Journyx's normal security model—most users can access only their own data, and only administrators have free reign.
Your application should always log out each session that it creates, by calling
the logout
method when done:
port.logout(skey);
Records
Almost everything in the Journyx database is stored as records. For example, a week of time entries which appear on a single page in the web user interface may actually correspond to several records, one for each filled grid square. Each entry in the pull-down fields (project, pay type, etc.) is a record, and so is each user.
Records, and other types of structured data used by Journyx, are represented by
Java objects. The jxapi_pkg
that you previously generated from the server's
WSDL includes a Java class for each record type used by the jxAPI. Each of these
classes defines conventional accessor methods for the fields in the record. For
example, if a record has an id
attribute (as most of them do), then the
corresponding Java object will have methods like setId(String x)
and
String getId()
. The jxAPI Reference has a full list of the fields in each type
of record, and their types.
More About Records: Time Entry
Time entries are represented by a single record per grid square. A full row on a user's time sheet corresponds to up to seven records, one per day, each with the project, pay type, bill type, and comment set for that row.
The first step in creating a time record is to create a
TimeRecord
object. Simply calling "new
TimeRecord
()" isn't usually the best way to do
this; the Java constructor creates a completely empty record, and there are
several fields that can be filled in with default values by the server. The
getDefaultTimeRecord
method asks
the server for a fresh time record with default values already filled in.
Finally, after the rest of the record is filled in, the
addFullTimeRecord
method inserts it
into the Journyx database:
TimeRecord trec;
String id;
trec = port.getDefaultTimeRecord(skey);
trec.setHours(6.0);
trec.setComment("test record");
id = port.addFullTimeRecord(skey, trec);
Notice that the session key is passed as the first parameter to both jxAPI
calls. The getDefaultTimeRecord
method implicitly creates a record for the current user, and
addFullTimeRecord
will throw an
exception if the current user doesn't have permission to add this record (if,
for example, the user
field of the record doesn't match).
Also note that addFullTimeRecord
returns an ID. The ID of a record is a unique key generated when the record is
first added to the Journyx database. It can be used later to delete or modify a
record:
trec = port.getTimeRecord(skey, id);
trec.setHours(7.0);
port.modifyTimeRecord(skey, id, trec);
port.removeTimeRecord(skey, id);
Other Record Types: Common Methods
The methods described above in the discussion of time entries have counterparts
for other record types in the jxAPI. For example, there is a
getDefaultExpenseRecord
,
addFullExpenseRecord
,
getExpenseRecord
, and so forth, with
corresponding methods for each of the core types:
TimeRecord
,
ExpenseRecord
, User
, Project
, Code
(Task), Subcode
(Pay Type), Subsubcode
(Bill Type), and Group
.
Project and Code Lists
If you are creating time and expense records, you probably want to fill in the
Project, Task, Pay Type, and Bill Type fields with meaningful values. (The
latter are called code
, subcode
, and subsubcode
in the
TimeRecord
and
ExpenseRecord
objects for historical
reasons.) The jxAPI provides several methods to retrieve all available values
for those fields:
String[] x;
x = port.getProjectList(skey);
x = port.getCodeList(skey);
x = port.getSubcodeList(skey);
x = port.getSubsubcodeList(skey);
In each case, the return value is an array of strings in which each pair of elements is the ID (to put in the corresponding field of a time or expense record) and name of a project, code, subcode, or subsubcode. Since these methods are authenticated, the returned list only includes items available to the current user.
Sheets
A time sheet represents a batch of time entries in a date range. You do not need
to explicitly create time sheets (they exist automatically based on the
timekeeping periods defined by the Journyx administrator) but you should take
them into account when creating time records. To retrieve the current user's
time sheet for a specific date, use the
getTimeSheetIDByDate
method; once you have the ID, you can manipulate it:
String id;
Float hours;
String[] a;
id = port.getTimeSheetIDByDate(skey, '20051001');
hours = port.getTotalHoursInTimeSheet(skey, id);
a = port.getDatesInTimeSheet(skey, id);
a = port.getTimeRecordIDsInSheet(skey, id);
When you add a time record, you should add it to the proper sheet; likewise, when you remove a time record, you should remove it from the sheet:
String trecid, tsid;
TimeRecord trec;
trec = port.getDefaultTimeRecord(skey);
trec.setHours(6.0);
trecid = port.addFullTimeRecord(skey, trec);
tsid = port.getTimeSheetIDByDate(skey, trec.getDate());
port.addTimeRecordToSheet(skey, tsid, trecid);
port.removeTimeRecordFromSheet(skey, tsid, trecid);
port.removeTimeRecord(skey, trecid);
Finally, you might want to submit a time sheet and, later, check its status:
port.submitTimeSheet(skey, tsid);
System.out.println(port.getTimeSheetStatus(skey, tsid));
The jxAPI also contains methods for approving and rejecting sheets, Expense and Mileage sheets, and administering approval templates. For more information on these topics, see the jxAPI Reference.
Other Features
The samples in this document show only a small part of the jxAPI's complete functionality. Most features of Journyx are accessible through the jxAPI now, or will be soon. The jxAPI Reference will contain an up-to-date list of every method and data structure it supports.