Testing blogging from my iPhone, this seems to work ok. Yay.
Keep an eye on this blog if you are interested in continous integration methods for improving your software team. I am preparing a post on the subject....
Wednesday, February 17, 2010
Tuesday, February 16, 2010
Improving upon continuous integration
I am quite a big fan of continuous integration and other automatable "agile practices" for improving performance in software teams. Roughly half a year ago the team I am the scrum master of started improving upon our practices, one of the first tasks was to create a script that made it able to create a release with a single command. With this done we added a continuous integration server (CruiseControl) and started down the path of automated tests & tasks. A couple of months later this has had measurable impact on the time it takes to make releases and as we've added compile & test tasks that run for each commit to SVN, this makes us more confident about the quality of the software we make.
I also hold the believe that nothing is ever perfect and it's always possible to improve and tune your software process. The problem I've been seeing lately is that, yes the continuous server helps us easily find compilation errors, bugs and broken tests. But once the code is in our SVN the damage is already done, we are working on a product with multiple teams in multiple time zones. It's very easy for someone to make a commit that breaks the build and then leave for the day, national holidays, other work assignments etc. I'll shortly outline our current process:
TeamCity allows us to have the following process:
A couple of minor caveats:
I also hold the believe that nothing is ever perfect and it's always possible to improve and tune your software process. The problem I've been seeing lately is that, yes the continuous server helps us easily find compilation errors, bugs and broken tests. But once the code is in our SVN the damage is already done, we are working on a product with multiple teams in multiple time zones. It's very easy for someone to make a commit that breaks the build and then leave for the day, national holidays, other work assignments etc. I'll shortly outline our current process:
- Write code & test
- Check in your changes to the version control system (VCS), such as SVN, GIT etc.
- Continuous integration server sees a change in the VCS and starts a build, tests and so on.
- If your code fails to compile or have broken some tests you will be notified and hopefully you are able to fix it before other developers update from the VCS.
- Other developers update from the VCS. They might update before you have had time to fix problems in the code you checked in.
- The bad code propagates to the whole team or the team might be sitting idle waiting for a fix for the bad code that is already in the VCS.
TeamCity allows us to have the following process:
- Write code & test
- Send your code to TeamCity, which can run the same checks and builds as the continuous integration server but before the code is committed to the VCS.
- TeamCity automatically commits to the VCS if your code compile, pass all tests etc.
- Other developers update as normally from the VCS but they only get good code.
A couple of minor caveats:
- TeamCity has no command line tool, so there is no way to script commits. Everything is done with IDE plugins.
- Java centric, be ready for a lot of scripting & configuration if your build is complex using lots of different build systems (makefile, vcproj/sln, cygwin etc).
Tuesday, January 5, 2010
Increasing java heap size when using maven
If you get out of memory exceptions while using maven you can tweak the amount of heap space available to the JVM with the following environment variable,
export MAVEN_OPTS=-Xmx512m
I didn't test any other but i presume you can set other Java options also with the same variable.
export MAVEN_OPTS=-Xmx512m
I didn't test any other but i presume you can set other Java options also with the same variable.
Wednesday, December 30, 2009
Adding custom Javascript bindings to WebKIT
This post will show you how to add custom objects / functions which are implemented in C but used in a Javascript that's part of a HTML document that WebKIT renders. We will add a class "myclass" to the Javascript engine instance and it will have one static function named "mymethod()" that returns a single string.
First you need to install all the needed dependencies, assuming you are using Ubuntu or other Debian based system run the following command as root:
simple.html
C implementation of myclass.mymethod()
mymethod() will be implemented as a static function on the myclass object. The JavaScript framework used by WebKIT can be used with an API that's documented on Apple's pages. The important thing for this simple class is the JSClassDefinition and JSStaticFunction struct both have to be filled out with information about our class, including its static function(s) (mymethod), initialize/constructor callback, finalize/destructor callback and so on. To add the class to the Javascript engine we need something called the JSGlobalContextRef, how you get it depends on the flavor of WebKIT you are using. In this tutorial I will show how to do it with the GTK port of WebKIT. Connect a handler to the window-object-cleared signal which is sent when a new page is loaded (found this out after a lot of googling, reference). In the callback you connect you can call webkit_web_frame_get_global_context(), it will return the JSGlobalContextRef you need.
Enough talking, here is the actual source code for the example,
Finally, to compile and test the example code run the following commands:
First you need to install all the needed dependencies, assuming you are using Ubuntu or other Debian based system run the following command as root:
- apt-get install libwebkit-1.0.1 libwebkit-dev
simple.html
<html>
<body>
<h1>String in html</h1>
<script type="text/javascript">
document.write("<h1>String from JS:");
document.write(myclass.mymethod());
document.write("</h1>");
</script>
</body>
</html>
C implementation of myclass.mymethod()
mymethod() will be implemented as a static function on the myclass object. The JavaScript framework used by WebKIT can be used with an API that's documented on Apple's pages. The important thing for this simple class is the JSClassDefinition and JSStaticFunction struct both have to be filled out with information about our class, including its static function(s) (mymethod), initialize/constructor callback, finalize/destructor callback and so on. To add the class to the Javascript engine we need something called the JSGlobalContextRef, how you get it depends on the flavor of WebKIT you are using. In this tutorial I will show how to do it with the GTK port of WebKIT. Connect a handler to the window-object-cleared signal which is sent when a new page is loaded (found this out after a lot of googling, reference). In the callback you connect you can call webkit_web_frame_get_global_context(), it will return the JSGlobalContextRef you need.
Enough talking, here is the actual source code for the example,
Compile & Test
#include <gtk/gtk.h>
#include <webkit/webkit.h>
#include <JavaScriptCore/JavaScript.h>
static void myclass_init_cb(JSContextRef ctx, JSObjectRef object)
{
// ...
}
static void myclass_finalize_cb(JSObjectRef object)
{
// ...
}
static JSValueRef myclass_mymethod(JSContextRef context,
JSObjectRef function,
JSObjectRef thisObject,
size_t argumentCount,
const JSValueRef arguments[],
JSValueRef *exception)
{
JSStringRef string = JSStringCreateWithUTF8CString("mystring");
return JSValueMakeString(context, string);
}
static const JSStaticFunction class_staticfuncs[] =
{
{ "mymethod", myclass_mymethod, kJSPropertyAttributeReadOnly },
{ NULL, NULL, 0 }
};
static const JSClassDefinition class_def =
{
0,
kJSClassAttributeNone,
"TestClass",
NULL,
NULL,
class_staticfuncs,
myclass_init_cb,
myclass_finalize_cb,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
static void addJSClasses(JSGlobalContextRef context)
{
JSClassRef classDef = JSClassCreate(&class_def);
JSObjectRef classObj = JSObjectMake(context, classDef, context);
JSObjectRef globalObj = JSContextGetGlobalObject(context);
JSStringRef str = JSStringCreateWithUTF8CString("myclass");
JSObjectSetProperty(context, globalObj, str, classObj,
kJSPropertyAttributeNone, NULL);
}
static void window_object_cleared_cb(WebKitWebView *web_view,
WebKitWebFrame *frame,
gpointer context,
gpointer arg3,
gpointer user_data)
{
JSGlobalContextRef jsContext = webkit_web_frame_get_global_context(frame);
addJSClasses(jsContext);
}
static GtkWidget* main_window;
static WebKitWebView* web_view;
static void destroy_cb(GtkWidget* widget, gpointer data)
{
gtk_main_quit ();
}
static GtkWidget* create_browser()
{
GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ());
gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (web_view));
g_signal_connect (G_OBJECT (web_view), "window-object-cleared", G_CALLBACK(window_object_cleared_cb), web_view);
return scrolled_window;
}
static GtkWidget* create_window()
{
GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 500, 500);
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy_cb), NULL);
return window;
}
int main (int argc, char* argv[])
{
gtk_init (&argc, &argv);
if (!g_thread_supported())
g_thread_init (NULL);
GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), create_browser (), TRUE, TRUE, 0);
main_window = create_window();
gtk_container_add(GTK_CONTAINER (main_window), vbox);
gchar* uri = (gchar*) "file://simple.html";
webkit_web_view_open(web_view, uri);
gtk_widget_grab_focus (GTK_WIDGET (web_view));
gtk_widget_show_all (main_window);
gtk_main ();
return 0;
}
Finally, to compile and test the example code run the following commands:
- gcc test.c -o test `pkg-config --cflags --libs webkit-1.0`
- ./test
Wednesday, December 16, 2009
Clutter tutorials
For some time I've been planning to look into Clutter more seriously, it looks like a really nice framework to build a UI engine on top of. Today I found the following two articles that gives a decent introduction to how the API works,
This post goes through the basics of Clutter's C API. It covers how to create an initial empty window, how to render simple rectangles (with textures) and finally how to animate and scale them.
http://tuxradar.com/content/clutter-beginners-tutorial
This one mentions on how it's possible to use gjs to create JavaScript bindings which gives you an easier to use development environment (no memory management and other C "features").
http://townx.org/blog/elliot/introduction-sorts-javascript-desktop-application-development-gjs-and-clutter
This post goes through the basics of Clutter's C API. It covers how to create an initial empty window, how to render simple rectangles (with textures) and finally how to animate and scale them.
http://tuxradar.com/content/clutter-beginners-tutorial
This one mentions on how it's possible to use gjs to create JavaScript bindings which gives you an easier to use development environment (no memory management and other C "features").
http://townx.org/blog/elliot/introduction-sorts-javascript-desktop-application-development-gjs-and-clutter
Monday, December 14, 2009
Creating a web service client using gsoap.
In this post I'll continue my posts related to creating web services (Part 1, Part 2), as have been shown it's easy to setup and create the server part of the service using Java, Axis2 and Tomcat. However you do not always have access to a very hungry and memory intensive Java stack so this post will cover how you can create the client in native C code. For this I'll be using gSOAP. If you have the web service up and running as describe previously you should be able to access it's WSDL document at http://localhost:8080/axis2/services/ExampleService?wsdl. The WSDL document describes the service in detail and can be used to generate the needed code to access the service. First you start off by installing the package:
- apt-get install gsoap
- wsdl2h -c -o mywebservice.h http://localhost:8080/axis2/services/ExampleService?wsdl
- soapcpp2 -C -c mywebservice.h -I/usr/include/gsoap
- gcc -I/usr/include/gsoap myclient.c -o myclient.o soapC.c soapClient.c /usr/include/gsoap/stdsoap2.c
#include "soapH.h"
#include "stdio.h"
#include "MyWebService.nsmap"
int main(int argc, char *argv[])
{
struct soap *soap = soap_new();
struct _ns1__getSomeValueResponse response;
struct _ns1__setSomeValue value;
*value.args0 = 1.0f;
if (soap_send___ns2__setSomeValue(soap, NULL, NULL, &value) == SOAP_OK)
printf("okay");
else
soap_print_fault(soap, stderr); // display the SOAP fault on the stderr stream
if (soap_call___ns2__getSomeValue(soap, NULL, NULL, &response) == SOAP_OK)
printf("value: %f\n", *response.return_);
else // an error occurred
soap_print_fault(soap, stderr); // display the SOAP fault on the stderr stream
}
Monday, November 2, 2009
Creating a simple web service using Axis2
This post will briefly outline how I implemented a sample web service using Axis2 POJOs. First you need to setup a project directory for you. It should be structed like this:
Implement a simple java (POJO) with one setter and one getter. This will be the
server side of the web service.
ExampleService.java
Steps to build and deploy locally,
That's it.
In my next post I will show how to do the client side using gSOAP and C/C++.
Related reads:
- Axis2 POJO Tutorial
- services.xml description
Reference services.xml:
<service name="ExampleService" scope="application">
<description>My example service</description>
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
<parameter name="ServiceClass">
mywebservice.ExampleService
</parameter>
</service>
Reference ant file, store this as build.xml:
rootdir/build.xml
rootdir/src/META-INF
rootdir/src/META-INF/services.xml
rootdir/src/mywebservice
rootdir/src/mywebservice/ExampleService.java
Implement a simple java (POJO) with one setter and one getter. This will be the
server side of the web service.
ExampleService.java
package mywebservice;
public class ExampleService
{
float someValue = 42;
public float getSomeValue()
{
return someValue;
}
public void setSomeValue(float someValue)
{
this.someValue += someValue;
}
}
Steps to build and deploy locally,
- Build the web service using by running ant in the root directory.
- Copy the whole build/MyWebService directory into /var/lib/tomcat6/webapps/axis2/WEB-INF/services/MyWebService
- Check that http://localhost:8080/axis2/services/listServices lists your new web service.
- You can look at the WSDL document by clicking on your services.
That's it.
In my next post I will show how to do the client side using gSOAP and C/C++.
Related reads:
- Axis2 POJO Tutorial
- services.xml description
Reference services.xml:
<service name="ExampleService" scope="application">
<description>My example service</description>
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
<parameter name="ServiceClass">
mywebservice.ExampleService
</parameter>
</service>
Reference ant file, store this as build.xml:
<project name="MyWebService" basedir="." default="generate.service">
<property name="service.name" value="MyWebService">
<property name="dest.dir" value="build">
<property name="dest.dir.classes" value="${dest.dir}/${service.name}">
<property name="dest.dir.lib" value="${dest.dir}/lib">
<property name="axis2.home" value="../../axis2-1.5">
<property name="repository.path" value="${axis2.home}/repository">
<path id="build.class.path">
<fileset dir="${axis2.home}/lib">
<include name="*.jar">
</fileset>
</path>
<target name="prepare">
<mkdir dir="${dest.dir}">
<mkdir dir="${dest.dir}/lib">
<mkdir dir="${dest.dir.classes}">
<mkdir dir="${dest.dir.classes}/META-INF">
</target>
<target name="clean">
<delete dir="${dest.dir}">
<delete dir="src" includes="sample/pojo/stub/**">
</target>
<target name="generate.service" depends="clean,prepare">
<copy file="src/META-INF/services.xml" tofile="${dest.dir.classes}/META-INF/services.xml" overwrite="true">
<javac listfiles="yes" srcdir="src" destdir="${dest.dir.classes}" includes="mywebservice/**">
<classpath refid="build.class.path">
</javac>
<jar basedir="${dest.dir.classes}" destfile="${dest.dir}/${service.name}.aar">
<copy file="${dest.dir}/${service.name}.aar" tofile="${repository.path}/services/${service.name}.aar" overwrite="true">
</target>
</project>
Subscribe to:
Posts (Atom)