Blog Archives

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.

Advertisements

EJB downloading an excel file from JSP

The Calling Page

Let’s say you have a button on a JSP page that calls it. One of the problems is stopping the page opening as blank. So here’s the calling button

<form method="post" action="#">
 <input type="button" value="Download" onClick="return downloadButton();"/>
        </form>
        

The iFRame is used to trigger the excel call, and here’s the download button javascript.

function downloadButton() {
 
    document.getElementById("excel").src="exportxl.jsp?sql=select * from mytable";
    return false;
    
}

The Responding Page

Now the Calling JSP Page that goes off and gets the Excel Spreadsheet from the EJB, I have an EJB called server and the corresponding remote interface “server remote” note that these must be registered in the xml files in the web app so the web app can see the remote interface in the EJB

<%-- 
    Document   : exportxl
    Created on : Aug 1, 2011, 8:36:23 AM
    Author     : paulc
--%>
<%@ page import = "java.sql.*" %>
<%@ page import = "javax.naming.Context" %>
<%@ page import = "javax.naming.InitialContext; "%>
<%@ page import = "PHJ.*" %>
<%@page contentType="application/vnd.ms-excel" pageEncoding="UTF-8"%>
<%

    PHJ.ServerRemote jobManagerBean = null;
    try {
        Context c = new InitialContext();
        jobManagerBean = (PHJ.ServerRemote) c.lookup("java:comp/env/Server");
    } catch (Exception ne) {
        System.out.println("Could not find Job Manager Bean " + ne);
        out.println("Could not find Job Manager Bean");
        return;
    }

    response.setHeader("Content-disposition", "attachment; filename=excelexport.csv");

    String sql = "";
    if (request.getParameter("sql") != null) {
        sql = request.getParameter("sql");

        out.print(jobManagerBean.prepareCSVForExcel(sql));

    } else {
        out.println("Error, No SQL statement specified");

    }
    
    

%>

The EJB

And here’s the routine in the EJB.

 
    private Connection conn;
    private String dbName = "myJNDIRESOURCE"; // make sure you have JNDI resource setup 
    /* This routine gets a connection from the above DBName, however, if it can't find it it lists the available JNDI resourcees
     * to the console or log
     */ 
    private Connection getConnection() {
        if (conn != null) {
            try {
                if (!conn.isClosed()) {
                    return conn;
                }
            } catch (SQLException ex) {
                // Do nothing just carry on.
            }

        }
        InitialContext ic = null;

        Query q = null;

        try {
            // initialize JNDI lookup parameters
            ic = new InitialContext();
            DataSource ds = (DataSource) ic.lookup(dbName);
            conn = ds.getConnection();
        } catch (Exception e) {
            try {
                System.out.println("JNDI Resource " + dbName + " not found " + e);
                NamingEnumeration children = ic.list("");
                while (children.hasMore()) {
                    NameClassPair ncPair = (NameClassPair) children.next();
                    System.out.print(ncPair.getName() + " (type " + ncPair.getClassName() + ")");

                }
                System.out.println("**** CANNOT FIND DATABASE ************************");
                children = ic.list("jdbc");
                while (children.hasMore()) {
                    NameClassPair ncPair = (NameClassPair) children.next();
                    System.out.print(ncPair.getName() + " (type " + ncPair.getClassName() + ")");

                }
                System.out.println("****************************************");
            } catch (Exception f) {
                System.out.println("Error 57:" + f);
            }
            System.out.println("ERROR 52: " + e);
            return null;
        }
        return conn;

    }

    public String prepareCSVForExcel(String sSQL) {

        String sResult = "";
        try {
            conn = getConnection();
            Statement s = conn.createStatement();
            ResultSet r = s.executeQuery(sSQL);
            // feldnames
            for (int i = 1; i != r.getMetaData().getColumnCount(); ++i) {
                sResult = sResult + r.getMetaData().getColumnName(i) + ",";


            }
            sResult = sResult + "\n";

            while (r.next()) {
                for (int i = 1; i != r.getMetaData().getColumnCount(); ++i) {
                    try {
                    if (r.getObject(i) != null) {
                        sResult = sResult + r.getString(i) + ",";
                    } else {
                        sResult = sResult + ",";

                    }
                    } catch (Exception e) {
                        sResult = sResult + ","; // Happens when there is a conversion error to a tiemstamp
                    }


                }
                sResult=sResult+"\n";



            }




        } catch (Exception e) {
            return e + "";
        }
        return sResult;
    }

