User Tools

Site Tools


Sidebar

Dave Orme muses about agile and functional programming.

My current work emphasizes SOA applications using Scala, Kubernetes, and AWS with a React-based SPA front-end. I'm also interested in progressive web applications and developer tools.


Blog

Scala, Clojure, and FP

Agile

The Cloud

Data-First Development

Older work

Coconut Palm Software home


Donate Bitcoin:

1Ecnr9vtkC8b9FvmQjQaJ9ZsHB127UzVD6

Keywords:

Kubernetes, Docker, Streaming Data, Spark, Scala, Clojure, OSGi, Karaf, GCP, AWS, SQL

Disclaimer:

Everything I say here is my own opinion and not necessarily that of my employer.

start

Agile- stress testing a release process

Sometimes you get on an airplane–or into a release process, and partway through the flight, something exciting happens.

You never want this to happen, but sometimes it happens anyway. And it becomes an opportunity to find out just how resilient your processes are.

One time I was on the way between Chicago O'Hare and Los Angeles International, and suddenly the airplane hit a really big bump, the captain instantly turned on the “Fasten Seatbelts” sign, and announced that we'd run into a bit of “unexpected weather”. As it was night, and I had a window seat, I then had a fantastic view of the lightning flashing around us when I looked out the window and saw thunder clouds towering from far below us to high above us.

This week, our agile team had the equivalent of the “fasten seatbelts” sign come on when our team's build server went down 1 week before our ship date and just as we were entering the testing phase of our release process.

No worries, we thought. We had prepared for this eventuality and simply moved the build to a backup machine while we waited for the primary machine to get the attention it needed to come back online.

Then yesterday–one day before our scheduled ship date and the day we were scheduled to build our gold master release–the backup build server suffered a catastrophic hardware failure. New machine needed. We had a day to rebuild our machine from original software images and configuration files, build the release, perform our due and administrative diligence, and ship.

However, being part of an extremely risk adverse organization, we had been forced by the organization several months ago to document all of our processes. We had all of the build server configuration files backed up in SVN. And we had the documentation we needed to quickly rebuild the server from scratch if we needed to.

In an 8 hour day's work, two of our team members rebuilt the server. Today, we built the gold release, did our due diligence, and shipped. On time and on budget.

Kudos to my manager and to all the team members who worked hard to implement the agile processes and documentation that made this possible. This is truly one of the greatest teams I've had the privilege to serve on–but we couldn't have done it without the agile practices that we have implemented from day one: agile practices based on Scrum, but with lots of input from XP and Eclipse Way.

2009/08/28 16:53

Write UIs more easily with FP techniques

At EclipseCon, I had some amazing conversations with various people about the potential to use EMF and modelling technologies to raise the abstraction level, and therefore programmer productivity, when creating user interfaces.

Since then, I've realized that XScalaWT can do all this already, for free, as long as you favor convention over configuration in your code…

More later. ;-)

~~LINKBACK~~ ~~DISCUSSION~~

2009/06/08 10:08

Eclipse Scala Plugin Progress

I just have to say: I've been using a recent build of the Eclipse Scala 2.7.4 plugin and finding it really solid and really productive!

  • Content assist for the most part Just Works
  • Ctrl-click to jump to source so far Just Works, regardless of if the source/destination is Java or Scala
  • And of course, the killer feature: integrating ScalaDoc and JavaDoc seems really stable now

All the old compiler crashes I was experiencing are now gone so I can now work for hours without restarting my IDE.

Now to figure out a way to releng mixed Java/Scala OSGI bundles. I hear that Maven is the way to go right now…

To the team: Nice job!

~~LINKBACK~~ ~~DISCUSSION:closed~~

2009/05/02 21:37

Oracle to unify Sun and Eclipse?

When Oracle joined the Eclipse board nearly seven years ago, it was with the stated intent to unify Sun Microsystems and Eclipse.

Assuming that their purchase goes through, they will have the power to actually do this. Will they?

~~LINKBACK~~ ~~DISCUSSION~~

2009/04/28 22:01

Creating a SWT custom control in Scala

I recently created a simple custom SWT control entirely in Scala, using some XScalaWT to simplify the UI code, to see how much simpler I could make the code using Scala.

Creating a SWT custom control in Java requires quite a bit of boilerplate code. Fortunately, while Scala cannot eliminate all this boilerplate, we will see how it can simplify it some. Of course, suggestions for how to improve it are welcomed in the comments. 8-)

