The speaker presents a Java application that behaves like a dedicated web server and provides Web services. It runs as a standalone network daemon and only calls system and network services that are directly executed by the JVM. No other software is necessary. The URL path referenced by the clients is not referring to files. Instead it is calling other middleware services and serves as a Web service gateway. The application only requires TCP/IP and Java library programming. Because it behaves as a web server, the browser can be any client capable of interfacing with the standard HTTP protocol.
Learn about Java network programming, specifically about security, reliability, supportability, monitoring, browser cache disabling, kit building, starting the Java server process, troubleshooting and monitoring, implementing on different operating systems and platforms, and integrating with other services. Debugging server processes is difficult because there is no direct user interface. Every interaction goes via network sockets, or process signals. Remotely control the server by using the HTTP protocol, enable and disable logging, tracing, and debugging info.
2. Introduction
• A Java application behaving as a web server
• Java & the HTTP protocol is the base
• and IP TCP + UDP programming
• KISS – Keep it simple, but fully functional
• Virtual file system
– Not about Applets, Servlets or JSP
– Not about Jakarta or Tomcat
– No SOAP, no BPEL, no WSDL
3. Why this Project?
• Interoperability of networked clients & servers
• Using Open standards
• HTTP protocol
• Network socket programming (the network is the system)
• Interfacing with middleware (building blocks)
• Any client supporting the HTTP protocol
• Reliable and performance
• 24/7 daemon written in Java
4. Why Java?
• Using standard Java
• Extensible
• Can run on any platform – CORE (code once run everywhere)
• Easy testing
• Easy implementation (distribute byte code)
• Can easily interface with other Java classes
• Use with any backend supporting Java
• Stable, resilient & very good exception handling
• Well documented, tools available
• Modern language – many programmers available
6. Useful? Let me know!
• Home use
• Enterprise use
• You manage everything
• No dependencies with other packages
• It is free, no licenses
• Just invest your own few mandays
• Download the template!
7. The Basic Algorithm
• Initialise the program
• Verify that it runs on one of the registered servers
• Verify the command parameters, overruling default parameters
• Open the log file if requested
• Create the main server listening socket
• Perform the main server loop (endless)
– Listen to the network port and wait for the next client request
– Get the client identification
– Check access authorisation
– Get the client capabilities
– Get the client input parameters
– Parse input parameters
– Validate input parameters
– Perform a server transaction
– Convert the status and results to the client capabilities
– Log the request and the results in the error log
– Return status and results to the client program
– Close the client network connection
A daemon
never dies
8. Program Header
package webtalk;
import java.io.*;
import java.net.*;
import java.util.*;
public class WebTalk {
// Creates a new instance of WebTalk
public WebTalk() {
}
// main program
}
9. Program initialization (1)
private static int tcpPort = 2006; // P1 = listen port: 2006
private static String logDirName = "/tmp";
private static FileOutputStream logFile; // P3 = logging mode: log,sms
private static PrintWriter log = null;
public static void main(String[] args) {
String crlfStr = System.getProperty("line.separator");
String runModeDefault = "normal"; // P2 = run mode: normal
if (crlfStr.equals("rn")) logDirName = "c:temp";
if (args.length >= 1 && !args[0].equals("")) tcpPort = Integer.parseInt(args[0]); // P1: listen port
logFileName = "webtalk-" + tcpPort + ".log";
if (args.length < 3 || args[2].indexOf("nolog") < 0) try { // P3: Open the log file at startup
logFile = new FileOutputStream(new File(logDirName, logFileName), true);
log = new PrintWriter (logFile, true);
} catch (FileNotFoundException e) {
writeLog(e.toString()); // But we continue processing, since not fatal
}
if (args.length >= 2 && !args[1].equals("")) runModeDefault = args[1]; // P2: Set trace mode
if (!runModeDefault.equals("normal")) writeLog("Enable " + runModeDefault);
}
First
implemented in
2006
10. Program initialization (2)
// P3: Open the log file at startup
if (args.length >= 3 && args[2].indexOf("log") >= 0) try {
logFile = new FileOutputStream(new File(logDirName,
logFileName), true);
log = new PrintWriter (logFile, true);
} catch (FileNotFoundException e) {
writeLog(e.toString());
// But we continue processing, since not fatal
}
default
nolog
12. Open main Server Socket
try {
server = new ServerSocket(tcpPort);
} catch (IOException e) {
sendPanic(e.toString());
System.exit(1);
}
private final static String versionString =
"WebTalk/20081013 (Java/HTTP)";
sendPanic("Starting " + versionString);
Server up
and running
13. Waiting the next Client
while (true) {
try {
client = server.accept();
} catch (IOException e) {
sendPanic(e.toString());
System.exit(4);
}
remoteAddress = client.getRemoteSocketAddress().toString();
remoteHost = remoteAddress.substring(1, remoteAddress.indexOf(':', 1));
try{
in = new BufferedReader(
new InputStreamReader(client.getInputStream(), webCharset));
out = new PrintStream(client.getOutputStream(), false, webCharset);
} catch (IOException e) {
sendPanic(e.toString());
System.exit(5);
}
// main processing logic here
}
A daemon
never dies
14. Client Access Control
private final static int MAXIP = 50;
private static int clientCount[] = new int
[1+MAXIP];
private static String allowAddress[] = new
String [1+MAXIP];
…
allowAddress[14] =
nslookup("client1.mshome.net");
allowAddress[15] = "192.168.210.34";
…
if (!allowRemoteHost (remoteHost)) {
sendPanic("Reject host: " +
remoteHost);
}
static boolean allowRemoteHost (String
remoteAddress) {
boolean allowIP;
allowIP = false;
for (int i = 1; i < allowAddress.length; i++)
{
if
(remoteAddress.equals(allowAddress[i])) {
allowIP = true;
clientCount[i]++;
break;
}
}
return allowIP;
}
15. Getting Browser Input
String webTalkIn;
webTalkIn = "n-- Start request";
// Get the client request
while (webTalkIn != null && !webTalkIn.equals("")) {
// Here comes the parsing of the browser request
// Get the next HTTP header until empty line encountered
webTalkIn = in.readLine();
}
TCP does
not have
EOF
16. Parsing the Client URL
String webRequest[]; // GET /urlPath/...?webParam=value&... HTTP/1.1
String mainPath[];
String urlPath[];
String webParam[];
String paramPair[];
writeLog(remoteHost + " " + gmTime + " " + webTalkIn);
webRequest = webTalkIn.split(" ");
mainPath = webRequest[1].split("[?]", 2);
urlPath = mainPath[0].split("/");
webParam = mainPath[1].split("&");
/* Here we should map the key/value pairs into the application logic */
for (int c = 0; c < webParam.length; c++) {
paramPair = webParam[c].split("=", 2);
paramPair[0] = paramPair[0].toUpperCase();
//System.out.println(paramPair[0]);
//System.out.println(paramPair[1]);
}
18. Identifying the Browser
/* set default userAgent */
if (userAgent == unkownUserAgent
&& webRequest.length >= 2
&& webRequest[0].equals("User-Agent:")) {
if (runMode.equals("trace")) writeLog(webTalkIn);
if (webRequest[1].startsWith("Mozilla")) {
// Firefox, Internet Explorer
userAgent = mozillaUserAgent;
} else {
// Lynx, Opera
userAgent = otherUserAgent;
}
}
19. The main Server Logic
Some examples we have implemented with success in production are:
• Validating Web forms by calling WebTalk via TCP socket
programming
• .Net calling the WebTalk server to validate customer orders
• Validating customer orders via a DTMF and a text to speech
system
• Oracle PL/SQL calling the WebTalk server to validate customer
orders via the UTL_HTTP and UTL_TCP package [6]
• Storing database transactions via HTTP protocol (avoid locking)
• Apache Embedded Perl calling WebTalk for order validation
21. GMT Time in HTTP Format
01234567890123456789012345678
Fri Nov 03 13:51:56 GMT 2006 standard GMT format (gmTime)
Fri, 03 Nov 2006 14:51:56 GMT internet GMT format (httpTime)
private static String gmTime;
private static String httpTime;
Date now;
TimeZone tz = TimeZone.getTimeZone("GMT");
tz.setDefault(tz);
now = new java.util.Date();
gmTime = now.toString();
httpTime = gmTime.substring(0,3) + ','
+ gmTime.substring(7,10)
+ gmTime.substring(3,7)
+ gmTime.substring(23,28)
+ gmTime.substring(10,23);
HTTP =
WWW thus
GMT time
22. Disabling Client Browser Cache
Our application is data driven
We must ensure that browsers, or proxies never
cache requests.
Therefore we generate the following headers:
Expires: -1
Cache-Control: no-cache, no-store, max-age=0, must-
revalidate
Pragma: no-cache
23. Close the Door
try {
in.close();
out.close();
client.close();
} catch (IOException e) {
sendPanic(e.toString());
System.exit(6);
}
• One client at a time
• Avoid locking using
single process database
inserts
• Let the TCP stack buffer
incoming requests
• Latent DoS problem
(if connection not properly closed)
24. Client Examples in practice
• Normal clients can be browsers like Firefox [8], Opera [8], or Internet
Explorer:
http://servername:2006/hub/2186/ivr?p1=1234&p2=5678
• With telnet:
telnet servername 2006
GET /hub/2186/ivr?p1=1234&p2=5678
(enter)
• With Lynx [8]:
lynx "http://servername:2006/hub/2186/ivr?p1=1234&p2=5678"
• With netcat:
echo "GET /hub/2186/ivr?p1=1234&p2=5678n" |nc servername 2006
25. Other Clients
• Perl
• PHP
• Unix Socket programs
• .Net clients
• Database systems like Oracle [6]
• Telecom servers like IVR
Any program
capable of
talking HTTP
26. Example: Perl
use IO::Socket::INET;
$Server = "servername:2006";
my $sock = IO::Socket::INET->new(PeerAddr => $Server, Proto => 'tcp');
$webStat = "";
if ($sock) {
$sock->write("GET /statusnn");
$sock->recv($webStat, 2000);
close($sock);
}
print "$webStatn";
27. Example: Oracle stored Procedure
CREATE FUNCTION web_request (
request in string)
return string is
c utl_tcp.connection; len PLS_INTEGER;
result string(2000);
BEGIN
c := utl_tcp.open_connection ('servername',
2006);
len := utl_tcp.write_line(c, 'GET ' || request);
len := utl_tcp.write_line(c);
result := utl_tcp.get_line(c, TRUE);
utl_tcp.close_connection(c);
return result;
END;
select
web_request(‘/status’)
from dual;
28. Caveat Firefox and Opera
[server loop]
if (urlPath.length >= 2 &&
urlPath[1].equals("favicon.ico")) {
runMode = "ignore";
}
[generating output]
if (runMode.equals("ignore")) {
writeBody(clientResult);
}
29. Backend Systems
• Oracle with permanent connection
• MySQL database gateway
• Middleware
• Other SOA systems
30. Server Management – Starting the Server
• On Unix systems:
su - apache -c "java -jar /html/java/bin/webtalk.jar 2006 normal log,sms
> /dev/null 2> /dev/null &"
• On Windows platforms you can start the server from a scheduled tasks (at system startup)
java -jar C:htmljavabinwebtalk.jar 2006 trace > nul 2> nul
• General format of startup command:
java -jar webtalk.jar [port] [runmode] [log,sms] [> nul] [2> nul]
Parameters:
port: TCP port number (default 2006; you could use 2005 for testing)
runmode: debug | test | trace | quiet | disable | enable | normal (default)
log: "log" to trigger the logging to disk, with nolog logging is disabled
sms: "nosms" to disable sending SMS messages
31. Stopping the Server
[Unix]
• ps –ef |grep webtalk
• kill $pid
[Windows]
• tasklist /fi “imagename eq java.exe”
• taskkill /pid ProcessID
Killing the
daemon
32. Temporarily Disable – Panic Button
• Uncouple the system to avoid downstream catastrophes
http://servername:2006/disable
http://servername:2006/enable
Internally the following code gets executed:
if (urlPath.length >= 2
&& (urlPath[1].equals("disable")
|| urlPath[1].equals("enable") ) ) {
runModeDefault = urlPath[1];
clientResult = "Server: " + runModeDefault;
sendPanic(clientResult);
}
39. Usage Statistics
http://servername:2006/counters
Usage counters per IP address since Mon Jun 04 20:56:39 GMT 2007:
192.168.86.109 2110 client1.mshome.net
192.168.219.113 1198 client2.mshome.net
192.168.112.50 916 client3.mshome.net
• This is handled by the following code:
if (urlPath.length >= 2 && urlPath[1].equals("counters")) {
clientResult = "Usage counters per client since " + resetTime + ":n";
for (int i = 1; i < allowAddress.length; i++)
if (!allowAddress[i].equals(""))
clientResult += "n" + allowAddress[i]
+ "t" + clientCount[i]
+ "t" + rnslookup (allowAddress[i]);
41. Building the Application
• java -version
java version "1.4.2"
Java(TM) 2 Runtime Environment, Standard Edition
Fast VM (build 1.4.2-6, native threads, mixed mode, 01/09/2007-23:17)
• Store the source code in a subdirectory, and
compile with javac.
javac webtalk/WebTalk.java
mkdir webtalk/RCS
ci –l webtalk/WebTalk.java
42. Run Interactively
• [Unix]
export CLASSPATH=lib1.jar:lib2.jar:.
• [Windows]
set CLASSPATH=lib1.jar;lib2.jar;.
• To start the program interactively, immediately after
compiling:
java webtalk/WebTalk 2005 debug nolog,nosms
43. Build the JAR File
• The manifest file can contain a list of all other required jar files and
the name of the main module to run. If your application is
complex, multiple jar files will be needed.
jar -cv0mf webtalk.jar webtalk/manifest.mf webtalk/*.class
vi webtalk/manifest.mf
Manifest-Version: 1.0
Created-By: 1.3.0_05 (Sun Microsystems Inc.)
Class-Path: lib1.jar lib2.jar
Main-Class: webtalk/WebTalk
44. Simulate a Server (1)
vi netcat.txt
HTTP/1.1 200 OK
Date: Tue, 29 May 2007 11:47:08 GMT
Server: WebTalk/20070528 (Java/HTTP)
Last-Modified: Tue, 29 May 2007 11:47:08 GMT
Expires: -1
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Content-Length: 18
Connection: close
Content-Type: text/html
P1:0003|P2:42108
Coding,
compiling,
testing takes a
lot of time
45. Simulate a Server (2)
while true ;do nc –lp 2005 < netcat.txt ;done
lynx –dump http://localhost:2005/test
lynx –source http://localhost:2005/test
nc –p 2005 localhost
telnet localhost 2005
46. Error Handling
Daemon process!Alarm notification
Allow for easy supportError logging
The program stopsFatal errors
Logged, status to clientUnexpected errors
Returned to client
application, not logged
Expected errors
How to handleError Type
47. General Exception Handling
try {
// put main program logic here
} catch (Exception e) {
e.printStackTrace ();
sendPanic(e.toString()); // could also use e.getMessage()
System.exit(7);
} finally {
sendPanic("Server closing down");
}
50. Enable Quiet Mode
• To set quiet mode
(when you would have too many transactions)
http://servername:2006/quiet
if (urlPath.length >= 2 && urlPath[1].equals("quiet")) {
runModeDefault = urlPath[1];
clientResult = "Enable quiet mode";
}
53. UDP to TCP Relay Server (1)
import java.io.*;
import java.net.*;
public class RelaySmsUdp {
public static void main (String args[]) {
DatagramSocket smsSocket;
DatagramPacket smsPacket;
InetAddress clientAddress;
String clientHost;
String panicString;
Socket outSocket;
PrintWriter out;
byte sms[] = new byte[165]; // byte array
String panicDest;
String smsHost;
panicDest = "0123456789"; // your Mobile alarm number
if (args.length >= 1 && !args[0].equals("")) panicDest = args[0];
smsHost = "sms-tcp-gateway";
if (args.length >= 2 && !args[1].equals("")) smsHost = args[1];
54. try {
smsSocket = new DatagramSocket(535); // listen to port
while (true) try {
smsPacket = new DatagramPacket (sms, sms.length);
smsSocket.receive (smsPacket);
clientAddress = smsPacket.getAddress();
clientHost = clientAddress.getHostAddress();
panicString = new String (smsPacket.getData(), 0, smsPacket.getLength());
if (!panicString.startsWith("0")) panicString = panicDest + " " + panicString;
// prefix with Mobile number if needed
if (clientHost.startsWith("192.168.")) { // Filter non-registered IP
addresses
outSocket = new Socket (smsHost, 535);
out = new PrintWriter(outSocket.getOutputStream());
if (panicString.length() > 165)
panicString = panicString.substring(0, 165);
out.println (panicString);
out.close();
outSocket.close();
}
} catch (UnknownHostException e) {
writeLog(e.toString());
} catch (IOException e) {
writeLog(e.toString());
}
} catch (SocketException e) {
writeLog(e.toString());
}
Relay to TCP
for message
transmission
55. Disable SMS at Startup
• Can be very handy while developing
private static InetAddress smsRelayAddressDefault;
private static InetAddress smsRelayAddress;
try {
smsRelayAddressDefault = InetAddress.getByName("sms-udp-gateway");
} catch (Exception e) {
smsRelayAddressDefault = null;
}
smsRelayAddress = smsRelayAddressDefault;
if (args.length >= 3 && args[2].indexOf("nosms") >= 0)
smsRelayAddress = null;
56. Disable or Enable SMS at runtime
lynx -dump http://servername:2006/[no]sms
• The following code gets executed:
if (urlPath.length >= 2 && urlPath[1].equals("sms")) {
smsRelayAddress = smsRelayAddressDefault;
clientResult = "Enable sms notification";
sendPanic(clientResult);
}
else if (urlPath.length >= 2 && urlPath[1].equals("nosms")) {
smsRelayAddress = null;
clientResult = "Disable sms notification";
sendPanic(clientResult);
}
If you are
drown with
alarms
57. Supported Server Platforms
Java virtually runs on all platforms:
– You only have to distribute the byte code in a Jar file!
• Any Intel Linux
• Any Intel Windows XP or Vista desktop
• Alpha Tru64 UNIX V5.1B-3 with Java 1.4.2-7, see [11]
• Itanium
• Windows server 2003 with Java 1.5.0_07
58. Implemented Standards
• DNS
• HTTP, see [2]
• Internet date & time
format
• Java, see [3] [4] [5]
• NFS during development
• NTP
• TCP/IP
• UDP for error relay
• Web Cache control
• ZIP for jar file
manipulation
59. What I have learned
• Think in objects
• Keep it simple (divide and conquer)
• Client /server programming is fun
... debugging and fault finding even more
• It boosts the team spirit
• It stimulates your own brains and
creativity
• Java (network) programming is not
really exotic, nor complicated
• Web applications must disable proxy
and browser cache
• TCP sockets do not have an end-of-
file...
– a server socket cannot know when the
client sends the last packet
– this is why a final empty line has been
built into the HTTP and SMTP protocol
• Java initialises all variables to 0, "", or
null
• Java always start with element 0
• In Java you do not use pointers and
linked lists to create dynamic data
structures
• Sparse matrices are natural in Java
• Error handling and planning for the
unforeseen is the most important –
try / catch should be a habit
• The HTTP protocol terminates every
line by CRLF. Originally I terminated
HTTP server output only by LF using
println. None of the Unix systems did
complain. .Net servers replied with an
error “The server committed a
protocol violation”.
• Keep the history of your changes. Use
e.g. RCS, Revision Control System.
60. Design Principles
• Separate code and data
• Flexible data structures
• Fully table & data driven
• Keep the code simple
• Code only once (no duplicate
instructions)
• Do normal things straight
• Use industry standards
• Use as much as possible standard
system functions
• Do care about and be
conservative with system
resources
• Give the power to the users
• Be flexible, and extensible
• Be future proof
• Be generous on what you accept,
be strict on what you return
• Do the unforeseen via exception
handling; be robust
• Be fool proof
• Avoid catastrophes at all times
• Use what you know
• Have maximum security and
access control
• Allow for logging, tracing, and
debugging
• Care about supportability
• Be platform independent
• Write a complete documentation
61. Future Extensions and Migration
• Advanced Java debugging
• Build and use appliances
• Application setup via config file
instead of hardcoded
• DNS caching
• IPv6, Internet protocol V6
• Java runtime optimisation
(tuning, memory usage)
• kill –HUP, to change debug level,
or restart the server
• Legacy applications
• Load balancing
• Multithreaded server
• UDP monitoring
• NTLM, Active Directory user
authentication
• POST or other HTTP protocols
• SIF, Service Invocation
Framework = SOA services for
Java
• Timeout, drop a bad behaving
client (currently we suffer from a
DoS problem)
• SNMP monitoring
• SOA, Service Oriented
Architecture
• System parameters
• XML, Input / Output in XML
format
62. References
[1] Full program source and additional material: http://www.hp-interex.be/pub/project/webtalk
[2] The HTTP protocol and related standards: http://www.w3.org
[3] Documentation and kits for Java: http://www.sun.com
[4] Java technical documentation: http://java.sun.com/j2se/1.4.2/docs
[5] Java search page: http://java.sun.com/j2se/1.4.2/search.html
[6] Oracle UTL_HTTP:
http://www.oracle.com/technology/sample_code/tech/pl_sql/htdocs/x/Utl_Http_Package_Enhan
cements/Cr_Using_Utl_Http.htm
[7] Iptables: http://www.netfilter.org
[8] Browsers:
The Lynx browser: http://lynx.browser.org
Firefox: http://www.firefox.com
Opera: http://www.opera.com
[9] Perl libraries: http://search.cpan.org
[10] NetBeans: http://www.netbeans.org
[11] HP Java implementations: http://www.hp.com/java
[12] Bruce Eckel, Thinking in Java, The definitive introduction to object-oriented programming in
the language of the World Wide Web, Fourth Edition, ISBN 0-13-187248-6, 2006, Prentice Hall,
Pearson Education, Code & Supplements at http://www.mindview.net
63. Thanks
• My colleague Danny De Thaye to encourage me in my
endeavors
• Connect Management for accepting my lecture
• To you, the audience
geert.van.pamel@belgacom.net
http://www.hp-interex.be/wiki/index.php/User:Geertivp
65. Abstract
• The speaker presents a Java application that behaves like a dedicated web server
and provides Web services. It runs as a standalone network daemon and only calls
system and network services that are directly executed by the JVM. No other
software is necessary. The URL path referenced by the clients is not referring to
files. Instead it is calling other middleware services and serves as a Web service
gateway. The application only requires TCP/IP and Java library programming.
Because it behaves as a web server, the browser can be any client capable of
interfacing with the standard HTTP protocol.
• Learn about Java network programming, specifically about security, reliability,
supportability, monitoring, browser cache disabling, kit building, starting the Java
server process, troubleshooting and monitoring, implementing on different
operating systems and platforms, and integrating with other services. Debugging
server processes is difficult because there is no direct user interface. Every
interaction goes via network sockets, or process signals. Remotely control the
server by using the HTTP protocol, enable and disable logging, tracing, and
debugging info.
66. About the Author
• The author works at Belgacom since 1997 in the Customer division as an
ICT Project Manager.
• He is Chairman of HP-Interex Belux since 2008.
• He is Board member of HP-Interex Belux since 2002. Member of DECUS
since 1984, and CUO since 1998.
• In his previous life he worked as Project manager at Digital Equipment
Corporation (DEC) [company merged with Compaq in 1998 and with HP,
Hewlett Packard in 2002].
• His early activities in the world of IT were biometrical statistics, teaching
computer courses, real time car manufacturing automation, and medical
image processing using nuclear isotopes computer tomography.
• He is an engineer in Agriculture and Applied Biological Sciences, and
postgraduate in Computer Science. He is eager to implement technology
as a business advantage.
67. Useful Utilities
• Any web browser [8] To test the server (Firefox, Internet Explorer, Opera, lynx)
• crontab To reset the daily log files, to monitor
• Google For help with Java, use e.g. Google: Java ServerSocket
• host To lookup the IP address of a machine
• init To start the Web Service
• jar Java archive builder
• java Java runtime interpreter
• javac Java Compiler
• nc, netcat To test, debug, or simulate
• NetBeans [10] Java IDE Integrated Development Environment Unix & Windows
• NFS The server is developed, build & tested cross-platform
• nmblookup, nbtstat To lookup the name of a Windows client, if not registered in DNS
• NTP, ntpq To synchronise system time
• Perl [9] Practical Extraction and Reporting Language
• ps, grep, kill To monitor or change run status
• telnet To monitor and test special requests (does not work in batch)
• vi Terminal based editor - on linux, you might have colours
• zip, Winzip To verify (or update) the contents of jar files.
68. Technical Terms
• API Application Programming Interface
• CRLF Carriage Return and Line Feed
• GMT Greenwich Mean Time, almost the same as UTS (Universal Time Coordinated)
• HW Hardware
• IVR Interactive Voice Response
• Jar Java archive
• JDK Java Development Kit
• JRE Java Runtime Environment
• JSP Java Server Pages
• JVM Java Virtual Machine
• OS Operating System
• Platform A combination of hardware and software
• SMS Mobile text message (do not confuse with Microsoft System Management Server)
• SW Software (operating system and layered products)
• Unix Any type of Unix, or Linux OS, in general
• UNIX™ UNIX Trademark