tag:blogger.com,1999:blog-48275504956669160222024-03-13T20:57:55.586-07:00Java FogyThoughts from an old developer with a penchant for young startupsJohnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.comBlogger15125tag:blogger.com,1999:blog-4827550495666916022.post-69746191278101853172013-12-03T12:30:00.003-08:002013-12-03T12:30:54.005-08:00From Zillow: iOS coding using Objective-C duck-typingWorking at <a href="http://zillow.com/jobs">Zillow</a>, I've had the opportunity to explore iOS and Objective-C. Please check out my first blog post there which describes a technique that enables <a href="http://engineering.zillow.com/specializing-cocoas-nsoutputstream-or-how-objc-duck-typing-saved-me-from-writing-redundant-code/">subclassing NSOutputStream</a> with reduced code by taking advantage Objective-C dynamic method (selector) resolution to give the effect of duck-typing.Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com1tag:blogger.com,1999:blog-4827550495666916022.post-70809770069183709032011-02-20T07:37:00.000-08:002011-02-25T18:49:01.429-08:00Automated Test for Facebook Canvas Apps – Front-end automation with Selenium<p>There are a number of challenges encountered in establishing test automation for Facebook applications. Among them is the fact that web browsers consider Facebook canvas applications to live in a separate security sandbox from the top-level page. This blog post describes how to use the <a href="http://seleniumhq.wordpress.com/2011/02/15/selenium-2-0b2-released/">Selenium 2.0 beta</a> WebDriver technology to automate integrated test scenarios where the application under test is embedded in the Facebook page. The same technique applies to other situations in which the test must interact with elements in an IFrame whose src is a different domain from the top-level page.</p><h2>Get the right driver</h2>Selenium 2.0 is in beta, and until Beta 2 was released (Feb 2011), the technique described here could only be used for Firefox. With Beta 2, one body of code works with both IE8 and Firefox 3.6 (at least). It's reasonable to hope that as Selenium 2 progresses to its final release, the same tests will be able to run with more browsers. The beta 2 release includes a driver for Chrome, but that driver is not able to execute the tests.<p></p><p>Selenium 2 merges WebDriver into the Selenium project. The tests here rely on the <a href="http://webdriver.googlecode.com/svn/javadoc/org/openqa/selenium/WebDriver.html">WebDriver API</a>.
</p><h2 id="fbIframe">Identify the IFrame</h2><p>In order to interact with the elements of your application, the test will need to get the IFrame name (or index). As of 25 Feb, 2011, the IFrame has a constant name:
</p><pre class="brush:groovy"> final def canvasName = "iframe_canvas"
</pre>The test could alternatively search through all IFrames in the window to locate the relevant item.
<p></p><h2 id="driver">Create a driver instance</h2>Selenium lets the test create a driver directly, i.e. <samp>new org.openqa.selenium.firefox.FirefoxDriver()</samp>. Writing the tests to use <samp>RemoteWebDriver</samp> allows the test framework to execute the test across platforms:
<pre class="brush:groovy">def seleniumDrivers = [
[browserName: "internet explorer", serverName: "windowshost:4444"],
[browserName: "firefox", serverName: "osxhost:4444"]
].collect {
def browserName = it.browserName
def driverCaps = new DesiredCapabilities()
driverCaps.javascriptEnabled = true
driverCaps.browserName = browserName
return new RemoteWebDriver(new URL("http://$it.serverName/wd/hub" as String), driverCaps)
}
</pre>The driver is required to enable JavaScript because it will allow the tests to probe Flash elements in the IFrame.<p></p><h2>Write tests</h2><p>It's not immediately apparent how to best encapsulate the aspects of the test setup where the driver is used to move through the initial flow required to start the application. For the moment, it's just one of the tests upon which the later tests depend.
</p><h3>Log in to Facebook</h3>Nothing tricky about this:
<pre class="brush:groovy">def login(WebDriver selenium) {
//Defines a trivial subclass of <a href="http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/support/ui/WebDriverWait.html">WebDriverWait</a>
def waitUntil = new GroovyWebDriverWait(new SystemClock(), selenium, 10, 50)
selenium.get("http://www.facebook.com")
// It seems to be a good idea to check that the field contains all typed characters before going to next test step
waitUntil.keysAccepted(selenium.findElement(By.name("email")), params.userEmail)
waitUntil.keysAccepted(selenium.findElement(By.name("pass")), params.userPassword)
// Click the Login button
selenium.findElement(By.xpath("//label/input")).click()
// Proceed only after Facebook displays the user's page
waitUntil.condition { selenium.findElement(By.id("navAccountLink")) }
}
</pre><h3>Load the app</h3>The test could drive the FB interface to locate the application in the UI and launch it from there, but if the objective is to test the workings of the app in the IFrame, send the browser directly to the application.
<pre class="brush:groovy">selenium.get(appURL)
// This is where the driver starts to interact with the application
selenium.switchTo().frame(canvasName)
</pre><h3>Wait for rendering</h3><p>The app probably has dynamically rendered elements. In particular if it uses SWFObject to initialize a Flash player the test should probe for the creation of the corresponding DOM element.
</p><pre class="brush:groovy">waitUntil.condition { selenium.findElement(By.id(swfElementId)) }</pre><p></p><h3>Interact with Flash</h3><p>If the test is concerned with a Flash application, it will need to make JavaScript calls into function exposed via the Flash ExternalInterface. A convenient way to make a number of useful test functions available is to include <a href="http://www.flexpilot.org/">FlexPilot</a>. It's (currently) necessary to build a SWF using the bootstrap classes provided with FlexPilot.</p><p>Assuming the SWF has successfully loaded FlexPilot, the test can proceed to check that the SWF loading is complete.
</p><pre class="brush:groovy">waitUntil.condition {
// The parameter to executeScript is really a script - if there's no return, there's nothing to check.
selenium.executeScript("return document.getElementById('$swfElementId').
fp_assertDisplayObject('$mainComponentName')")
}
</pre><p>That should give the general shape of the solution. Hopefully it'll be useful to some folks. Perhaps inspiration will strike once more and additional posts will elaborate on details. Please add a comment if you can suggest an improvement or idea for a following post.
</p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com28tag:blogger.com,1999:blog-4827550495666916022.post-50326276419587487432010-09-27T14:24:00.000-07:002010-10-02T09:34:09.928-07:00Using the Bigdoor API - first glanceThe API provided by <a href="http://bigdoor.com/">BigDoor</a> is quite robust, and the documentation is fairly complete, though it is lacking a diagram of the objects that the client needs to manipulate. Since there are at least 27 object types defined in the documentation, some perspective on the relationships among them would be beneficial. Here's a diagram showing relationships among the 10 objects that seem necessary to a minimal implementation.
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKDIkAKAOxobr_ebN9_9Z7QBa4eFwTsS9lDkyVMgUB_68nQO0MJbdk2rDWsIlOg-IMKuYK78TPhEvF6iBrKNSOnxqhJOyAsA8g-XoleuOHUtXN8AoaGbyj8oF6u00xHRjgwiLcbHk3Ijc/s1600/Core+BigDoor+Model+Elements.png"><img style="cursor: pointer; width: 400px; height: 163px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKDIkAKAOxobr_ebN9_9Z7QBa4eFwTsS9lDkyVMgUB_68nQO0MJbdk2rDWsIlOg-IMKuYK78TPhEvF6iBrKNSOnxqhJOyAsA8g-XoleuOHUtXN8AoaGbyj8oF6u00xHRjgwiLcbHk3Ijc/s400/Core+BigDoor+Model+Elements.png" alt="" id="BLOGGER_PHOTO_ID_5521746376754920194" border="0" /></a></p><p>
It seems that one could get started with the <code>Currency</code> and <code>Transaction</code> objects. When looking at the BigDoor API, it's helpful for me to translate some naming conventions. The key is to first remove 'Object' from the name, as every type in the system is termed an 'object'. At the next level there are types called <em>Named XXX</em>. If I read this as <em>XXX Descriptor</em>, it works better for the cases I'm working with. Alternatively, <em>XXX Protytype</em>, in the sense of a JavaScript prototype, might convey the relationship between these object templates and the instances that are created from them.
</p><p>I'm going to start with just one Currency and one Transaction. I created my currency on the Define Currencies page of the BigDoor <em>Economy</em> UI by using the 'Pre-fill suggested currencies' facility. That created 'Bucks', 'Coins' and 'Experience'. I'm not sure about the <em>Currency Type</em> attribute. I'm starting by using the 'Experience' currency with its default <em>Currency Type</em> of <em>Redeemable Hybrid Currency</em>. I imagine the <em>Dollar Exchange Rate</em> setting of '-1.00' indicates that it cannot be converted to USD. Yes, I did RTFM and it lists 4 <span style="font-style: italic;">Currency Types</span> while the UI provides 9 options and the description of exchange rate doesn't address the possibility of negative values. (In the real world, exchange rates are positive real numbers.) The response to my note to the BigDoor Sherpa revealed that the different types don't drive any behavior and the -1.00 was meant to designate currencies that don't 'convert', though conversion seems a bit nebulous just now. I didn't get a good answer as to why zero wouldn't be a clear indication that the currency is not convertible. It seems that there's some single reference currency against which each currency must be pegged. This makes me feel like <a href=http://en.wikipedia.org/wiki/Belize_dollar">Belize</a> or <a href-"http://en.wikipedia.org/wiki/Argentine_peso#Peso_Convertible.2C_1992.E2.80.93present">Argentina prior to its financial crisis of 2001</a> though my currency was assigned the same ID as the <a href="http://en.wikipedia.org/wiki/Serbian_dinar">Serbian Dinar</a>.
</p><p>I used the Define Transactions page to create a new object titled "Grant experience points" which references the 'Experience' currency with the Default Amount set to '5.00'.
</p><p>Now to see if I can use the API to initiate the transaction for a user. It's useful to note at this stage that the <cite>End User</cite> object is created as a side-effect of the first transaction in which a previously unknown user id is specified.</p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com0tag:blogger.com,1999:blog-4827550495666916022.post-25401261193096294282009-11-16T09:25:00.000-08:002009-11-16T10:14:56.503-08:00Gonzo Camp II: Writing Ruby<p>
Thanks to <a href='http://www.linkedin.com/in/markbriggs'>Mark Briggs</a>, the <a href='http://gonzocamp.com'>Gonzo Camp II</a> event was well-run and very informative. The event brought together a variety of experts, practitioners and students of journalism. Mark's guidance and inspiration created a fertile environment for the development of a <a href='http://www.techflash.com/seattle/2009/11/gonzocamp_features_the_entrepreneurial_side_of_journalism.html'>variety of entrepreneurial ideas for journalism</a>.
</p><p>
This camp was less productive in terms of running code demonstrated than the inaugural event, probably because a large fraction of the coders who signed up didn't attend. The poor internet connectivity was also an impediment – the prototype that I developed could have had more functions if I'd been able to test faster and download more code to integrate. Still, it was surprising that I was on the only team (out of 5) to demonstrate a working prototype.
</p><p>
The prototype I built for our team implemented a low-cost paywall targeting community news outlets. It implemented a basic HTTP gateway. I built it by extending <a href='http://mongrel.rubyforge.org/'>Mongrel</a> and adding an entry to my local hosts file to simulate a DNS entry. The result was a paywall erected for <a href='http://www.lodinews.com'>lodinews.com</a> that allowed viewing of the paper's home page without registration, required confirmation to view any local news article, and allowed unfettered access to AP articles.
</p><p>
It was disappointing that I didn't get to see how others would approach building a prototype within 3-4 hours. On the other hand, it was very interesting to learn about the ideas that were developed with the influence of students and young journalists.
</p><p>
Thanks to Mark's organization and the event sponsors, there were plentiful tasty refreshments, nutritious lunch and a bountiful after-party. Gonzo Camp was definitely a valuable experience.
</p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com2tag:blogger.com,1999:blog-4827550495666916022.post-44313486537019665712009-09-14T02:51:00.002-07:002009-09-14T23:33:59.177-07:00Bahn.de is awesome!<p>
I've appreciated the clean bahn.de website and its complete and accurate railway itinerary creation ever since I first used it in 2003. The site continues to impress with additions of comparative travel charts like this one:
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdf_XnlYMuPVfXH8wRevMNx758mYfmcKJpTkndvatwkan2d3fDKolW6a9CmSTs_M0gHnPg718IOwLBQoIbrkUTDAeD__foDA32nMf8aSf7iUKM3OjiQmro8dfvVPsLqwisEa0Q2kg2xcI/s1600-h/bahn.de.png"><img style="cursor: pointer; float:center" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdf_XnlYMuPVfXH8wRevMNx758mYfmcKJpTkndvatwkan2d3fDKolW6a9CmSTs_M0gHnPg718IOwLBQoIbrkUTDAeD__foDA32nMf8aSf7iUKM3OjiQmro8dfvVPsLqwisEa0Q2kg2xcI/s320/bahn.de.png" alt="Bahn.de comparative energy consumption graph" id="BLOGGER_PHOTO_ID_5381304104727316226" border="0" /></a>
</p><p>
It's pretty cool to see how much less impact travel by rail will be compared to a car or airline.
</p>
While I'm sure more rigorous users have some complaints, the <a href="http://bahn.de/">bahn.de</a> service seems much more helpful in getting around Europe than anything else. I must also observe there are no such comprehensive travel solutions for planning a trip in the US. Then again, the only comparable options for transportation in the US are bus and airline – train travel is only possible in certain areas.
</p><p>
In Europe, reservations are only available from the national carriers, so only certain itineraries can be reserved from the Bahn.de website. On the other hand, since I'm traveling with a Eurail pass, it would be necessary for me to make the reservations in person anyway. (It would be nice if the Eurail pass could develop a website for pass holders to make reservations, but I'm sure that's more easily said than done.)
<p></p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com0tag:blogger.com,1999:blog-4827550495666916022.post-33322096813586867492009-09-01T16:01:00.000-07:002009-09-02T07:18:59.906-07:00Eclipse update sites for XText incubation<P>
I've been fumbling around a bit trying to get XText 0.7.2 working in my Eclipse 3.5 installations, so I thought it might be helpful to write down what I've found.
</p><p>
There are 3 update sites that were needed in order to complete the update today.
<ol><li>
MWE SDK from <a href='http://download.eclipse.org/modeling/emft/updates/releases/'>EMFT→ http://download.eclipse.org/modeling/emft/updates/releases/</a>
</li><li>
The Xtext plugin from <a href='http://download.eclipse.org/modeling/tmf/updates/'>TMF→ http://download.eclipse.org/modeling/tmf/updates/</a>
</li><li>
The Xtext ANTLR Support plugin (0.7.2) from <a href='http://download.itemis.com/updates/'>Itemis→ http://download.itemis.com/updates/</a>
</li></ol>
The last is optional, though there are warnings that the capability is limited without ANTLR. It is omitted due to the requirement for EPL in Eclipse projects; ANTLR's current license prevents it from being offered from the Eclipse.org update sites. These all appear in the <a href='http://ekkescorner.wordpress.com/eclipse/update-sites/'>list of Eclipse update sites on ekkes-corner</a>.
</p><p>
The <a href='http://download.itemis.com/updates'> Itemis update site</a> provides a convenient collection of all the related modeling plugins. I turns out that my difficulty resulted from the fact that I didn't realize p2 (Eclipse Provisioning Platform) wasn't loading the current contents of the update site, so I started to search for update sites that had the 0.7.2 release of the plugins. What I learned is that I can get the current contents of the update sites by opening the Install/Update Preferences and invoking 'Test Connection' on each. Perhaps there's a better way...
</p><p>
Hopefully not too many others will encounter the difficulty I had finding the right versions, particularly for MWE.
</p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com3tag:blogger.com,1999:blog-4827550495666916022.post-69794084450632136282009-08-01T10:57:00.001-07:002009-08-11T19:08:04.635-07:00Groovy Eclipse Plugin alpha zero-day review<P>
In a multi-language project, Eclipse is a crucial tool for a number of reasons that might be apparent to readers of other posts here. One of the languages that is important in this particular project is Groovy. Until the end of July 2009, the <a href='http://groovy.codehaus.org/Eclipse+Plugin'>Groovy Eclipse plugin</a> was a rather cursory integration that was generally effective in getting Groovy projects to build together with other Eclipse projects, but didn't provide a full set of IDE capability for Groovy.
</p><p>
Great news arrived as July ended: the alpha for <a href='http://groovy.codehaus.org/Eclipse+Plugin+V2+FAQ'>V2 of the Groovy eclipse plugin</a> was published for Eclipse 3.5. (The website is currently only referring to Eclipse 3.4.2 support, but there's also a <a href='http://dist.codehaus.org/groovy/distributions/greclipse/snapshot/e3.5'>Groovy Eclipse update site for Eclipse 3.5</a>.) After a few hours of exploration, a few bugs and areas needing polish are apparent, but these are so far no more of an impediment than the issues encountered with the old dev-release plugin for Groovy 1.6 (the previous Groovy 1.5 plugin was a bit more useable than 1.6, but not so much as to prevent migration to the newer version).
</p><p>
The basic functions at this stage of the V2 development will be very relevant to this project: the integration of Java with core Groovy is exactly the level of capability at the foundation of the plug-in. Grails developers may not find as much relevance until the plug-in gets more features. Pure Groovy developers might have a more robust IDE than Eclipse. But the support for multiple languages – C, Java & Groovy in this case – makes Eclipse a uniquely comprehensive and extensible solution.
</p><p>
This new plugin offers many more IDE features than previously available, though they remain more basic that the features in Eclipse Java (JDT) environment.
<ul><li>
The outline view is much improved.
</li><li>
Performance is snappy – no observable delays while editing.
</li><li>
Compile errors handled properly – previously, java-level errors like missing implementation of abstract method would only appear after a save. Tests would launch and run against the old code, causing consternation if one didn't watch the Problems view.
</li></ul>
</p><p>
The biggest downside of installing this plugin so far is the appearance of warnings when using Java generic types in Groovy. While adding the type specifiers to Map and Collection might not be a bad thing, there seem to be a few problems – with the result one may end up specifying <samp><Object></samp> where a more specific type would be accurate and correct in Java. A few editor glitches appear sporadically, though they're not yet pervasive enough to warrant a bug report.
</p><p>
This is an important milestone for Eclipse & Groovy. The team at <a href='http://www.springsource.com/'>SpringSource</a>, particularly Andy Clement and <a href='http://contraptionsforprogramming.blogspot.com/'>Andrew Eisenberg</a>, have done a great job with this alpha release of a promising V2 product!
</p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com1tag:blogger.com,1999:blog-4827550495666916022.post-9874497463497239612009-07-21T16:12:00.001-07:002009-07-23T10:30:20.596-07:00Xtext Linking one step at a time<p>
The <a href='http://www.eclipse.org/Xtext'>Eclipse environment with Xtext</a> provides an astoundingly powerful toolset. The EMF/TMF folks are doing a great job providing good capabilities with straightforward means of tailoring and extension. That said, there's a lot to the environment that can make some tasks appear more daunting than need be.
</p><p>
After reading <a href='http://blog.efftinge.de/2009/07/xtext-scopes-and-emf-index-in-action.html'>Sven Efftinge's post on an experimental Xtext feature that automates linking among models in a project</a>, I was definitely inclined to make use of it. On the other hand, it's a solution much bigger than the problem that I currently face: linking to references within the same model (program, actually) while assuming that references without a local definition are external.
</p><p>
My grammar allows references to imported constructs in a manner similar to Java's implied import of all class names that reside in the same package. The approach in Sven's article on integrating with the EMF index will ultimately be implemented if time allows in this project. Presently, I don't want the parser to actually load all the models partly because the main goal is to analyze individual models and the actual content of imported models is extraneous.
</p><p>
The simple way keep errors from being flagged where implicit imports can't be resolved is to extend the <samp>DefaultLinkingService</samp>. To start with, the <samp>ILinkingService</samp> binding has be be replaced by adding an override in the Language<samp>RuntimeModule</samp> class in the main parser project's <src> directory:
<pre class='brush:java'>
public Class<? extends ILinkingService> bindILinkingService() {
return PdlLinkingService.class;
}
</pre>
</p><p>
The custom linking service is a minimal extension of <samp>DefaultLinkingService</samp>. Thanks to <a href='http://zarnekow.blogspot.com/'>Sebastian</a> for guidance on optimizing the integration to Xtext. <a href='http://www.linkedin.com/pub/knut-wannheden/1/40/a98'>Knut</a>'s pointers for dealing with the ECore resources was crucial to implementing a proper solution. Here's the complete class (I'm sure there's still room for improvement):
<pre class='brush:java'>
/**
* Provide the linking semantics for PDL. The references to 'imported' table
* definitions are stubbed out by this class until the Indexer is implemented.
*
* @author John Bito
*/
public class PdlLinkingService extends DefaultLinkingService {
private PdlFactory factoryInstance = null;
/**
* Keep stubs so that new ones aren't created for each linking pass.
*/
private final Map<String, PhysicalFileName> stubbedRefs;
private Resource stubsResource = null;
public PdlLinkingService() {
super();
stubbedRefs = new Hashtable<String, PhysicalFileName>();
}
/**
* Retrieve the factory for model elements
*
* @return the factory for the model defined by the language
*/
private PdlFactory getFactory() {
if (null == factoryInstance)
factoryInstance = PdlPackage.eINSTANCE.getPdlFactory();
return factoryInstance;
}
/**
* Use a temporary 'child' resource to hold created stubs. The real resource
* URI is used to generate a 'temporary' resource to be the container for
* stub EObjects.
*
* @param source
* the real resource that is being parsed
* @return the cached reference to a resource named by the real resource
* with the added extension 'xmi'
*/
private Resource makeResource(Resource source) {
if (null != stubsResource)
return stubsResource;
URI stubURI = source.getURI();
stubURI = stubURI.appendFileExtension("xmi");
stubsResource = source.getResourceSet().getResource(stubURI, false);
if (null == stubsResource)
// TODO find out if this should be cleaned up so as not to clutter
// the project.
source.getResourceSet().createResource(stubURI);
return stubsResource;
}
/**
* Override default in order to supply a stub object. If the default
* implementation isn't able to resolve the link, assume it to be a local
* resource.
*
* @param context
* the model element containing the reference
* @param ref
* the reference defining the type that must be resolved
* @param node
* the parse tree node containing the text of the reference (ID)
* @return the default implementation's return if non-empty or else an
* internally-generated PhysicalFileName
* @throws IllegalNodeException
* if detected by the default implementation
* @see org.eclipse.xtext.linking.impl.DefaultLinkingService#getLinkedObjects(org.eclipse.emf.ecore.EObject,
* org.eclipse.emf.ecore.EReference,
* org.eclipse.xtext.parsetree.AbstractNode)
*/
@Override
public List<EObject> getLinkedObjects(EObject context, EReference ref,
AbstractNode node) throws IllegalNodeException {
List<EObject> result = super.getLinkedObjects(context, ref, node);
// If the default implementation resolved the link, return it
if (null != result && !result.isEmpty())
return result;
// Is this a reference to be stubbed?
if (PdlPackage.Literals.FILE_NAME
.isSuperTypeOf(ref.getEReferenceType())) {
// Get the stub's name from the text of the parse tree node.
String name = getCrossRefNodeAsString(node);
FileName stub = stubbedRefs.get(name);
if (null == stub) {
// Create the model element instance using the factory
stub = getFactory().createPhysicalFileName();
stub.setName(name);
// Attach the stub to the resource that's being parsed
makeResource(context.eResource()).getContents().add(stub);
}
result = Collections.singletonList((EObject) stub);
}
return result;
}
}
</pre>
</p><p>
Of course, this is a stop-gap that's not appropriate for complete language processing, but it's illustrative of one simple way semantics may be adjusted within the Xtext framework. There are two likely problems making this implementation sub-optimal:
<ul>
<li>
The 'temporary' resource lifetime isn't managed, so the local cache of <samp>EObject</samp> references can be out of sync. Intuitively, one would expect the resource to exist longer than the <samp>LinkingService</samp>, so it will be surprising to find the <samp>LinkingService</samp> using a reference to an <samp>EObject</samp> that's not stored in the resource.
</li><li>
Since the code doesn't try to find <samp>EObject</samp> instances that are already in the resource, there can be a memory leak if the <samp>LinkingService</samp> is created multiple times during a session. It may make sense to use the <samp>delete</samp> method on the <samp>Resource</samp>, but it looks a bit dangerous and I don't have the wherewithal to test that at the moment.
</li>
</ul>
I searched a bit for examples of code managing <samp>ECore</samp> resources; my search terms weren't very fruitful. Pointers would be greatly appreciated.
</p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com1tag:blogger.com,1999:blog-4827550495666916022.post-17243226770544894362009-07-11T11:09:00.000-07:002009-07-13T07:40:48.688-07:00Embedding Java in a C language application<p>The Java Native Interface is a powerful API that allows Java to call native libraries and also allows native executables to invoke Java (or any JVM-based) classes.
</p><p>
An <a href='http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-14.html'>important addition to the Java Native Interface in Java 1.4</a> was support for <samp>java.nio.ByteBuffer</samp> parameters. This allows the native code (C in my case) to efficiently share data with classes running in the JVM. Often, when C code is invoking Java methods, it has to create objects, particularly <samp>String</samp>s, to pass to the methods. While this provides some safety to the Java side, it has some performance implications.
</p><p>
With Java 1.4, we have the option to pass data across the JNI in a single buffer shared by the C and Java code referenced by a <samp>java.nio.ByteBuffer</samp>. The use of this technique comes with many caveats, particularly if the application runs multiple threads. The ideal application for this approach is when a fixed-size message with an unvarying or self-defining format is passed across the interface. The performance advantage comes because both the C and Java code can change the data, so the ByteBuffer object only has to be created once. The C code can change the data in the buffer and pass the same ByteBuffer object to multiple method invocations and then make use of changes the Java code makes to the buffer contents.
<pre class='brush:c'>
JNIEnv *jni = get_jniEnv();
jclass cls = getClassRef();
jmethodID getdata_mid = getMethodID(DATA_LOADER);
static jobject jbuff = NULL;
static char *databuff = NULL;
if (!databuff)
if (databuff = malloc(cbuff))
memset(databuff, '\0', cbuff);
if (jni && !jbuff && databuff)
jbuff = (*jni)->NewDirectByteBuffer(jni, databuff, cbuff);
if (!(jni && cls && getdata_mid && jbuff))
//quit unless all references are available
return NULL;
(*jni)->CallStaticVoidMethod(jni, cls, getdata_mid, jbuff);
if (check_exception())
return NULL;
return databuff;
</pre>
The code above assumes that all the work to initialize the JVM, load the class and lookup the method is handled elsewhere. The caller can examine and change the data retrieved by the Java code. It can then modify the contents of the buffer returned and call the function again; then Java code can use the changes made in buffer between the calls. This saves object creation and destruction as well as the time copying data from one buffer to another.
</p><p>
On the Java side, there are some limitations on the use of the <samp>ByteBuffer</samp>. It's not backed by an <samp>Array</samp> object, so some of the operations declared by the abstract class are unsupported when the object is created by the C code.
</p>
<h2>JRE Internal Error – "exception happened outside interpreter, nmethods and vtable stubs (1)"?!</h2>
<p>When calling Java via JNI, there's no checking of the method parameters. As a result, if your code passes parameters that don't match the method signature in a <samp>Call...Method</samp> JNI call, the JVM will likely panic and terminate with a message like "exception happened outside interpreter, nmethods and vtable stubs (1)" if you're lucky (and your JVM is at least 1.6). If you're really lucky, the JVM will write an error log that includes a stack trace pointing to the C code that made the JNI call.
</p><p>
Unfortunately, the 'Internal Error' reported by the JVM is really a generic panic message, so it's also likely to result from more insidious problems like your code writing into the Java heap. In that case you could try <a href='http://valgrind.org/'>valgrind</a> or similar tool to track down stray memory usage, but I can't say whether it'll work when calling into the JNI.
</p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com3tag:blogger.com,1999:blog-4827550495666916022.post-70419699563401207122009-07-07T15:15:00.001-07:002009-07-12T19:39:47.085-07:00Adding function to Xtext-generated plugins<p>
The Xtext parser generator is generating much more than a parser—otherwise ANTLR by itself would be a simpler solution. As noted in my post on <a href='http://jwbito.ballardview.com/2009/07/migrating-from-oaw-xtext-to-eclipse-tmf.html'>migrating the Xtext grammar</a>, just by deploying the plugins generated by Xtext, a basic outline is provided while editing the defined language.
</p><p>
For my analyzer, I have to add checks that flag errors for programs that contain multiple definitions for certain types of structures. The legacy language allows a single name to be associated with multiple, different structure definitions as the program executes, but part of the upgrade will cause this to be illegal, so it's the job of the static analyzer (parser) to detect this case so the programmers don't have to search out and test each program manually.
</p><p>
The <a href='http://www.eclipse.org/Xtext/documentation/0_7_0/xtext.html#validation'>Xtext manual section on Validation includes Custom Validation</a> describes the classes involved in implementing validations for the language. In order to get the Xtext customization framework for validation, add
<pre class='brush:xml'>
<fragment class="org.eclipse.xtext.generator.validation.JavaValidatorFragment"/>
</pre>
to the <samp>Generate</samp>LanguageName<samp>.mwe</samp> file in the parser project. Unfortunately, the Java-based checks are not so easy to write as the oAW Check language. One of the nice things about oAW was the content assist—the editor for Check knows the AST model and makes it easy to write checks that work. There's another fragment to add to the MWE file in order to get the Check capability:
<pre class='brush:xml'>
<fragment class="org.eclipse.xtext.generator.validation.CheckFragment"/>
</pre>
Since the TMF Xtext plugins don't seem to include a Check editor with content assist, it's actually more convenient to write the validations in Java. Referring to the LanguageName<samp>.ecore</samp> file in the visual editor (should open when you double-click the ecore file) makes it pretty easy to see the types and their features when working on validations.
</p><p>
I just needed to add two validations (so far). The Java is pretty small, but it took me a little while to get comfortable with the CST classes.
<pre class='brush:java'>
/**
* Issue warning if the View object is using the dynamic resolution syntax
* @param view object to be validated
*/
@Check
public void checkViewNotDynamic(View view) {
if (null != view.getDynamic())
warning("View defined with dynamic target", PdlPackage.VIEW__DYNAMIC );
}
/**
* Issue error if there there exist multiple Join objects identified by the same name
* @param join one of the Join objects in the current ProcessDefinition
*/
@Check
public void checkJoinUnique(final Join join) {
final String name = join.getName(); // This name must not be used to identify any other Join object
// Now loop on all the other elements that are in the ProcessDefintion
for (EObject sibling : ((ProcessDefinition) join.eContainer()).getCommands()) {
// Check for another object instance that's a Join with the same name as the one being validated
if (join != sibling && sibling instanceof Join && name.equals(((Join) sibling).getName()))
error("duplicate join '" + name + "'", PdlPackage.JOIN__NAME);
}
}
</pre>
These two validators are picked up by the Xtext framework and invoked by the editor and the generator. The warnings and errors show up in the editor as well as the Package Explorer, Problems and other views.
</p><p>
With the parser doing the right thing, I copied the <a href='http://wiki.eclipse.org/Xpand_New_And_Noteworthy'>Xpand</a> template that I wrote under oAW into the generator project as <samp>templates/Template.xpt</samp>. The <samp>workflow/</samp>LanguageName<samp>Generator.mwe</samp> had a problem—it got a NoClassDefFoundError because it specified a class name in the <samp>register</samp> element with an initial lowercase letter. I don't know if that was because of something I did or a bug in the project wizard. Changing the MWE file was all that was needed to test the template. It's the same as oAW, which is to say it's a convenient way to traverse the CST and emit code.
<pre class='brush:plain'>
«DEFINE main FOR ProcessDefinition»
«FILE "test"»
«EXPAND viewDef FOREACH commands.typeSelect(View)»
«EXPAND joinDef FOREACH commands.typeSelect(Join)»
«ENDFILE»
«ENDDEFINE»
//In the output file, there will be one line for each instance of Join
//Within the tempate, the properties of the instance are accessed like
//local variables.
«DEFINE joinDef FOR Join »
// Pay no attention to the man behind the curtain named «name»
«ENDDEFINE»
«DEFINE viewDef FOR View »
«IF null!=name && null!=source -» «REM» Generate mappings for statically-defined views «ENDREM»
views["«name.toUpperCase()»"] = joins.createView("«source.toUpperCase()»");
«ENDIF -»
«ENDDEFINE»
</pre>
You'll notice that the template language uses guillemets to enclose the executable instructions. To make sure that you read all of the documentation, the authors only tell you that the characters are bound to CTRL-< and CTRL-> at the end. The Xpand editor was pretty nice to use in oAW. I haven't tried it yet in TMF, partly because it wasn't installed. I'm not quite sure how I got the runtime plugin for Xpand installed—perhaps p2 resolved a dependency. I'm pretty sure that once I install the Xpand UI from the <a href='http://download.eclipse.org/modeling/m2t/updates/releases/'>M2T Xpand update site</a>, I'll get the content assist that I used when I was originally developing the template.
</p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com5tag:blogger.com,1999:blog-4827550495666916022.post-7384107420211860612009-07-07T08:51:00.000-07:002009-07-13T07:52:47.482-07:00The Software Life: Antlr Frustrations<p>Andrew McKinlay's post <a href="http://thesoftwarelife.blogspot.com/2008/07/antlr-frustrations.html"><em>The Software Life: Antlr Frustrations</em> on "no start rule" warnings</a> gives a succinct explanation of a problem that can be somewhat evasive.
The ANTLR warning "no start rule (no rule can obviously be followed by EOF)" may come and go as other issues with the grammar are resolved. One answer is to always start the grammar with a rule like:
<pre class='brush:plain'>
prog : expr ;
</pre>
The <samp>prog</samp> rule doesn't change anything about the language that can be parsed. It can be used as an entry point by the code calling the parser, like an interface that can be stable even as the grammar changes underneath.</p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com1tag:blogger.com,1999:blog-4827550495666916022.post-40024282645899861792009-07-03T11:56:00.000-07:002009-07-07T14:36:32.354-07:00Migrating from oAW XText to Eclipse TMF XText<p>Part of my project is analyzing the structure of programs processed by the interpreter that I'm working to enhance. Xtext and the related tools from oAW allowed me to define a subset of the language for analysis and code generation. As there's a need for more function (and hopefully more speed), it's great that a new Xtext is available for Eclipse Galileo.
</p><p>
The <a href='http://www.eclipse.org/Xtext/documentation/0_7_0/xtext.html#from_oaw_to_tmf'>reference for Xtext includes a section on changes from oAW to TMF</a> that's quite informative, but doesn't include any advice on how to change the existing Eclipse projects. That's in the <a href='http://wiki.eclipse.org/Xtext/Documentation/Migration'>Eclipsepedia wiki section on Xtext Migration</a>.
</p><p>
The guide is a bit ominous-sounding when it talks about specifying the language name in the Xtext project wizard. Since the previous name for my package wasn't very good, and there is very little extension work in the previous project—the main purpose is the generator—the approach for the moment is to copy the text into the shells created by the project wizard. The wizard doesn't give much advice about the naming, but the editor complains if the last element of the language name is lowercase.
</p><p>
In the old oAW system, the plugin added a context menu named 'generate Xtext artifacts'. This doesn't appear anymore. Since I'm building my eclipse configuration from the 'Classic SDK', it's necessary to install the <a href='http://www.eclipse.org/modeling/emft/?project=mwe'>Modeling Workflow Engine (MWE)</a> separately. The MWE is required to run the workflow <samp>Generate</samp>LanguageName<samp>.mwe</samp> in the parser project.
</p><p>
As the documentation says, unlike oAW, TMF Xtext doesn't enable parser backtracking by default. I was able to restructure the grammar rules to get rid of many of the <samp>warning(200)</samp> … <samp>Decision can match input such as</samp> "'whatever'" <samp>using multiple alternatives</samp> messages. (These aren't really warnings, since the resulting parser is ignoring portions of the grammar that I'm specifying). In the end, I found that there is a construct in the legacy language accepted by its recursive interpreter that's indeterminate. So I <a href='http://www.eclipse.org/newsportal/article.php?id=1240&group=eclipse.modeling.tmf'>modified the Xtext MWE file as recommended by Sebastian Zarnekow</a> to replace <samp>AntlrDelegatingFragment</samp> with <samp>XtextAntlrGeneratorFragment</samp> and
<samp>DelegatingGeneratorFragment</samp> with <samp>XtextAntlrUiGeneratorFragment</samp> adding the child <samp><options backtrack="true"/></samp> element to each (don't remove the <samp>JavaBasedContentAssistFragment</samp>). I wonder if Xtext provides (or will provide) a way to enable backtracking for a subset of the grammar rules.
</p><p>
Once the Grammar was compiling again, I was able to check it out quickly by following the steps suggested in the <a href='http://www.peterfriese.de/getting-started-with-xtext/'>Getting Started with Xtext post by Peter Friese</a>. Invoking 'Run As → Eclipse Application' from the context menu of the parser project brings up a new IDE in a separate, initially empty, workspace. From there, create a new project and within that a new file with the extension named in the Xtext Wizard. Copying an existing program populated the outline view—a vast improvement over oAW which ate all the heap so the outline had to be disabled. One caveat: with the generated plugin configured, the editor is sure to fail with an NPE if you open a file named with the extension associated with your editor outside of a project (using File → Open).
</p><p>
Now, on to working with linkages in the AST!
</p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com0tag:blogger.com,1999:blog-4827550495666916022.post-10322078431831876552009-07-02T11:34:00.000-07:002009-07-02T11:51:55.666-07:00Jevopi's Developer Blog: User Report: Migrate from oAW Xtext to TMF Xtext<strong><a href="http://jevopisdeveloperblog.blogspot.com/2009/07/user-report-migrate-from-oaw-xtext-to.html">Jevopi's Developer Blog: User Report: Migrate from oAW Xtext to TMF Xtext</a></strong>
<p>
Just starting to work on the conversion of the Xtext grammar and code generator to the new technology developed by TMF. My case is a bit different as the language definition is for an existing general-purpose programming language. The current scope of the processing is limited to analyzing and extracting specific constructs in the language.
</p><p>
It's nice that Javopi provided such a thorough explanation of the process required to migrate that language processor from <a href='http://www.openarchitectureware.org/pub/documentation/4.2/html/contents/xtext_reference.html'>oAW XText</a> to the <a href='http://www.eclipse.org/Xtext/'>Eclipse TMF XText</a>. I'll be working on some additional details like analyzing cross references and code generation.
</p><p>
<em>More posts to come.</em>
</p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com0tag:blogger.com,1999:blog-4827550495666916022.post-58675470843158877882009-06-22T17:34:00.000-07:002009-07-01T09:17:46.619-07:00Unit test framework for legacy C application code<p>Adding a bunch of function to a big application (a 4GL) that was developed long ago and over the course of 10 years (1987 - 1997) is a risky business. Particularly when the only extant testing code is written in the 4GL – equivalent to only being able to test an HTML browser by getting it to process HTML.</p><p>I've certainly learned a lot since I took on my first product development job. One of the practices I'm still learning is good unit testing. I've learned to think in terms of the <a href="http://junit.org/">JUnit unit testing framework</a>. Such a framework is important to focus the testing code on testing instead of housekeeping and to define standard reports. There are several <a href="http://www.opensourcetesting.org/unit_c.php">unit testing frameworks for C listed on OpenSourceTesting.org</a>.</p><p>The following list contains the subset of the test frameworks that I've considered for my project. As noted below, I've picked up the Cgreen framework with good results.
</p><dl><dt><a href="http://www.boost.org/doc/libs/1_39_0/libs/test/index.html">Boost.Test</a>
</dt><dd>This framework is in active use, but it's primarily used for C++ applications. The API looks simple enough that it could be reasonably used to test C functions.
</dd><dt>C Unit Test System</dt><dd>Defunct project – there's a note on the sourceforge project forum from 2003 asking if there are any users.
</dd><dt><a href="http://www.lastcraft.com/cgreen_suites.php">Cgreen</a></dt><dd>Unit testing strictly for C with a facility for mocking functions.</dd>
<dt>C Unit</dt><dd>Abandoned project. No response to inquiries or code updates since 2006.</dd>
<dt><a href="http://cutest.sourceforge.net/">CuTest</a></dt><dd>A very simple implementation of unit test framework. Some activity on the project. No documentation found.</dd><dt>RCUNIT</dt><dd>Abandoned project. No activity since 0.9 in 2006</dd><dt>Simple C Test</dt><dd>Abandoned project. No activity since 2005. Some documentation is provided.</dd><dt>Test soon</dt><dd>Abandoned project. No activity since 2007. Seems to focus on flexibility to structure tests and not so much on enabling easy authoring.</dd><dt><a href="http://tut-framework.sourceforge.net/">TUT test framework</a></dt><dd>Interesting framework in C++ compiled into each test suite. Not clear how failures should be detected, not designed to automatically recover from faults (SEGV) so further test cases can run.</dd><dt>unit--</dt><dd>Abandoned project. No activity since 2006.</dd><dt><a href="http://sourceforge.net/projects/embunity/">Unity</a> & <a href="http://sourceforge.net/apps/trac/cmock/wiki">CMock</a></dt><dd>Nice looking unit test and mock tools for C targeting embedded systems developers. Cmock requires Ruby and Rake.</dd></dl><p>
The other tools listed were apparently only for C++ or objective C.
</p><p>
After some examination and experimentation, the Cgreen package seems to be the best fit. The mock function capability is a useful stand-in for the <a href="http://en.wikipedia.org/wiki/Mock_object">mock objects</a> one would use for an object-oriented environment.
</p>
<p></p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com0tag:blogger.com,1999:blog-4827550495666916022.post-7482980364769733222009-06-22T13:32:00.000-07:002009-06-22T14:18:28.071-07:00Updating the logging code with log4c<p>Having been delighted at my introduction to log4j in 2001, I was anxious to find a flexible <a href="http://en.wikipedia.org/wiki/Logging_Tool">logging</a> and <a href="http://en.wikipedia.org/wiki/Tracing_%28software%29">tracing</a> framework suitable for introduction in the C program I'm updating. All the Google searches I tried produced results that pointed at Java, Python or PHP tools. I'd begun to despair and was thinking about putting something together on my own. It was <a href="http://en.wikipedia.org/wiki/Log4J">Wikipedia's Log4J</a> that finally pointed me to the <a href="http://en.wikipedia.org/wiki/Log4c">Log4c logging and tracing framework</a>.
</p><p>
I'm still working on getting it fully integrated, but <a href="http://sourceforge.net/project/platformdownload.php?group_id=38627">the Log4c download</a> was easy to compile on <a href="http://www.sun.com/software/solaris/10/index.jsp">Sun's Solaris 10</a> (binaries for Linux are provided). One thing to note is that the CVS repository only has sources for automake, so the installation instructions are a couple steps removed.
</p><p>
It's not so easy to find documentation, though some effort seems to have gone into preparing some. The links for documentation go to a SourceForge site that yields an entry saying 1.0.0 with no content. I was eventually able to find a good <a href="http://www.slideshare.net/gzm55/log4-c-developers-guide-presentation">guide to the use of Log4C on slideshare</a>.
</p><p>
I haven't tried all the options, yet, but Log4C provides an elegant API that looks like it will be quite efficient. It will allow logging and tracing calls to be added with little impact on the application. It also promises to support generating <a href="http://en.wikipedia.org/wiki/Syslog">syslog</a> entries and rolling log files.
</p>Johnhttp://www.blogger.com/profile/10743270318149221614noreply@blogger.com0