The control

The SWT control we're creating displays a star that can be turned on and off by clicking it.

It follows the following standard SWT conventions:

  1. The standard SWT (parent, style) constructor
  2. Reuses SWT property and event names: selected and selectionListener

The code

Let's step through the code:

Notice that our default constructor only needs the standard SWT parameters and to call super. So we simply define it as a part of the class parameters.

Then we have constants, instance variables, and the internal layout of the control, which we will define using XScalaWT. In this case, our XScalaWT is really simple since what we are doing is really simple. More complicated custom controls would benefit even more from it.

class StarButton(parent : Composite, style : Int) extends Composite(parent, style) {
  val starOnImage = STAR_ON.image;
  val starOffImage = STAR_OFF.image;
 
  var starButton : Label = null;
 
  this.contains(
    label(starButton=_, starOffImage, 
          {e : MouseEvent => setSelected(!selected)})
  )

Here we instantiate a few images. STAR_ON and STAR_OFF are constants declared elsewhere that wrap a JFace ImageDescriptor.

The starButton is a SWT Label that will contain either starOnImage or starOffImage, depending on if the control is selected or not.

The XScalaWT block instantiates the Label and puts the default starOffImage in the label. It also adds a mouseDown listener that toggles the “selected” property.

The remainder of the code manages this property, fires the selection change event, and handles control resizing. First, the property:

  var selected = false;
 
  def getSelected() = selected
 
  def setSelected(newValue : Boolean) = { 
    selected = newValue
    if (selected) starButton.setImage(starOnImage) 
      else starButton.setImage(starOffImage)
    fireSelectionEvent
  }

Here's a standard JavaBean property implemented in Scala. Since SWT doesn't implement bound properties, we don't that here either. We also don't use the @BeanProperty annotation since we need custom code in the #setSelected method.

Next, selection listener handling:

  private var selectionListeners : scala.List[SelectionListener] = Nil
 
  def addSelectionListener(l : SelectionListener) = 
        selectionListeners = l :: selectionListeners
  def removeSelectionListener(l : SelectionListener) = 
        selectionListeners.remove(_==l)
 
  private def fireSelectionEvent = {
    val detail = new Event()
    detail.widget = this
    detail.data = selected.asInstanceOf[Boolean].asInstanceOf[Object]
    val event = new SelectionEvent(detail)
    selectionListeners.foreach(_.widgetSelected(event))
  }

The selection listener handling is pretty standard except that we use a few Scala-isms to simplify the code a bit.

First, we use a scala.List instead of a java.util.List implementation.

The add and remove selectionListener code uses Scala's list append (cons) operator to add the selection listener to the head of the list. Notice that Scala's List#remove accepts a filter function instead of the element to remove. This is only slightly more verbose than Java, but also a lot more powerful. In this context, the underscore represents the parameter being passed to the function (the candidate being evaluated.

Finally, we have the code for managing the control's size:

  addControlListener(new ControlAdapter() {
    override def controlResized(e : ControlEvent) = {
      val newSize = getSize()
      starButton.setBounds(0, 0, newSize.x, newSize.y)
    }
  });
 
  override def computeSize(xDefault : Int, yDefault : Int) = 
    starButton.computeSize(xDefault, yDefault)
}

Aside from Scala's ability to skip the curly braces when the body of a function is a single line, this code is nearly exactly the same as the equivalent Java.

Conclusion

Scala is useful for simplifying SWT custom control creation. For a simple control like this one, we don't see the benefit nearly as much as for a complicated custom control that could benefit greatly from XScalaWT. However, I still find the resulting code clearer, with less line noise than the equiavalent Java.

Can anyone see a way to simplify this further? If so, please leave a comment.

For reference, Here's the whole class:

class StarButton(parent : Composite, style : Int) extends Composite(parent, style) {
  val starOnImage = STAR_ON.image;
  val starOffImage = STAR_OFF.image;
 
  var starButton : Label = null;
  this.contains(
    label(starButton=_, starOffImage, 
          {e : MouseEvent => setSelected(!selected)})
  )
 
  var selected = false;
 
  def getSelected() = selected
 
  def setSelected(newValue : Boolean) = { 
    selected = newValue
    if (selected) starButton.setImage(starOnImage) 
      else starButton.setImage(starOffImage)
    fireSelectionEvent
  }
 
