Sunday, September 29, 2013

Enabling AutoComplete In ADT

I got the Android Development Toolkit, which includes Eclipse and the SDK for developing Android applications. After having a go at it for a couple of minutes, I noticed that I didn't have any autocomplete. Being a newbie at Android development (no experience with Android development, apart from a few days of Android coding in 2010 or 2011), I really needed the autocomplete to work so I looked for something that could point me the right way. I finally stumbled upon the settings at:
Window > Preferences > Java > Editor > Content Assist > Advanced

I enabled the Java Proposals, Java Type Proposals, and Java Non-Type Proposals, and as soon as I dismissed the dialog box by clicking the Ok button, I was able to use Ctrl+Space for the code autocompletion!

Saturday, September 28, 2013

Python: Subclassing the BaseHTTPRequestHandler

As discussed in my previous post, Python provides the HTTPServer class for listening to HTTP requests and dispatching them to request handlers. To write our own handler, we can create a subclass of BaseHTTPRequestHandler and handle the requests by providing functions named with the 'do_' prefix followed by the HTTP action verb (Eg. do_GET, do_HEAD, do_POST etc). The following is an example that uses this approach to create a web server.

from http.server import HTTPServer
from http.server import BaseHTTPRequestHandler
from http.server import SimpleHTTPRequestHandler

def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):
 server_address = ('', 8000)
 httpd = server_class(server_address, handler_class)
 httpd.serve_forever()

class MyHandlerForHTTP(BaseHTTPRequestHandler):
 def do_GET(self):
  self.send_response(200)
  self.send_header('Content-Type', 'text/plain')
  self.end_headers()
  self.wfile.write(bytes('Hello World\n', 'UTF-8'))
  self.wfile.write(bytes('You have requested '+self.path+'\n', 'UTF-8'))

run(handler_class=MyHandlerForHTTP)

In this example, we created a class named MyHandlerForHTTP that inherits from BaseHTTPRequestHandler and defined the do_GET method within it. The BaseHTTPRequestHandler class provides methods to set the HTTP response status code, output the headers, and write data to the response stream. Note that you do not have to call the close method on the wfile member as the BaseHTTPRequestHandler class implicitly calls the flush method of the wfile member after the execution of the do_* method.

Python HTTP Web Server

Python makes it extremely simple to create a web server. I adapted the run function provided in the Python documentation to create the following example.

from http.server import HTTPServer
from http.server import BaseHTTPRequestHandler
from http.server import SimpleHTTPRequestHandler

def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):
 server_address = ('', 8000)
 httpd = server_class(server_address, handler_class)
 httpd.serve_forever()

run(handler_class=SimpleHTTPRequestHandler)

In the code above, we first import the HTTPServer, BaseHTTPRequestHandler, and SimpleHTTPRequestHandler classes from the http.server module (if you want to know more about modules, look at my slides on Python Modules). We then have a run function that accepts the name of an HTTP server class and an HTTP request handler class as parameters.

The HTTPServer class is used to listen for web requests and dispatch them to request handlers. Request handlers are what we use to figure out what needs to be done and to send a response. The BaseHTTPRequestHandler calls methods with a 'do_' prefix followed by the name of the HTTP action verb (more on that in another post). In the example above, we use a SimpleHTTPRequestHandler that provides the functionality out-of-the-box to serve files from the current directory.

Our example above acts as a glue between the HTTP server and the SimpleHTTPRequestHandler class without doing the actual processing on its own. In another blog post, I will describe how you can create your own request handler class to process requests in Python code.

[Python] TypeError: str does not support buffer interface

When writing data, such as to sockets, you probably see a lot of code that calls a write function and passes in a string like this:
self.wfile.write('Hello World')


This code ran perfectly well in Python 2.x, but not so in Python 3.x. In Python 2.x, strings that contained only ASCII characters could be passed as data but if the strings contained characters that couldn't be represented as ASCII characters, a UnicodeDecodeError would occur.

Python 3.x treats text and binary data as distinct types, and raises a TypeError if you provided text where binary data was expected. In Python 3.x, you have to convert text data to binary data using the bytes function, so expect to rewrite your code to look like the following:
self.wfile.write(bytes('Hello World', 'UTF-8'))

Wednesday, September 25, 2013

SQL Monitoring / Query Analysis with MySQL

I'll keep this post a short one. I wanted to view the queries that are being run against a MySQL database and found the simplest way to do it is to view the queries in the general log file using tail. There are 2 variables: general_log to set the logging ON or OFF, and the general_log_file, which indicates the location of the log file.

