Codecademy.com – the good – the bad and the ugly.

School holidays are a great time for kids to well, have a holiday.

But this year, this poor programmer has been besieged by some pupils of a local School. The poor things had been set the task of doing the javascript course on the http://www.codecademy.com site.

It’s a big course. I was a bit dubious about some of it’s teaching methods though. One poor lad was stuck for 24 hours when he wrote a lovely infinite loop. Instead of the Code Academy site working that out, it just let the code hang the browser. The lad thought his computer had gone wrong.

I also detected a large amount of copy and paste. There is  a help forum which is very copy and pastey and I wondered about how much javascript they were REALLY learning and how much of CTRL C/V was going on.

I noticed with loops (and this is a minor point) they did not point out it is better to do:-

var a=b.length;
for (var c=1;c<a;++c)

than

for (var c=1;c<b.length;++c)

Because the for next loop is reading the b.length over and over. Ok I’m being picky but.

I’m not sure about storing functions in variables either.

var x=function() {
 console.log ("Hello");
};

as opposed:-

function x() {
console.log("Hello");
}

The first example is 97% slower running than the second. That’s a whole lot of slower. (Credits to this link)

I did like the way it taught object oriented programming and different notations although the student I worked through it with got very confused by it. But point taken it’s probably really good to learn all three things.

But my main bug bear was really that you would get code that would fail even though it was correct. In one exercise the output of J.R.R Tolkien vs J.R.R. Tolkien caused the code to fail. Technically the code was right so it should have passed. Yes, there was a slight difference in the output from what was required but I get the impression the test of whether the code works is not able to actually tell if the code is right but only what output is given under certain circumstances, it’s like JUnit testing where you write a test in java that really doesn’t actually test the code but just the output. Although the student didn’t notice at one point I did manage to fool the tester into thinking I’d written correct code just by “console.logging” what I thought it wanted to hear.

Overall it’s a very good concept, the site is laid out well and nice to use. *BUT* I think it’s inappropriate to throw it at a complete new programmer (who is 14) without much help. At worst it teaches you to Copy and Paste. At best you actually learn to code.

Lastly I wondered why thee was no interaction with the web itself, Javascript is essentially a web technology but there was no effort to give any more output than “console.log”. Sure, you learn javascript but all you can do is put up input boxes and output to a console. Maybe at the end they could have introduced web technologies like JQuery as  a pre-cursor to a javascript course.

Yup, it’s a great site, I love what it’s trying to do, but the big no no for me is the hanging when a student writes an infinite loop, it can’t be that hard to write a “code timeout” that says if it’s not executed within a set amount of time give the “infinite loop” warning. Also, some of those error messages just don’t really help!. At one point I was going to get the student to install NetBeans and paste the javascript in there as it would pretty much help them to get it right. All the students I worked with kept doing this:-

for (var i=0;i<k.length;++i) ;