Android Global Variables.

Those of you familiar with android programming will be used to using intents to pass data from activity to activity but there is a much easier way of storing state information. Using a global variable class.

1. Create a class

public class GlobalVariables extends Application {

    public String sResult = "";
}

This extends the application class.

Then edit your AndroidManifest.xml file

   <application android:name="GlobalVariables" android:theme="@style/CustomTheme" android:label="@string/app_name"
                 android:icon="@drawable/icon"  >

When you want access to one of those juicy globals in your application just use:-

  GlobalVariables gb = ((GlobalVariables) getApplicationContext());
  Log.i("Test Variable is "+gb.sResult);

Simples!

 

Using Jasper Reports with Visual Web in Netbeans 6.5

Firstly Infragistics let us down – you can only use Infragistics for JSF with Netbeans 5.5 (Although the website just sasy “NETBEANS”) ,… Refund please.

So our requirements:-

Netbeans 6.5
Jasper Reports
Visual Web – Woodstock/Icefaces

1. DO NOT INSTALL the Jasper Reports Plugins into Netbeans 6.5 – it breaks Visual Web
2. to Edit Reports use the stand alone Jasper Reports applciation

Secondly we need to add Jasper Reports ENGINE only to the Netbeans project so that we can run the jasper reports without upsetting visual web.

Now we can install the icefaces plugins and use them with our project.

To do this, simply download the Jasper Reports JAR file and then create a library “JasperReports” and add it to your web project – this will give you the support you need.

Save your reports into the WEB folder and then use the other code I have on this blog to execute the reports you create in your external IReport application.

Important: http://facestutorials.icefaces.org/tutorial/woodstock/PortingGuidePart1.html < Read this first before adding icefaces to your project.

 Also you’ll find this 2 page crud useful as it contains both Icefaces and JSP pages. http://facestutorials.icefaces.org/tutorial/woodstock/TwoPageCrudTable_Part2.zip

 Page Locations

Your old JSP pages (Woodstock) will be located at http://localhost:8080/Project-war/faces/pagename.jsp

IceFaces Pages are at http://localhost:8080/Project-war/pagename.iface  

You will also find your project runs index.html which you should redirect to where you want by changing it to:-

<meta http-equiv=”refresh” content=”0;url=faces/Page1.jsp”>

Netbeans 6.5 RC Can’t load 6.1 Project

Normally I write posts to solve problems. Sadly today I’m writing a post out of desperation. I am currently reviewing the RC of Netbeans 6.5, it has some great features *BUT* we have our main huge project we are working on right now that we can’t work with in it.

It’s an enterprise application with Jasper Reports and Java Server Faces, however. We cannot load any JSF pages they don’t appear for editing, just the java code, we occasionally get an “Illegal State Exception”.

I read somewhere that the problem is to do with Jasper Reports, but even not loading the plugins we cannot load the JSF pages from the project in 6.5.

UPDATE
It is the jasper reports plugin Ireport causing the problem. Unfortunately you can’t just uninstall the plugin it seems to actually “stuff up” (technical term) NB completely.

Java Server Faces, SQL SERVER and CHAR FIELDS

I have modified the excellent JTDS driver to strip the spaces from CHAR FIELDS so that Java Server faces controls do not get confused when fields are of different lengths and also when you go to edit a field you don’t get a pile of spaces at the end of the text.

The problem.

Well I have a project where the people who originally designed the database were obviously monkeys. So they used CHAR fields throughout the database. But not all the same size, for example:-

TABLE 1 (SERVICE CODES) SERVICE CODE CHAR 2 JI

Then in an other table

TABLE 2 SERVICE CODE CHAR 50

This means that if you create a drop down box on a page with the service code list it would be padded and would not match the other table. I initially started modifying the SQL code to CAST service code as a CHAR to match the other one. Since there were 100 odd tables this meant masses of extra work to use Java Server Faces.

The other problem is that editing fields have extra spaces at the end of the data – what a nightmare.

So I pulled down the open source JTDS driver and rewrote it to trim all spaces from CHAR fields, thus making JSF work right and solving my SPACE problem.

The files are here