  private var selectionListeners : scala.List[SelectionListener] = Nil
 
  def addSelectionListener(l : SelectionListener) = 
        selectionListeners = l :: selectionListeners
  def removeSelectionListener(l : SelectionListener) = 
        selectionListeners.remove(_==l)
 
  private def fireSelectionEvent = {
    val detail = new Event()
    detail.widget = this
    detail.data = selected.asInstanceOf[Boolean].asInstanceOf[Object]
    val event = new SelectionEvent(detail)
    selectionListeners.foreach(_.widgetSelected(event))
  }
 
  addControlListener(new ControlAdapter() {
    override def controlResized(e : ControlEvent) = {
      val newSize = getSize()
      starButton.setBounds(0, 0, newSize.x, newSize.y)
    }
  });
 
  override def computeSize(xDefault : Int, yDefault : Int) = 
    starButton.computeSize(xDefault, yDefault)
}

~~LINKBACK~~ ~~DISCUSSION:closed~~

2009/04/05 16:38

EMF is social software

What I realized at EclipseCon: EMF is firstmost social software. Fundamentally, it's a better JavaBeans with a performant reflective API.

Oh–and unlike java.lang.reflect, they encourage you to use the reflective API.

Not surprisingly, the result is that EMF has become the seed out of which a whole lot of really cool meta programming tools have sprung:

  • Graphical modeling tools
  • External DSL creation tools
  • Code templating engines and code generators
  • Much more…

IMO, that is both the simplicity and genius of EMF.

~~LINKBACK~~ ~~DISCUSSION~~

2009/03/31 16:25

Declarative Data Binding using XScalaWT

This article builds upon the previous work showing how Scala can simplify SWT user interface development by introducing Declarative Databinding (DDB) for XScalaWT. DDB uses Eclipse / JFace Data Binding under the hood, and was designed with the following features in mind:

  • The API should follow–not hide–the underlying data binding API design
  • DDB will be implemented by applying common Scala idioms to reduce and/or eliminate Java syntax overhead
  • Code using DDB will more readily describe the programmer's intentions than the equivalent Java code (be more intentional)

Although XScalaWT's overall design is largely my own, DDB in particular owes a great debt to Shine, Andy Maleh's Glimmer data binding syntax. Thanks, Andy, for pushing the Eclipse community's data binding work farther than any of us imagined it could go and ultimately inspiring me to create XScalaWT with DDB.

Brief recap and Administrivia