they would get very confused about when you { or ( or [ rather than ;.

Anyway – we got there in the end. Perhaps I should become a teacher?

A simple NULL killer.

You know what it’s like – you want to avoid nulls. Well this is part of my utilclasses package. Along with the “optional” package. This simple routine is a one line call to ensure I never get a null back.

To call It I simply do

String stringTest=null;
Integer numTest=null;
System.out.println(noNulls.fix(stringTest));
System.out.println(noNulls.fix(numTest));

Here’s the class.

package utilclasses;
/**
 * 
 * Another fine Java Class
 * http://www.netbeansboy.org
 * @author paulc
 */
public abstract class noNulls {

public final static Object fix(Object value) {
 if (value==null) {
     if (value instanceof String) return "";
     return 0;
     }
 return value;
 }
 
}

Optional Parameters another way.

I’ve always liked the way that in C++ and other languages you can have optional parameters and I’ve been messing around with ways to do it in JAVA, so I came up with a class that extends the HashMap and makes it quite a neat way of having optional parameters in code.

Here’s the class

package utilclasses;
import java.util.HashMap;
/**
 *
 * Another fine Java Class http://www.netbeansboy.org
 *
 * @author paulc
 */
public final class optional extends HashMap {
 
 optional(Object... objects) {
 put(objects);
 }
 
 public void put(Object... objects) {
 for (int i=0;i<objects.length;i=i+2) {
 Object key=objects[i];
 Object value=objects[i+1];
 put(key,value);
 }
 }
 
 
 
}

 

As you can see it has one routine called put that is called in the constructor that constructs the hash map, so it’s use in your code is pretty simple.

 
 opt(new optional("Name","John","Age",34,"Address","test"));
 
 
 
 }
 
 
 
 private static void opt(optional y) {
 System.out.println(y.get("Name"));
 System.out.println(y.get("Age"));
 System.out.println(y.get("Address"));
 System.out.println(y.get("22"));
 
 }

Which produces the result:-

John
34
test
null

Note that the last result is null because optional parameter 22 has not been set.  Note however this will only work with Java 8. I’ve actually used their optional solution to create mine! Only that I really like the idea of just filling out key values so you can see in your code the variables.

Transferring from MYSQL to Mongo DB

I recently wanted to transfer from MYSQL to MONGODB so I developed some routines to make the transfer. It’s pretty self explanatory but allows you to dump tables and delete data as required.

package mongo;
import java.math.BigDecimal;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import java.net.UnknownHostException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
 *
 * @author Paul Clevett
 * http://www.dailyforextrader.me
 */
public class Mongo {
/**
 * @param args the command line arguments
 */
 public static void main(String[] args) {
 try {
 // To directly connect to a single MongoDB server (note that this will not auto-discover the primary even
// if it's a member of a replica set:
Connection conn;
 try {
 // create a java mysql database connection
 String myDriver = "com.mysql.jdbc.Driver";
 String myUrl = "jdbc:mysql://***SERVERIPADDRESS****/**INSERTDATABASE***";
 Class.forName(myDriver);
 conn = DriverManager.getConnection(myUrl, "***INSERTUSERNAME***", "**INSERTPASSWORD***");
// your prepstatements goes here...
 } catch (Exception e) {
 System.err.println("Got an exception! ");
 System.err.println(e.getMessage());
 return;
 }
MongoClient mongoClient = new MongoClient("***MONGODBIPADDRESS**", 27017);
PrintDatabaseNames(mongoClient);
 DB db = mongoClient.getDB("**MONGODBDATABASE****");
 char[] password = "r00t21".toCharArray();
 boolean auth = db.authenticate("root", password);
deleteRecords("alarms",db);
 deleteRecords("sites",db);
 deleteRecords("users",db);
 deleteRecords("datakeys",db);
 
 
 
 dumpTable("datakeys",conn,db);
 dumpTable("alarms", conn, db);
 dumpTable("sites", conn, db);
 dumpTable("users", conn, db);
} catch (UnknownHostException ex) {
 System.out.println("Unkoown Host " + ex);
 }
 }
private static void deleteRecords(String sTableName,DB db) {
 BasicDBObject query = new BasicDBObject();
 DBCollection col1=db.getCollection(sTableName);
 col1.remove(query);
 }
private static void dumpTable(String TableName, Connection conn, DB db) {
 CreateCollection(TableName, db);
 DBCollection coll = db.getCollection(TableName);
 Statement s = null;
 ResultSet r = null;
 try {
 // get the iVolt units table
 s = conn.createStatement();
r = s.executeQuery("select * from " + TableName);
} catch (Exception e) {
}
 try {
 while (r.next()) {
 Map fields = new HashMap();
for (int i = 1; i < r.getMetaData().getColumnCount() + 1; ++i) {
 String sColumnName = r.getMetaData().getColumnName(i);
if (r.getObject(sColumnName) != null) {
if (r.getObject(sColumnName).getClass() == BigDecimal.class) {
 fields.put(sColumnName, new BigDecimal(r.getObject(sColumnName) + "").doubleValue());
 } else {
 fields.put(sColumnName, r.getObject(sColumnName));
 }
 }
}
InsertRecord(createRecord(r.getMetaData().getColumnName(1), r.getObject(1) + "", fields), coll);
 }
 } catch (Exception e) {
 System.out.println("Fail " + e);
 }
}
private static BasicDBObject createRecord(String tablename, String DBName, Map keyvalues) {
 BasicDBObject result = new BasicDBObject(tablename, DBName);
 Iterator<Map.Entry<String, String>> i = keyvalues.entrySet().iterator();
 while (i.hasNext()) {
 String key = i.next().getKey();
 result.append(key, keyvalues.get(key));
}
return result;
 }
private static void InsertRecord(BasicDBObject doc, DBCollection coll) {
coll.insert(doc);
 }
private static void PrintDatabaseNames(MongoClient mongoClient) {
List dbnames = mongoClient.getDatabaseNames();
 System.out.println("DatabaseNames");
 for (int i = 0; i < dbnames.size(); ++i) {
 System.out.println(dbnames.get(i) + "");
}
}
private static void PrintCollectionNames(DB db) {
 System.out.println("**** Collection Names ****");
 Set<String> colls = db.getCollectionNames();
for (String s : colls) {
 System.out.println(s);
 }
}
private static void CreateCollection(String CollectionName, DB db) {
DBCollection collection;
 if (db.collectionExists(CollectionName)) {
 collection = db.getCollection(CollectionName);
 } else {
 DBObject options = BasicDBObjectBuilder.start().add("capped", false).get();
 collection = db.createCollection(CollectionName, options);
 }
}
}

Java EJB passing string parameters from the front end.

Firstly, my apologies I’ve not been very active writing for the blog, I have been building a huge enterprise application at my work  that handles billions of records of data, it’s been keeping me VERY busy.

Recently I’ve been working on a project which has a “CRUD” module as part of it (to save me time), the software generates a complete Grid, editing forms, adding ‘thing’.

I had real problems because I wanted to pass a joined string parameter.

It was called from a prime faces menu.

<p:menuitem value="Edit counterfiet serial numbers" 
 ajax="true" 
 update="CRUDDLGDIALOG"
 actionListener="#{cRUD.init(
'dateofreport=timestamp,reportedby='+srs.thisUser.username))}" 
 onclick="CRUDDIALOG.show();"/>