Source Code (converted into a Netbeans Project)

Note if you download and use this you do so at your own risk, no warranty, implied or otherwise is provided for this software.

Note 2: if you were using an OLD jdts driver you will need to remove the references from the SERVER as well as NETBEANS and use this new one – I might get round to renaming the driver to something else but if you find there are spaces where there should not be its probably because you are running the standard driver not the new one.

Note 3: If you just want the driver its in the “dist” subdirectory, you need the LIB folder as well.

Note 4: If you publish a project using this driver and modify the driver then publish it again, NB won’t change the driver on the glassfish server if it has the same name, so you’ll have to copy it over yourself.

Java Server Faces and Google Chrome — Goodbye IE!

When Firefox 3 came out I was hoping it would run JSF faster than IE did, instead it actually failed to run at all well so we just forgot about it and went back to sunny IE for our clients.

Today! I install Google Chrome… Actually I expected JSF not to work at all… let alone how it does.

JSF runs VERY VERY VERY Fast in Google Chrome, sorry, actually, the whole internet runs VERY VERY VERY FAST.

Our tests so far show perfect compatibilty with JSF and it turns the web browser into an application browser, apart from the fact we can perform more customisations of the browser and use it as a real tool for accessing the multiple JSF projects we have.

We can now see bottlenecks without running profiler. The time between the pages loading shows where the problems are. IE really struggled with massive amounts of componants on pages. 

GOOD JOB GOOGLE

If you’ve not tried Google Chrome please please do… hitch it up to your JSF application (or any web app) or your favorite website and just fall off your chair at the MARKED DIFFERENCE in speed. 

I would think once word gets out that people will not want to use IE any longer.

Beautiful Coding – The way to life.

I often have to fix other people’s code. You can tell coders who have been coding for years simply by the feel of their code.

One of the problems with java is the simple fact that you can end up with a spaghetti-junction of objects all calling, calling back, implementing, sub classing, overriding, running ejb’s etc etc and it can be a bit of a nightmare to find your way through.

The key here (although you can reverse engineer into a UML Model with Netbeans) is really in the way that the code is written.

Things I do to make code more readable

– Initials of variables

All my strings for instance start with s – sName, sUsername
integers I , iCount, iGold
doubles d

and so on for different types of variables or objects.

Components on forms I use a 3 letter start up.

txtTEXTBOX
lblLABEL
stcSTATICTEXT
cmbCOMBOBOX