(If you've read all my previous posts on this topic, you can make sure you have the latest nightly Scala Development Tool build and skip to the next section.)

In my previous posts Simplifying SWT with Scala and XScalaWT Stylesheets, I introduced the idea of using Scala to simplify one of the most painful parts of Eclipse RCP programming, user interface coding. We observed that the pain of SWT interface coding does not have to do with SWT so much as with the imperative style of coding. By creating a domain specific language (DSL) in Scala called XScalaWT that represents user interfaces declaratively rather than imperatively, we were able to eliminate all of the Java boilerplate code, leaving us with very simple, straightforward, intuitive code.

And for those who are not ready go jump ship from Java wholesale (ie: probably nearly all of us now), I started this series with the post, Using Scala to Create Eclipse RCP Applications, describing how to create mixed Scala and RCP applications.

One last administrative detail before we get started: Since I started this series I've gotten reports that the latest nightly Scala Eclipse builds are better than the latest stable build. I recently upgraded and have found this to be true.

A brief introduction to Eclipse Data Binding

Eclipse Data Binding (EDB), previously called JFace Data Binding, is a library that lets you describe how data flows from your business model objects to your user interface in an Eclipse application.

It works by providing a generic facade around observer pattern implementations, giving all observer patterns the exact same API. When all things that you can observe, IObservables if you will, have the same API, then you can hook a generic object called a Binding between them. This binding listens to change events on both sides. When a change is detected on one side, the new value is retrieved and copied to the other side.

For example, calling #addModifyListener on a Text widget requires a ModifyListener object. But detecting changes to a JavaBean bound property requires calling #addPropertyChangeListener and passing a PropertyChangeListener.

We can achieve a generic observer pattern API by wrapping the Text widget with a TextObservableValue (implementing the IObservableValue interface) and wrapping the JavaBean property with a JavaBeansObservableValue (also implementing the IObservableValue interface).

Observables on a pair of fields

Once we have this, we can then use a generic ValueBinding object (that knows how to synchronize arbitrary IObservableValue objects) to monitor both objects for changes and automatically keep them in sync.

Bind a single field

Java code to do this for one property looks something like the following:

Text firstName = new Text(parent, SWT.BORDER);
 
DataBindingContext bindingContext = new DataBindingContext();
bindingContext.bindValue(
    SWTObservables.observeText(firstName, SWT.Modify), 
    BeansObservables.observeValue(person, "firstName"),
    null, null);

This Java code is a whole lot better than the equivalent code that manually registers listeners and keeps these properties in sync.

The result is that you can create a whole user interface by repeating this pattern for each field that you want to bind.

Full binding of a simple user interface

In XScalaWT, we can certainly translate this code directly into Scala and include it in our layouts:

text (
  { txt =>
    val bindingContext = new DataBindingContext()
    bindingContext.bindValue(
      SWTObservables.observeText(txt),
      BeansObservables.observeValue(person, "firstName"), 
      null, null)
  }
)

Here, inside the node for the “text” object, we create an anonymous function that accepts as a parameter the actual Text widget that is created. Since we now have a reference to this Text widget, we can now use regular data binding API calls to bind it just like we did in Java.

But we will ask, as we have previously, “Can we do better?”

Implicitly Bindable

And in Scala, the answer is nearly always “Yes!”

Here is the same example, rewritten to use XScalaWT's data binding:

text (
  dataBindingContext(),
  _.textObservable <=> (person-->'firstName)
)

In the code above, the “⇔” operator is read “connects to” or “maps to” and is what calls bindingContext#bind(). The “_.textObservable” calls a method that we added to org.eclipse.swt.widgets.Text that returns an IObservableValue bound to the “text” property of the text object.

Generically then, XScalaWT adds four bits of syntactic sugar that greatly simplify binding:

  1. All SWT widgets have xxxObservable methods for each property “xxx” that can be observed. More formally, for every static method in the SWTObservables class of the form observeXxx(widget), XScalaWT adds a corresponding xxxObservable method to widget returning the same observable.
  2. Data binding contexts in XScalaWT are associated with a container. All objects inside that container inherit its data binding context. If you don't specify an explicit data binding context, XScalaWT will create a new one for each binding.
  3. The ⇔ operator along with a few bind() methods are added to the various IObservable subclasses.
  4. The –> operator is added to java.lang.Object, and directly returns a JavaBeansObservableValue bound to the property named by the parameter.

Note that these methods are only added to the corresponding receivers when XScalaWTBinding has been imported; these additions are then lexically scoped to the container performing the import.

A complete example

Now that we know how to bind controls in XScalaWT, we can present a fully-worked example using the Model-View-Presenter pattern. As Andy Maleh did in his Glimmer example, I will present a login dialog example in XScalaWT.

First, we need an SWT snippet that starts everything and prints out results:

object DataBindingMain {
  def main(args : Array[String]) = {
    val loginData = new LoginViewModel()
    val display = new Display()
    runWithDefaultRealm {
      val loginView = new LoginView(loginData)
      runEventLoop(loginView.createDialog())
    }
    println("Username:  " + loginData.username)
    println("Password:  " + loginData.password)
    println("Logged in: " + loginData.loggedIn)
  }
}

In this example, loginData is our presentation or view model. Naturally, LoginView is the View itself.

The only new things here are:

  • runEventLoop, which runs the SWT event loop on the specified Shell until the shell is disposed.
  • A convenience function “runWithDefaultRealm” that does the same thing as the following Java code:
Realm.runWithDefault(SWTObservables.getRealm(Display.getDefault()), new Runnable() {
  public void run() {
    // your code here...
  }
});

Our view model or presentation model is the following:

class LoginViewModel {
  @BeanProperty
  var username : String = "";
 
  @BeanProperty
  var password : String = "";
 
  var loggedIn = false
  def login() = { loggedIn = true }
}

Here the “@BeanProperty” annotations direct Scala to automatically generate Java setters and getters for the specified fields.

We also declare a stub login() method that will be called when the user wishes to log in.

The view itself can now be written as:

class LoginView(loginData : LoginViewModel) {
  def createDialog = {
    object loginStyles extends Stylesheet(
	  $[Control] (
	    setBackground(SWT.COLOR_WHITE)
	  )
	)
 
    val window = shell("Please log in",
      dataBindingContext(),
      group("User information",
        setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)),
        setLayout(new GridLayout(1, false)),
 
        label("Username"),
        text (
          setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)),
          _.textObservable <=> (loginData-->'username)  //'// Map Text-->text to loginData-->username
        ),
 
        label(""),
 
        label("Password"),
        *[Text](SWT.BORDER | SWT.PASSWORD) (     // The manual, "specify everything" syntax
          setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)),
          _.textObservable <=> (loginData-->'password)  //'// Map Text-->text to loginData-->password
        )
      ),
 
      // OK/Cancel buttons
      composite (
        setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)),
        setLayout(new GridLayout(2, true)),
 
        button("&OK", {e : SelectionEvent => loginData.login(); closeShell(e) }),
        button("&Cancel", {e : SelectionEvent => closeShell(e) })
      )
    )
    loginStyles.apply(window)
 
    window.pack
    val size = window.getSize()
    window.setSize(250, size.y)
 
    window
  }
 
  def closeShell(e : SelectionEvent) = e.widget.asInstanceOf[Control].getShell().close()
}