Ofcourse this did not work, for some reason the backing bean thought that I was trying to add two numbers together… WHY????

So the solution, write a new function in the backing bean to join the two strings together.

<p:menuitem value="Edit counterfiet serial numbers" 
 ajax="true" 
 update="CRUDDLGDIALOG"
 actionListener="#{cRUD.init(
cRUD.stringJoin('dateofreport=timestamp,reportedby=',srs.thisUser.username))}"
 onclick="CRUDDIALOG.show();"/>

Here is the backing bean code. Note that I have two backing beans cRUD for managing the CRUD form and SRS which is a general purpose backing bean for the application. I definitely did not want to have one mixed into the other because it was very useful to have a CRUD system I could use when generating any EJB application.

public String stringJoin(String string1,String string2) {
 return string1.concat(string2);
 }

Setting up MON for mysql

Just a short post. I was trying to get two database servers to check each other for the running database. Here are the Parameters (I actually had to look at the package source to get them!).

msql-mysql.monitor --mode MySQL --database=dbname --user=user --password=pw

Tungsten Replicator setting up and Gotchas

Tungsten Replicator site Clicky

So we have a big MYSQL server with mission critical data on it.

I want to replicate it accross to another MYSQL database, they are both ubuntu servers with Percona MYSQL database.

1. Preparation

Master – Install RUBY, JAVA,

Slave – Install RUBY, JAVA

edit the hosts files on both machines in etc/hosts and add the other servers in each one and reference the IP address – just makes things easier.

2. SSH

Make sure you set up SSH so that you can ssh from one server to the other WITHOUT using passwords.

3. PORTS

make sure all ports required 10000,10001 are available (particularly problematical PLESK, WEBMIN a whole host of things like these ports) on all machines. One server actually had a PLESK tool on it even though plesk was not installed!!

4. MYSQL

make sure everything is set up and restore a backup of the database before you start.

5. Helper scripts

Set up your tungsten. You’ll need to edit NODES_MASTER_SLAVE.sh to make sure your nodes are correct and USER_CONFIG as per the tungsten documentation.

install.sh – put in the tungsten folder e.g. tungsten-replicator-2.1.0-343

VERBOSE=1 ./cookbook/install_master_slave ./cookbook/NODES_MASTER_SLAVE.sh

tungsten.sh (actually I renamed this to tungsten and did a chmod +x tungsten)

if [ "$1" == "help" ] || [ "$1" == "" ]; then
 echo "Commands"
 ls installs/cookbook/tungsten/tungsten-replicator/bin/
else
installs/cookbook/tungsten/tungsten-replicator/bin/$1 $2 $3 $4 $5
fi

So you can type

./tungsten replicator status

To run commands.

Creating an automatic backup script for mysql

Ok this is really step by step. There’s nothing complicated

1. Created a backup folder as ROOT

> sudo su
enter password
> cd /
> mkdir backup
> cd backup

now create a shell script I use NANO to do this. (don’t forget to change the username and password to match yours)

> nano backup.sh

cd /backup
mysqldump -u username -ppassword --all-databases>backup`date +%a`.sql

Save the file. backup.sh

Now edit the cron table

> crontab -e
01 02 * * *  /backup/backup.sh

and save.

This will cause your backup to happen every morning at 2am.

It’s a good idea to test your backup routine sh backup.sh before leaving it to cron to do the work.

 

Building a processing application with EJB’s (don’t use THREADS!)

I have for some time had to build processing applications. These normally consist of thread based things that run off and do a lot of calculations and database work. These days however I use EJB’s and the @Asynchrounous tag above a routine to make it work asynchronously.

To make it work you need to create 2 stateless session beans.

One will hold your routines that you wish to run, lets call this runnerBean, you need to create a local interface to it.

Second, create the timer bean that will start off the threads in runner bean.

In the timerBean that starts all the threads off create an @Schedule routine and a reference to the runnerBean.

@EJB
private doRunnerLocal doRunner;

@Schedule(second = “*/5”, minute = “*”, hour = “*”, persistent = false)
private void importThreadManager() {

while (true) {

List serialNos=new ArrayList();

try {
serialNos.em.createNativeQuery(“select * from serialnos where processed<1”,SerialNos.class).getResultList();
} catch (Exception e) {

}

if (serialNos.isEmpty()) {
// Have a sleep for a while if nothing found
try {
Thread.sleep(10000);
} catch (InterruptedException x) {
}
} else {
for (i=0;i<serialNos.size();++i) {
doRunner.doSomething((String)serialNos.get(i));
}
}

}

In the runner bean then create your Async threads really simply.

@Asynchronous
public void doSomthing(String serialNo) {

// Process serial numbers

}

Job Done!