Also in the code using the java doc function, within Netbeans if you type /** enter it will auto document the next function and you just “fill in the blanks”, javaDoc is fantastic and well worth looking into. If you have “java doced” your code, not only does Netbeans pick up the documentation when you are typing or using your own functions but also you can generate a website that documents your classes!!! How Call

ALT-SHIFT-F – auto format your code, very useful.

Comment long bracketed loops. I always put // from  next to a bracketed loop  that is too long to see in one screen. e.g.

for (int iCount=0;iCount<10;++iCount) {          
system.out.println("Hello World "+iCount); } // From count to 10 icount

Also comment all calls to EJB’s to say what they do –

// Get this job’s History
JobManagerBean.getHistory(sJobNumber);

Beautiful Code!

Lisp programmers write beautiuful code, why? Because you have to, it becomes unreadable otherwise. In a way I wish all programmers would learn Lisp – because it makes you think in a different way and see software development from an almost etherial height. When I get some further research time I want to work on a lisp implementation for netbeans.

Remember that you will not be around forever, don’t punish the next poor programmer who has to work on your code. I like my code to be really easy to read and understand.

Code Rewriting

You know that sometimes I will rewrite a whole subroutine if I’m not happy with it. Programmers are artists, the difference is that the result of our art is a system for people to use or some form of output. Well written, neat, fast, efficient code means happy users and that is the caling of a programmer, to make the lives of the users easier.

If your software makes it harder. It needs rewriting, or maybe replacing with a pen and paper.

Be passionate about your coding and your users will be passionate about your software.

Jasper Reports — those empty reports.

Jasper reports is a wonderful product .. and it does integrate really nicely with netbeans. But when it goes wrong you can get blank reports with no clue to what the problem is.

Here are some short observations when coding it up with java and JSF that might help you.

1. Watch your field names – I noticed that when you generated reports Jasper Reports writes a pretty odd query especially with SQL server 2000 at the back end (yes I know, some people still use it, although this one WILL be upgraded to MYSQL):-

SELECT
     tblZones.”ZoneDescription” AS tblZones_ZoneDescription
FROM
     “dbo”.”tblZones” tblZones
ORDER BY
  tblZones.”ZoneDescription

Now this is fine – so then the fields in the report are mapped to tblZones_ZoneDescription intead of just leaving it as is – so if you then have a custom query for the report make sure that you are using the right field names or you could get that “blank page thing”

2. Main/Subforms or header/details (you know, Purchase Order Header and lines) – getting sub forms to work is hard graft! – I will post a solution when we do it – but until then it’s easier to have a SINGLE query with a join have the lines in the detail and group by the header id.

3. When it all goes wrong – sometimes I’ve had it refusing to run the jasper reports report I created earlier in good Blue Peter fashion. Normally a restart of NetBeans does fix this – but sometimes I’ve found a CHKDSK.

4. BACK IT UP – EVERYONE who develops should use a repository system such as subversion or CVS it’s saved my life countless times.

Have fun!

Writing out from a Java Server Faces table to a CSV….

Imagine if you will that you have a Java Server Faces table and you want to write it out to a CSV file.

1. Put The following code in your application bean.

public String OutputFromTableToCSV(
String sFilename,
TableRowGroup tableRowGroup1,
CachedRowSetDataProvider tblzonesDataProvider) {
// Create an ooutput text file
FileOutputStream out; // declare a file output object
PrintStream p; // declare a print stream object

try {
out = new FileOutputStream(sFilename
+".txt");

p=new PrintStream(out);
} catch (Exception e) {
return "Error, could not write to "+sFilename+".txt";
}

String sFields = "";
String sColumnTitle = "";
String sThisFieldName="";
List theseColumns = tableRowGroup1.getChildren();
// Columns
for (int i = 0; i < tableRowGroup1.getColumnCount(); ++i) {
sColumnTitle = sColumnTitle.concat(sColumnTitle);
sColumnTitle = sColumnTitle.concat(",");

// Get the SQL mapped fields
TableColumn thisComponant = (TableColumn) theseColumns.get(i);
try {
sColumnTitle = sColumnTitle.concat(
thisComponant.getHeaderText());
} catch (Exception e) {
}
}
if (!sColumnTitle.equals("")) {
sColumnTitle=sColumnTitle.substring(1); // Chop off initial ,
}
// Write it out
p.println(sColumnTitle);

RowKey[] TheseRows = tblzonesDataProvider.getAllRows();
for (int rowCount = 0; rowCount < TheseRows.length; ++rowCount) {
// Now do the rows
tblzonesDataProvider.setCursorRow(TheseRows[rowCount]);
for (int i = 0; i < tableRowGroup1.getColumnCount(); ++i) {
sFields = sFields.concat(sFields);
sFields = sFields.concat(",");
// Get the SQL mapped fields
TableColumn thisColumn = (TableColumn) theseColumns.get(i);
UIComponent thisChild=(UIComponent) thisColumn.getChildren().get(0);
// ",[#{currentRow.value['ZoneDescription']}]"
try {
sThisFieldName = thisChild.getValueExpression("text").toString();
sThisFieldName = sThisFieldName.substring(
sThisFieldName.indexOf("['") + 2);
sThisFieldName = sThisFieldName.substring(0,
sThisFieldName.indexOf("']"));

} catch (Exception e) {
}

// Add the field to the string to write out

sFields = sFields.concat(
tblzonesDataProvider.getValue(sThisFieldName).toString()
);

}
if (!sFields.equals("")) {
sFields = sFields.substring(1); // Chop off initial ,
}
p.println(sFields);

sFields="";
} // Next Row
// At this point we have to csv strings
// sfields and column title

// Now we have a comma delimited string called sresult in theory

p.close();
return "OK";
}

2. On the form with the JSF page.
a. Add the binding attribute to the tableRowGroup (in the left hand bottom pane).

Create an “Export to CSV file” button and in the event when clicked add this code:-

thefilename – the filename you want to write to
tableRowGroup1 – The table row group from your JSF page table
yourdataprovider – The data provider that feeds the JSF table

getApplicationBean1().OutputFromTableToCSV("thefilename", tableRowGroup1, yourDataProvider);