The following is dump of my MySQL client output:

mysql> SHOW VARIABLES LIKE "general_log%";
+------------------+----------------------------------+
| Variable_name    | Value                            |
+------------------+----------------------------------+
| general_log      | OFF                              |
| general_log_file | \xampp\mysql\data\reddythink.log |
+------------------+----------------------------------+
2 rows in set (0.00 sec)

mysql> SET GLOBAL general_log = 'ON';
Query OK, 0 rows affected (0.08 sec)

mysql> SET GLOBAL general_log = 'OFF';
Query OK, 0 rows affected (0.04 sec)

Friday, September 20, 2013

Oracle DECODE and CASE expressions

The use of the DECODE function in Oracle is to substitute a value or expression with another. The CASE expressions serve a similar purpose but can be used in a wider variety of scenarios.

Let's say you have a character field in the database and you want to select data from the table and display a more user-friendly value instead of a single character. You can use the DECODE function to specify the column or expression to be checked followed by a pair of values or expressions to be matched with a substitution value, and finally a substitution value to be used if none of the matching values or expressions matched. Here is an example:

A table r5translines containing a column trl_type has the value 'I' for goods issued (sent out), 'RETN' for goods returned (such as when a defective product is returned), and 'RECV' for goods received (such as goods received from a supplier). To display this information in a user-friendly form, the SELECT statement can be writted with a DECODE statement as follows:
SELECT DECODE(trl_type, 'I', 'Issue', 'RETN', 'Return', 'RECD', 'Received', 'Unknown') FROM r5translines;


You can also do this using a CASE expression as follows:
SELECT CASE trl_type WHEN 'I' THEN 'Issue' WHEN 'RETN' THEN 'Return' WHEN 'RECD' THEN 'Received' ELSE 'Unknown' END CASE FROM r5translines;


In another selection of data, let's say you want to display the string 'Incoming' for received or returned goods, and the string 'Outgoing' for goods issued. You can use a CASE expression in a slightly different manner as follows:
SELECT CASE WHEN trl_type IN ('RECD', 'RETN') THEN 'Incoming' ELSE 'Outgoing' END CASE FROM r5translines;

Wednesday, September 18, 2013

Missing tools.jar during deployment

This is just a quick note to suggest a possible solution to the missing tools.jar file when deploying configuration changes in Infor EAM - if you get an error message from the deployment script indicating that the tools.jar file is missing, install a JDK (not a JRE) and set the JAVA_HOME environment variable to point to the path of the JDK directory. Alternatively, you can copy the tools.jar file from a JDK into the java/lib directory in the Infor EAM directory.

Tuesday, September 17, 2013

Infor EAM 10.1.2 Installation

The Infor EAM software and CD keys are available to channel partners, in addition to access to Infor Xtreme, the system for obtaining tech support and looking up the knowledge base. The installer consists of 3 CDs:
(i) Database objects setup (there's a CD for SQL Server and another for Oracle)
(ii) Application setup
(iii) Advanced Reports setup

The installation logs do not help much during the installation process for the database objects setup other than for verifying that the installation occurred as intended. If the directory locations provided to the Infor EAM database objects setup do not exist, the setup application goes all the way to the end without performing an installation. Ensure the installation paths exist, and set the path for the data files, log files, and index files to the data directory where you would normally store them for your database installation.

The application setup is just as tricky as the database objects setup - the installer doesn't tell you if you are missing the Visual C++ 10.0 run time DLL so make sure you install it before starting the application setup. You can tell if you are missing the Visual C++ 10.0 run time DLL if the Infor Application HTTP service is missing (you should see 2 services for Infor in services.msc). After the installation completes and the web server does display a login screen, you can check the WildFly/JBoss logs for additional error messages. You may have a warning in the logs indicating that the application server could not connect to the database - you can configure the database connection in the depconfig directory by editing the ewsconfig.xml file and then executing the deploy.bat batch file. Another common source of errors is when the deploy.bat file indicates that the tools.jar Java archive is missing - this message appears in the command prompt window when deploy.bat begins execution.

After sorted out all the errors and have the application running, you can browse to the application in the web browser and attempt to log in with the username "r5" and password "r5", which is the default account created within the application.

The installer could have been made to reduce the administration effort for installing the application, but once you've installed it, you can create a procedure manual for your team to follow the steps that you did for setting up the system.