If you've been following this series, all of this code should be familiar by now. If the Scala syntax trips you up a bit, I highly recommend the book Programming Scala by Odersky et al.

Again, we notice that the various concerns are well-expressed with minimal line noise getting in the way of understanding what the code is doing. We also notice that except for the convention of mapping the data binding context to a container, XScalaWT's DDB syntax just simplifies data binding without hiding anything or adding anything magical on top of the Eclipse data binding API.

Conclusion

Scala has proven to be a useful library to use in Java projects for greatly simplifying user interface development. The resulting code is easier to read and more directly expresses the programmer's intentions.

Yep, the latest code is still available at http://bitbucket.org/djo/xscalawt/. :-)

~~LINKBACK~~ ~~DISCUSSION:closed~~

2009/03/21 22:23

The way forward for XSWT

Given all the discussion around modeled UI in the Eclipse E4 (Eclipse 4.0) space and my recent talk about XScalaWT, I received an email wondering aloud what will happen to XSWT (hosted here). Here's more or less what I wrote in response:

XSWT will graduate

XSWT is going to morph into something else as its ideas are adopted into E4. The result is that what we know today as XSWT is splitting into two development streams:

1) Its immediate successor will be whatever the E4 XML declarative UI language is. There are several proposals, all with excellent ideas.

The main intent with E4's XML UI language is to learn from previous projects (including XSWT) and to marry these former ideas to ideas that are new in the UI space, but proven elsewhere. Particularly, we're interested in bringing in ideas from Microsoft's XUL as well as the idea of a full formal model of the UI using EMF. The former provides better extensibility than XSWT had and the latter means that you won't have to implement fifteen (or so) extension points just to get an app running. It will be one model, the whole of which can be modeled directly in XML.

2) Its second immediate successor is XScalaWT, or declarative UI ideas married to an internal DSL written in Scala. As I have blogged recently, XScalaWT provides a safe, proven route for Java programmers to adopt Scala in a limited way in their Java RCP projects. Performance is better in XScalaWT, since XScalaWT isn't interpreted but compiles to regular Java class files. In addition, XScalaWT itself is more readable than XSWT or Java, has much simpler code to maintain (than the XML-based version), IDE tooling for free, and Scala-based scripting for free.

When eventually coupled with the Modeled UI ideas from E4, this ought to be even more powerful and expressive.

I've personally been working on #2. Hallvard, Yyves, Tom Schindl, and others are working on #1, and in my estimation, it's in very capable hands.

The migration path

If you have a graphic design team working with XSWT and you're using it to rigorously separate presentation from behavior and content, then you'll want to migrate to Eclipse's XML-based UI language. If you are using XSWT as a productivity tool for programmers, then I'd encourage you to look at XScalaWT, which is more expressive and more powerful. I've blogged about how to create mixed Scala/Java RCP projects.

So to directly answer your question, once Eclipse E4 chooses an XML description language, I will end-of-life XSWT and encourage everyone to migrate to Eclipse's XML UI implementation or to XScalaWT.

~~LINKBACK~~ ~~DISCUSSION~~

2009/03/09 23:03

<< Newer entries | Older entries >>

start.txt · Last modified: 2014/10/20 15:40 (external edit)