I created a blog post “Behavior counts for improved JUnit tests” on my other blog. It shows a possible technique to assure that JUnit tests are robust and are really testing what you think they are testing.
Groovy script to bootstrap a Gradle Project
March 8, 2012I took Ted Naleid’s “Quick Shell Function to Bootstrap a Gradle Groovy Project” example code and converted it to a Groovy script.
Listing 1.
// NewGradle.groovy
// Author: Josef Betancourt
// Based on T. Naleid's shell script
println "Creating files for new Gradle project ..."
new File(".gitignore").withPrintWriter{ w ->
"*.un~,*.iml,*.ipr,*.iws,build,.gradle".split(",").each{
w.println(it)
}
}
new File("build.gradle") << ="""\
apply plugin: 'groovy'
apply plugin: 'idea'
apply plugin: 'eclipse'
repositories {
mavenCentral()
}
dependencies {
groovy 'org.codehaus.groovy:groovy:1.8.6'
compile 'org.apache.ivy:ivy:2.2.0'
}
task createSourceDirs(description :
'Create empty source directories for all defined sourceSets')
<< {
sourceSets*.allSource.srcDirs.flatten().each {
File sourceDirectory ->
if (!sourceDirectory.exists()) {
println "Making \$sourceDirectory"
sourceDirectory.mkdirs()
}
}
}
idea {
project {
jdkName = '1.6'
}
}
""" // end content
"cmd /c gradle createSourceDirs".execute()
"cmd /c git init".execute()
Thread.start{
sleep 5000 // allow time for all files to be created
new File(".").eachFile{
println it
}
}
Not expert Groovy, but was easy to do. The bulk of it is the creation of a “here” doc using Groovy’s triple quote string. I didn’t duplicate the last line of Naleid’s script: “ls -a1 && find src # list all created assets”.
This script is not fully cross-platform. The invocation of shell commands at the end are in the Windows format. Left as an exercise to reader is the use of inline AntBuilder to reuse Ant’s exec task.
Updates
2012-03-09: Tweaked the source. Removed use of two temp variables.
2012-03-09: Added the Eclipse plugin. Now after creating the Gradle project executing eclipse will create the eclipse project: gradle eclipse
Or instead generate the Idea project: gradle idea.
Further Reading
- Groovy (Programming language)
- Groovy
- Gradle
- Quick Shell Function to Bootstrap a Gradle Groovy Project
- Strings and GString
- Groovy JDK extensions
- Executing External Processes
- Using Gradle to Bootstrap your Legacy Ant Builds
Off Topic
Test Coverage Using JMockit
January 21, 2012The JMockit Unit Testing library continues to astound. One new thing I discovered is its Coverage reporting.
Code Coverage
Code coverage is simply a measurement of what code has been actually run when tests are executed. There are many such measures, ramifications, and tools. Like testing itself, code coverage measurement is probably not done enough, or misused.
“Code coverage tells you what you definitely haven’t tested, not what you have.” — Mark Simpson in comment
Path Coverage
Plenty of coverage reporting tools out there. What this one also includes is Path coverage. This is different then branch coverage. Paths are possible execution paths from entry points to exit points. If you visualize a methods statements in a directed graph, paths are a enumeration of the possible edges traversed when that method is invoked. So, Path coverages is inclusive of Branch coverage. Well, I’m not a testing expert, so this may be way off.
Very surprising results. For example, you run a coverage report with a tool such as Cobertura or Emma and feel very happy that you exercised every line and branch with your tests. Then you run the same tests but use JMockit Coverage and discover your tests didn’t cover all the paths! Not only that your line coverage wasn’t so great either.
Report
JMockit explicitly gives you a report showing:
Path
Measures how many of the possible execution paths through method/constructor bodies were actually executed by tests.
The percentages are calculated as 100*NPE/NP, where NP is the number of possible paths and NPE the number of fully executed paths.Line
Measures how much of the executable production code was exercised by tests. An executable line of code contains one or more executable segments.
The percentages are calculated as 100*NE/NS, where NS is the number of segments and NE the number of executed segments.Data
Measures how many of the instance and static non-final fields were fully exercised by the test run. To be fully exercised, a field must have the last value assigned to it read by at least one test. The percentages are calculated as 100*NFE/NF, where NF is the number of non-final fields and NFE the number of fully exercised fields.– from the JMockit coverage report HTML page
Other information is found by using the full HTML output option.
Example
A sample JMockit coverage report is here. Of course you can drill down into various parts of the html page. Like when you click on an exercised line you will get a list of what invoked that line.
Worth it?
Are the metrics such as Path coverage that this tool generates accurate? Is JMockit coverage a replacement for other tools such as Cobertura? I don’t know. For most projects, the resources would probably make the use of coverages generated by multiple tools prohibitive.
Evaluation
One possible approach to evaluating coverage tools is to just use actual real results of the target application. Use the list of bugs and correlate to a coverage tool report. Where were the bugs? Which tool gave the least measure for this location?
Further Reading
- Pitfalls of code coverage
- Measuring line and path coverage with JMockit Coverage
- What’s the point of basis path coverage?
- Basis-Testing
- Code coverage tools in Java
- Statement, Branch, and Path Coverage Testing in Java
- FLOWGRAPHS AND PATH TESTING
- What is Wrong with Statement Coverage
- Easy code coverage reports with JMockIt
- Unit Test Code Coverage
- Planning for JMockit 2
Eliades Ochoa – Siboney
Testing getter/setter using JUnit
November 19, 2011So, I was thinking of testing my getter and setters in a JUnit test. Yea, I know it is not recommended, but I thought that I could write a simple reflective iterator that could do it without much fuss.
What I show below is that maybe getter/setters should be tested, especially in Java which really does not have “real” properties. Further, by investigating a potential solution, I show that it doesn’t work, and the reason is that testing IS hard to do.
Anyway, just to save time, and not have to code this, I did a quick search and found that this has been done many times before. So I looked at one of the solutions, Scott’s. Very nicely done! With one line you can test a class’s property getters and setters. Then I noticed a problem.
In his approach he invokes the setter and then the getter, finally comparing that the values are the same. For example, if the property is a boolean, the test class will set it true, then read it and the value better be true. However, what if the value prior to your set was true, the object is initialized with true for the field value?
For example, I took a class and set field x to true via the default constructor, then I modified the setX method to not set the field value.
public class Fubar {
private boolean launch = true;
public void getLaunch(){
return this.launch;
}
public void setLaunch(boolean launch){
/* this.launch = launch; */ // broken!
}
}
Code at: git clone git://gist.github.com/1408493.git gist-1408493
In the unit test the getLaunch method still returned true. The getter/setter test did not fail; the test was bogus. Not only that, the fact that the setLaunch method did not work illustrates that sometimes testing setters is warranted.
Thus, the version of the program that controls the sports strategy will ship and the boolean that aborts a play cannot be set to false! (Edited, removed joke about war stuff; you can’t be too careful with all the craziness in the world).
In a recent presentation I gave on unit testing, I said that testing could be difficult. This is a great example of this. In this case, one should have followed analogous patterns in other fields. Thus, from semiconductor testing, for example, you would test gates by not just writing a 1 bit, you have to write 1 and 0 to make sure the gate is working.
Updates
Feb 11, 2012: I’m using Scott’s solution in our test suite. I did modify the code a bit. Turns out that a JavaBean property is not so clear cut. If you have a getter and setter method pair but no actual target field, are those Javabean methods? Looks like the Java bean introspector will report these as bean accessors. Hmm.
Further Reading
- Behavior counters for improved JUnit tests
- Duplicate of this blog post: Testing getter/setter using JUnit
- Should unit tests be written for getter and setters?
- Is there a Java unit-test framework that auto-tests getters and setters?
- Do You Unit Test Getters and Setters?
- Google search
Bill Evans Trio – Nardis – 19 Mar 65 (7 of 11)
Article on Bill Evans: http://www.chuckisraels.com/articleevans.htm
JMockit
November 19, 2011Yesterday at work I gave a presentation on Unit Testing. It went well. 160 slides! And, no one passed out and hit the floor.
One thing I mentioned was mocking frameworks and how JMockit is very useful. Perhaps JMockIt represents the state of the art in Java based Mocking tools.
There are plenty of good reasons for using mocks:
JMockit is ” a collection of tools and APIs for use in developer testing, that is, tests written by developers using a testing framework such as JUnit or TestNG.”
I’ve used it for some tests. Since it uses Java instrumentation it can mock almost anything, especially those legacy untestable great OO classes. Best of all it has a very good tutorial.
The only ‘negative’, so far, is that JMockit does not, afaik, have many developers working on the project. That could also be a plus, of course.
Another mock tool is PowerMock.
Seems to me there are too many mock frameworks and they do pretty much the same things. Time for consolidation so that an API and a body of practice can shake out?
Further reading
-
Duplicate of this post on new blog: JMockit
- Mock object
- MockingToolkitComparisonMatrix
- Beyond EasyMock and JMock, try JMockIt !
- The Difference Between Mocks and Stubs
- The JMockit Testing Toolkit
- The Concept of Mocking
- PowerMock
- Unit Testing Using Mocks – Testing Techniques 5
- Making a mockery of CQ5 with JMockit
Off topic, some music …
Stefano Cantini – Blowin in the wind
Exception verification using fault injection via AOP
November 13, 2011A simple example is used to show how to use Aspect Oriented Programming to provide fault injection.
Intro
A few months ago I was looking at Java code and thinking there must be a better way to see if this will really work, if there are any issues in how the program would react to exceptional conditions. I could write some unit tests or force some problems to see if the exception handling is correct and the log file output is really useful. But is there another way?
I got a solution after a while of thinking: Insert faults. Now how to do that in an easy and maintainable way? Not a new idea of course. After doing a web search I found some interesting references.
Funny, today at work I was extending an application and one of the support objects was failing. Turned out to be an index out of bounds problem. The method had adequate exception handling but, of course, an index out of bounds scenario was not tested. In this case the problem would not occur in production (hmmm), but it definitely occurred during development, and was not handled correctly.
Exception Handling
There are many references of correct exception handling strategies and best practices. However, when creating applications, the developer must still make critical creative decisions about how to handle an exception. That decision may not be a wise one. And even if it is, may later prove to have been very unwise since the system requirements and implementation may have changed due to maintenance or requirement evolution.
Testing Approaches
Using various testing methodologies a subsystem can be exhaustively tested for exception handling. Yet, most testing methods require that the subsystems be isolated in some manner. This, though very valuable, can give fatal false confidence that the system will behave in a predictable manner in responding to exceptional conditions.
The prime example of this is within the Unit Testing methodologies. Since Unit Tests are tests of isolated components, they do not test actual exception handling in the live system. A perfect component can still contribute to system failure when it is used incorrectly or uses other components incorrectly. For example, a unit test can show that class X’s methods correctly handle and when necessary throw the perfect exception. That means nothing if components that interact with X don’t correctly use those exceptions: they swallow, mask, or mistakenly catch them when there is nothing they can do.
Thus, one needs to use Integration Testing to test assemblages of components. But, we are still back with the same shortcoming as with Unit Testing. Thus we would next need various forms of system testing. And, that system testing must be a White Box test. A Black Box test wherein an interface is exercised with various inputs (such as in web test systems or by QA personnel), will not necessarily invoke the full internal API/SPI between components that could be part of a complicated call chain. Why? Because, the interface, such as a browser client, will have (we hope) the validation, security, and logging layers implemented so that by the time a system test workflow enters the deep system components within the client or middleware, there is no way to influence the target component state into programmatic intentional failure mode.
If there is no way to exercise a run time trajectory, then why bother? The reason is that exceptional conditions are exceptional. Resources can be exhausted, systems not available, and so forth. The rule of Fail Fast may not be enough if collaborating components are not exceptionally responsive.
Fault Injection
To see if a system is responding to exceptional conditions, one must wait for those conditions or create them. Analogously to Fuzz Testing we can dynamically and randomly insert faults. In Fuzz Testing, inputs are manipulated to a system under test. In Fault Injection we have to manipulate inputs inside the real system, within the components themselves. And as in Fuzz Testing, we can employ various strategies to do so, such as randomized faults, etc. Of course, this system is not the deployed production system, it is the real system in a test environment, an internal full deployment.
Some approaches are: source modification, source macros, annotations, dependency injection (IOC), and Aspect Oriented Programming (AOP). Of course, there are many other techniques as found in open/closed projects, commercial products, and the research community.
Fault Injection using AOP
Since using the real system is required, a viable approach is to use the Instrumentation already available in the Java system. We could dynamically insert code that forces exceptions. AOP as implemented by the AspectJ language can already do this.
The major advantage of using AOP is that the source is not changed in any way. AspectJ is the state of the art in the Java ecosystem for using AOP.
Other approaches
Monitoring
BTrace (a Java oriented approach comparable to DTrace) is very interesting. However, since, like DTrace, it is meant to be safe, defect injection may not be doable. But, see this post on an unsafe mode for BTrace.
Source modification
One way of injecting failure is just to edit the source code and add strategic code that will cause the instigating failure. An advanced form of this is Mutation Testing. Code changes could be: arguments with wrong values, nulls, deliberately thrown exceptions, etc. For example, one can simply create a method that throws a runtime exception:
*** DON'T DO THIS ***
public static void REMOVE_XXX_FROM_XXX_SOURCE(){
if(true){
throw new NullPointerException(
"\n\t****** DELIBERATE RUNTIME EXCEPTION*****\n");
}
}
Then insert invocations to this method at strategic points in the code, deploy to a test environment, and see if the expected results are obtained, such as logging output that can identify the cause, or that no side effects are recorded, such as incorrect data storage.
This is a low tech and error prone approach. Most importantly, this is dangerous. In the mad development rush to meet deadlines and also eat lunch, this code could make it into production! Even with that horrific method name, it will wind up in production! One would have to create deployment filters that stop the process if any “fault” inducing code is included. Another reason why this is not a good approach is that it doesn’t scale very well. Forcing exceptions is just one type of verification. Another is setting values outside of expected ranges or states. Thus, one would need many different kinds of source code insertions.
Of course, Unit and Behavior based testing tools sets can supply these required verifications if included into the system as Built-In Self-Tests (BIST).
Built-In Self-Test
In the hardware realm, BIST as found in, for example, IEEE 1149.1 JTAG, has been very successful. On the software side, there is ongoing research on how to implement BIST-like capability. This would make Brad Cox’s concept of the “Software IC” even more powerful.
Macros
A somewhat viable approach to source code fault insertion is instead of inserting the faulting code, insert “include” macros in the original source code that indicates what fault insertion should be done at a location. A fault injection preprocessor can scan and insert the fault framework’s invocations to accomplish the requirement. The source code build process can then simply enable or disable the use of the preprocessor. This would however still require source code modification and an extra maintenance nightmare. When the code changes the macros may also require change.
Annotations
Instead of macros, we could also use Annotations. Annotations could explicitly state the runtime exceptional behavior “service level agreements” at the component level. These SLA could then be systematically manipulated to test if they really hold at the system level.
Dependency Injection
One can also inject exceptional behavior by dependency injection, using programmatic, declarative, or annotations, faulted components could be inserted (or created via Aspect Oriented Programming) into the target system.
AOP Demonstration
In listing one below, an ATM class uses a service to do some banking.
/**
* Driver class for example.
* For a real system see: https://bitbucket.org/aragost/javahg/
* @author jbetancourt
*/
public class ATM {
private BankService service = new BankService(1000);
/**
* Perform a banking action.
*/
public void transaction(){
{
service.deposit(100L);
service.withdraw(200L);
}
service.statement();
}
/** Application entry point */
public static void main(String[] args) {
new ATM().transaction();
}
}
Listing two is the BankService being used. Of course, a real service would be more complex.
/**
* Example service.
*/
public class BankService {
// Use Long to allow example's null for failure
// injection.
private BigDecimal balance;
public BankService(long savings){
this.balance = new BigDecimal(savings);
}
/** */
public void deposit(Long amount){
balance = balance.add(new BigDecimal(amount));
System.out.println("Deposit: " + amount);
}
/** */
public void withdraw(Long amount){
balance = balance.subtract(new BigDecimal(amount));
System.out.println("Withdraw: " + amount);
}
/** */
public void statement() {
System.out.println("Balance: " + balance);
}
} // end BankService
A example Non-faulted execution result is:
Report: pointcut usage
withdrawCut: true -> false
depositCut: false -> false
Deposit: 100
Withdraw: 200
Savings: 900
When we run the demo program we get:
Exception at the withdraw method.
Report: pointcut usage withdrawCut: true -> true depositCut: false -> false Deposit: 100 Exception in thread "main" java.lang.NullPointerException at BankService.withdraw_aroundBody2(BankService.java:15 at BankService.withdraw_aroundBody3$advice(BankService.java:81) at BankService.withdraw(BankService.java:1) at Main.main(Main.java:16)
Exception at the deposit method.
Report: pointcut usage withdrawCut: true -> false depositCut: false -> true Exception in thread "main" java.lang.NullPointerException at BankService.deposit_aroundBody0(BankService.java:9) at BankService.deposit_aroundBody1$advice(BankService.java:81) at BankService.deposit(BankService.java:1) at Main.main(Main.java:15)
All pointcuts enabled.
Report: pointcut usagewithdrawCut: true -> true depositCut: false -> true Exception in thread "main" java.lang.NullPointerException at BankService.deposit_aroundBody0(BankService.java:9) at BankService.deposit_aroundBody1$advice(BankService.java:81) at BankService.deposit(BankService.java:1) at Main.main(Main.java:15)
Implementation
Now to test the exceptional behavior we want to fault the deposit and withdraw methods.
First we have a way of specifying what we want to fault by using a JSON configuration file:
{
"__comments":[
"File: properties.json"
],
"settings":{
"random":true
},
"cuts":{
"depositCut":false,
"withdrawCut":true
}
}
The “cuts” settings indicate which AspectJ “pointcut” to turn on. The “random” setting indicates if we want the exceptions to be randomly inserted into the code base at the enabled pointcuts.
The Abstract failure injection aspect. Subclasses (aspects) will supply the actual pointcuts to specify where to ‘do’ the injection.
/**
* FailureInjectionAspect.aj
* @author jbetancourt
*
*/
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Abstract Aspect that determines if failure should occur.
* @author jbetancourt
*
*/
public abstract aspect FailureInjectionAspect {
private Map<String, Boolean> pointcutFlags = new HashMap<String, Boolean>();
private volatile boolean initialized =false;
/**
* Initialize Failure injection aspect.
* @throws Exception
*
*/
protected void init() throws Exception {
Config config = new Config();
config.configure();
pointcutFlags = config.getPointcutFlags();
initialized = true;
}
/**
* Get boolean value for pointcut name.
*
* @param name pointcut name.
* @return true if pointcut enabled.
* @throws IOException
*/
protected boolean isPointcutEnabled(String name) {
if(!initialized){
try {
init();
} catch (Exception e) {
throw new IllegalStateException(
"Could not initialize object",e);
}
}
boolean f = false;
Object val = pointcutFlags.get(name);
if (null != val) {
f = ((Boolean) val).booleanValue();
}
return f;
}
} // end FailureInjectionAspect.aj
Here is a aspect that uses a nulling type of injection.
/**
*
* Example of an aspect for nulling an argument to a method.
* @author jbetancourt
*
*/
public aspect AmountFailureAspect extends FailureInjectionAspect {
/** fault the deposit */
private pointcut depositCut(Long amount) :
execution(public void BankService.deposit(Long))
&& if(AmountFailureAspect.aspectOf().isPointcutEnabled("depositCut"))
&& args(amount)
&& !within(FailureInjectionAspect)
;
/** fault the withdrawal */
private pointcut withdrawCut(Long amount) :
execution(public void BankService.withdraw(Long))
&& if(AmountFailureAspect.aspectOf().isPointcutEnabled("withdrawCut"))
&& args(amount)
&& !within(FailureInjectionAspect)
;
/** Null the amount arg */
void around(Long amount) : depositCut(amount)|| withdrawCut(amount) {
amount = null;
proceed(amount);
}
}
Here is how to read the configuation JSON file. I use the JSON-Simple library.
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
/**
*
* @author jbetancourt
*
*/
public class Config {
private static final Logger logger =
Logger.getLogger(Config.class.getName());
private String configFile = "\\src\\properties.json";
private Map<String, Boolean> pointcutFlags = new HashMap<String, Boolean>();
private volatile boolean initialized = false;
private String basePath;
/**
*
* @param configFile2
* @throws Exception
*/
@SuppressWarnings("unchecked")
public void configure() throws Exception {
basePath = new File(".").getAbsolutePath();
String path = basePath + configFile;
Object obj = (JSONObject) JSONValue
.parse(new FileReader(new File(path)));
Map<String, Map<String, ?>> map = (Map<String, Map<String, ?>>) obj;
pointcutFlags = (Map<String, Boolean>) map.get("cuts");
Map<String, Object> settings = (Map<String, Object>) map
.get("settings");
Object r = settings.get("random");
boolean randomize = (r != null && ((Boolean)r)) ;
if(randomize){
println(String.format(
"Pointcut usage\n%16s %6s %6s","Name ",
"Prior","Current"));
for(Map.Entry<String, Boolean>entry : pointcutFlags.entrySet()){
Boolean prior = entry.getValue();
Boolean f = Math.random() > 0.65;
entry.setValue(f);
println(String.format(
"%15s: %6s -> %6s", entry.getKey(),prior,f));
}
println("\n");
}
saveConfig();
initialized = true;
logger.log(Level.INFO,"Initialized: " + initialized);
}
/**
* Write the config settings to external JSON file.
*
* Format is: { cutname : boolean , ... }
* Example: {"withdrawCut":true,"depositCut":true}
* Will be used to set up behavior analysis service to
* monitor response.
*
* @throws IOException
*/
protected void saveConfig() throws IOException{
String json = JSONValue.toJSONString(pointcutFlags);
File file = new File(basePath + "\\runtimeProperties.json");
FileWriter writer = new FileWriter(file);
writer.append(json);
writer.close();
}
/** getter */
public Map<String, Boolean> getPointcutFlags() {
return pointcutFlags;
}
/** setter */
public void setPointcutFlags(Map<String, Boolean> cutFlags) {
this.pointcutFlags = cutFlags;
}
/**
* Just a shortcut to System.out.println(String).
* @param s
*/
private void println(String s){
System.out.println(s);
}
}
Running at the command line
Using AspectJ is much easier in a supporting IDE like Eclipse. Below is the “mess”, unless you love the CLI, of compiling and running in a command shell. Could be made clean by creating aliases, scripts, etc.
cd src src>javac -d ..\bin -cp ..\jars\json-simple-1.1.jar *.java src>java -cp ..\bin Main Jun 9, 2011 3:18:24 PM Main main INFO: Starting Main..... Deposit: 100 Withdraw: 200 Balance: 900
Now we change the flag from false to true in the runtimeInjection.json file:
src>type runtimeInjection.json | sed "s/false/true/" > temp src>copy /Y temp runtimeInjection.json src>del temp
Compile the aspects using the Aspectj “ajc” compiler. Here we use 1.6 compliance level; destination of output to ..\bin folder; and give the classpath.
c:\Users\jbetancourt\Documents\projects\dev\AspectsForNullTesting\src>\java\aspectj1.6\bin\ajc -1.6 -d ..\bin -cp "c:\java\aspectj1.6\lib\aspectjrt. jar;c:\java\aspectj1.6\lib\aspectjtools.jar;c:\java\aspectj1.6\lib\aspectjweaver.jar;..\jars\json-simple-1.1.jar" -sourceroots .
Now we run the same Main program. Since the pointcut flag is true, the advise is invoked and the list argument to the service(List) is set to null.
c:\Users\jbetancourt\Documents\projects\dev\AspectsForNullTesting>java -cp "c:\java\aspectj1.6\lib\aspectjrt.jar;c:\java\aspectj1.6\lib\aspectjtools .jar;c:\java\aspectj1.6\lib\aspectjweaver.jar;jars\json-simple-1.1.jar;bin;." Main Jun 9, 2011 3:25:04 PM Main main INFO: Starting Main..... Pointcut usage Name Prior Current withdrawCut: true -> false depositCut: false -> false c:\Users\jbetancourt\Documents\projects\dev\AspectsForNullTesting>java -cp "c:\java\aspectj1.6\lib\aspectjrt.jar;c:\java\aspectj1.6\lib\aspectjtools .jar;c:\java\aspectj1.6\lib\aspectjweaver.jar;jars\json-simple-1.1.jar;bin;." Main Jun 9, 2011 3:25:10 PM Main main INFO: Starting Main..... Pointcut usage Name Prior Current withdrawCut: true -> true depositCut: false -> true Jun 9, 2011 3:25:10 PM Config exec INFO: Initialized: true Exception in thread "main" java.lang.NullPointerException at BankService.deposit_aroundBody0(BankService.java:19) at BankService.deposit_aroundBody1$advice(BankService.java:26) at BankService.deposit(BankService.java:1) at Main.main(Main.java:16) c:\Users\jbetancourt\Documents\projects\dev\AspectsForNullTesting>java -cp "c:\java\aspectj1.6\lib\aspectjrt.jar;c:\java\aspectj1.6\lib\aspectjtools .jar;c:\java\aspectj1.6\lib\aspectjweaver.jar;jars\json-simple-1.1.jar;bin;." Main Jun 9, 2011 3:25:13 PM Main main INFO: Starting Main..... Pointcut usage Name Prior Current withdrawCut: true -> true depositCut: false -> false Jun 9, 2011 3:25:13 PM Config exec INFO: Initialized: true Deposit: 100 Exception in thread "main" java.lang.NullPointerException at BankService.withdraw_aroundBody2(BankService.java:25) at BankService.withdraw_aroundBody3$advice(BankService.java:26) at BankService.withdraw(BankService.java:1) at Main.main(Main.java:17)
Updates
- Feb 1, 2012: Just learned about Byteman.
Further Reading
- Byteman
- BIST for Analog Weenies
- http://en.wikipedia.org/wiki/Fault_injection
- AOP and fault injection
- BTrace == DTrace for Java; http://blog.igorminar.com/2008/06/btrace-dtrace-for-java.html
- DTrace Knockoffs
- http://stackoverflow.com/questions/372589/automated-exception-handling
- Built-In Self-Test
- http://www.sohar.com/proj_pub/download/A_Systems_Engineering_Approach_to_ExptHndl.pdf
- http://joshgertzen.com/bypassing-java-checked-exception-verification/
- http://www.google.com/search?q=verification+exception+handling
- Effective Java NullPointerException Handling
- “Safe Construction Techniques”, Brian Goetz, http://www.ibm.com/developerworks/java/library/j-jtp0618/index.html
- Using Fault Injection to Increase Software Test Coverage
- “code injection, error throwing and handling mobile debugging“.
- BTrace
- Compiling Conditional Pointcuts for User-Level Semantic Pointcuts
- Test-based pointcuts: a robust pointcut mechanism based on unit test cases for software evolution
- “Towards Reliable Cloud Storage“; H. Gunawi; UC Berkeley. Accessed at cloudseminar.berkeley.edu/data/fatedestini.pptx
- Context-Aware Exception Handling in Mobile Agent Systems: The MoCA Case
- Towards Automatic Exception safety Verification
Nicolas Lens – Sumus Vicinae (Flamma Flamma)
Java’s HTTP Server for browser-based Groovy app
April 10, 2011Code illustrating use of the HTTP server included in Java JDK 1.6. via Groovy to present a browser-based UI to an app.
Result
The code allows this usage:
main.SimpleServer.serve(0){ s, t, p ->
// handle the request, response here...
// now shut down,
s.stopServer()
}
Listing 1, How it’s used.
This will create a web server using the host “localhost” at an unused port p, and then automatically open the default browser at “http://localhost:p/”. The closure will be the application. Neat. Of course, you would only use this behind a firewall, etc.
The above code, as a I later discovered, is very similar to other frameworks. Here is a new one I just learned about:
vertx.createHttpServer().requestHandler { req ->
def file = req.uri == "/" ? "index.html" : req.uri
req.response.sendFile "webroot/$file"
}.listen(8080)
A sample session running the example code and using telnet is:
telnet localhost 21224 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. GET /?reply=24 HTTP/1.1 HTTP/1.1 200 OK Content-length: 15</pre> <h1>Wrong!</h1> <pre>Connection closed by foreign host.
The Eclipse console contains:
+++++++ Simple Server ++++++++++++++++++ uri: [/?reply=24] protocol: [HTTP/1.1] query: [reply=24] path: [/] params: [[reply:[24]]] ------------------------- Stopping server ... stopped!
The browser will show:
Scenario
You have to supply a GUI for running a local Java application. One example could be the setup of a product build. Builds, though usually executed with Ant, Maven, or Gradle, may still require the user to select some target parameters or build type. Why not just use the browser? It can present a more modern interface and with good design, allow more fault tolerant use then that with command line or multiple prompt boxes.
This approach also allows future remote build server use, since the designed browser UI can be reused. The browser is ubiquitous and creating web pages is relatively easy (though can be a hair pulling nightmare sometimes). And, with the use of AJAX and high-level frameworks, like Dojo or JQuery, browser clients can more easily duplicate the usability of dedicated thick client apps. HTML5 (see HTML5 Rocks) is also helping to obliterate any remaining reasons for using a thick-client app.
An embedded server as used here, is great when the task is ad hoc, short lived, or single user. In the provided example, once the input is received the server shuts down. For more complex or ubiquitous use a standard server or more powerful embedded server should be used.
Embedded Server
For a local application that accesses system resources and uses the browser as the UI, using an embedded server is the simplest approach. Pure Javascript, Applets, and other means are very complex and may run against configuration issues with Browser security settings and so forth. In the Java world, that would mean using the more popular Tomcat or Jetty servers.
However, Java 1.6 now includes a light-weight HTTP Server. So, the configuration and requirements are more tractable. Nothing more to download and programmatic configuration concerns are minor. Note that the Java HTTP server does not offer many features, one augments this with custom code. For example, parsing of the request query is not present.
That the package of this server is com.sun… is problematic. Will it stay around, become part of the javax packages, etc? Should the JDK even have this built in? According to this post by M. MacMahone
… is that the API and implementation are a fully supported, publicly accessible component of Sun’s implementation of Java SE 6. It does mean however, that the packages are not formally part of the Java SE platform, and are therefore not guaranteed to be available on all other (non Sun) implementations of Java SE 6.
Incidentally, the Groovy language has an import system, Grape, that can also make use of Tomcat or Jetty as transparently as using the JDK embedded server. See the Further Reading below for an example using Groovlets.
This code illustrates
(more for my future reference)
The list below was some of the things the code used and the final code listed here may no longer have them.
- com.sun.net.httpserver API use.
- Using JQuery in external js files.
- How to stop the server.
- With AJAX post
- Timeout
- HTTP context
- Using ScheduledExecutorService to limit runtime.
- A console ASCII spinner.
- Groovy GString use.
- Launching the default browser.
- Selecting an unused port.
- Simplistic state machine configuration.
- Detecting Java version.
- AJAX using JQuery.
- Groovy object construction from script.
- Use of Closure.
- Basic authentication
- Quasi Anonymous class use in Groovy
- access to resources
Of course, not great example of the above, but … Warning, code is not production ready, etc. There is no real exception handling!
How it works.
TODO: Give some idea what all that code does.
The index.html creates a simple form with three buttons (submit, ping, and end), an input field, and a ‘console’ output area.
- submit: send the answer to the server which then gives feedback, correct or wrong. The server then deliberately shuts down.
- ping: sends an AJAX request to the ping context which just sends back the time, the response is appended to the console.
- end: sends an AJAX request to the ‘stop’ context. The server responds with ‘stopping server …’, then shuts down. All buttons are disabled.
Why Groovy
Groovy is a dynamic JVM based language whose most prominent feature is that it extends the Java syntax to be more usable, i.e., less wordy,. From the example, a method that prints the contents of a map can be defined as:
def showInfo(info){info.each{ k,v -> println "$k = $v" }}
Then invoked as:
showInfo(uri:uri,protocol:protocol,query:query,path:path)
The Groovy In Action book is pretty thorough. Chapter 1 makes a good case, and may still be available here.
Why not Groovy? Well, being dynamic can be rough, especially if it impacts the ability of a IDE to offer the features that come from using Java, like completions, etc. The Eclipse plug-in is getting much better, and I read the IntelliJ IDEA groovy support is top-notch. But, the worlds most popular language, JavaScript, is dynamic, and it hasn’t bothered too many people (maybe end users?).
Source
When I first wrote this, I created a complicated “app” with a bunch of class files and so forth. Then I simplified it. Later I said, yuck. Finally I decided that this should just be a simple one method invocation as shown at the beginning of this post. Consequently, a bunch of stuff in this sample code is guarded by conditionals and it works but sure can be simplified.
While coding I ran into a strange classloader issue see this post. There are a few files in this demo
- SimpleServer.groovy: provides the ‘facade’ to HTTPServer. Handles the “/” context.
- AppContext.groovy: An example of an “app” that gets mapped to a context path.
- server.properties: Externalizes some properties.
- index.html: The initial app interface.
- scripts.js: The JQuery AJAX button handlers
- stylesheet.css: Stylesheet, just to show that the code can load it.
- TestServe.groovy: An example of just using the serve method. Not really a test.
The source code can be downloaded at: here
Listing 4. TestServe.groovy (not a unit test, btw)
//import static main.SimpleServer as SS; // still won't work!!! GROOVY-4386
import com.sun.net.httpserver.HttpExchange;
import main.SimpleServer
main.SimpleServer.serve(0){
ss, t, params ->
if(!(params.size())){
def path = t.getRequestURI().getRawPath()
if(path.length()>1){
ss.sendPage(t,path)
}else if(path =="/") {
ss.sendPage(t,"/src/index.html")
}
}else{
def answer = params.get("reply")
reply = (!answer || answer[0] != '"42"') ? "Wrong!" : "Correct!"
ss.sendString(t,"</pre>
<h1>$reply</h1>
<pre>")
ss.stopServer()
}
}
/**
* File: SimpleServer.groovy
* Date: 20110314T2125-05:00
* Author: jbetancourt
*/
package main
import java.io.IOException;
import java.io.OutputStream;
import java.net.Authenticator;
import java.nio.channels.*
import java.nio.*
import java.text.SimpleDateFormat
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit as TU;
import java.util.zip.*;
import com.sun.net.httpserver.Authenticator;
import com.sun.net.httpserver.Authenticator.*;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.BasicAuthenticator;
import java.util.concurrent.ScheduledExecutorService;
import org.codehaus.groovy.reflection.ReflectionUtils
import edu.stanford.ejalbert.BrowserLauncher;
/**
* Example of using the Java 1.6 HTTP server com.sun.net.httpserver.
*
* @see "http://download.oracle.com/javase/6/docs/jre/api/net/httpserver/
* spec/com/sun/net/httpserver/package-summary.html"
*
* Version 0.02
*
* @author jbetancourt
*/
class SimpleServer implements HttpHandler{
static final STOP_WAIT = 2
static final HOST = "localhost"
static final HTTP_PROTOCOL = "http://"
static final splashText = " Embedded Java 1.6 HTTP server example (ver $version) "
static final company = " 20110314T2125-05:00 jbetancourt"
static final UTF_8 = "UTF-8"
static final version = "0.3"
static final realmName = "my realm"
static port =0 // if zero, get unused port
static url
static int counter = 0 // for spinner
static String basedir // docbase
static String scriptDir
HttpServer server
static SimpleServer simpleServer
def SRC_INDEX_HTML = "/src/index.html"
def serverPropFilePath = "server.properties"
def props = new Properties()
def browserLauncher
def ScheduledExecutorService cancelExec
def authenticate = false
def Closure handleParams
/**
* The only thing you really need.
* @param port if 0, unused port will be used
* @param closure handles the request,response
* @return
*/
static serve(port, Closure closure){
def ss = new SimpleServer()
ss.port = port
ss.handleParams = closure
ss.serverPropFilePath = ""
ss.exec(new String[0])
return ss
}
/**
* Entry point into the demo.
* @param args
*/
static main(args) {
splash()
if(!validJavaVersion()){
return
}
simpleServer = new SimpleServer()
simpleServer.exec(args)
} // end main
/** */
def exec(args){
def basedir = new java.io.File(".").getAbsolutePath()
configure(args)
createHTTPServer()
start()
println("server started. url=$url,basedir=$basedir,scriptDir=$scriptDir,")
def spb = props.getProperty("progressBar")
cancelExec = Executors.newScheduledThreadPool(1)
keepAlive(false,
TU.MILLISECONDS.convert(1L, TU.MINUTES))
}
/**
* Handle the given request/response.
*
* The first response is the input form. The subsequent
* request evaluates the answer if any, and then the server
* is stopped. Any exception will also stop the server.
*
*/
@Override
public void handle(HttpExchange t) throws IOException {
try{
def uri = t.getRequestURI()
def query = uri.getRawQuery()
def path = uri.getRawPath()
def params = parseQuery(query)
showInfo(
uri:uri,protocol:t.getProtocol(),
query:query,path:path,params:params)
if(handleParams){
handleParams(this, t, params)
}else{
if(query == null){
if(path.length()>1){
sendPage(t,path)
}else if(path =="/") {
sendPage(t,SRC_INDEX_HTML)
}
}
}
}catch(Exception ex){
ex.printStackTrace()
stopServer()
throw ex;
}
}
/** */
def showInfo(info){
println "+++++++ Simple Server ++++++++++++++++++"
info.each{ k,v ->
println k + (v ? ': [' + v +']' : ": []")
}
println "-------------------------"
}
/** */
static splash(){
println("$splashText\n\n$company")
}
/** */
def configure(args){
try{
basedir = new java.io.File(".").getAbsolutePath()
scriptDir = "$basedir/src/"
def propFileName = (args.length) >0 ? args[0] :serverPropFilePath
port = unusedPort(HOST)
url = "$HTTP_PROTOCOL$HOST:$port/"
if(propFileName){
def getResource = {def resource->
ReflectionUtils.getCallingClass(0).
getResourceAsStream(resource)
}
InputStream context = getResource(propFileName)
if(context){
props.load(context)
context.close()
}
}
}catch(Throwable ex){
handleException(ex)
}finally {
//System.exit(1)
}
}
/** */
def createHTTPServer(){
server = HttpServer.create(new InetSocketAddress(port),0);
props.propertyNames().iterator().each{key ->
if(key.matches(".*Context\$")){
def conf = props.get(key).split(",")
def className = conf[0]
def contextPath = conf[1]? conf[1].trim(): "/"
def obj = createObjectFromScript(className, this)
def context = server.createContext(contextPath, obj)
if(conf.length>2){
def authClassName = conf[2]
def ac = createObjectFromScript(authClassName,
conf.length > 3? conf[3] : realmName)
context.setAuthenticator(ac)
}
def iProp = key + ".initialState"
if(props.containsKey(iProp)){
obj.currentState = props.getProperty(iProp)
}
iProp = key + ".transitions"
if(props.containsKey(iProp)){
obj.setTransitions(props.getProperty(iProp))
}
}
}
def context = server.createContext("/", this)
if(authenticate){
context.setAuthenticator(new MyAuthenticator("my realm"))
}
server.createContext("/stop", [
handle:{
println("in handler for stop .. t[" + it + "]")
sendString(it,"stopping server ....")
stopServer()
}
] as HttpHandler);
server.createContext("/ping", [
handle:{ ct ->
println("pinging ...")
ping(ct);
}
] as HttpHandler);
} // end createHTTPServer
/**
*
* @return
*/
static boolean validJavaVersion(){
def flag = true
def ver = System.getProperty("java.version");
if(!ver.contains("1.6") && !ver.contains("1.7")){
println("ERROR *** Requires Java 1.6 or above. Detected: $ver");
flag = false;
}
return flag;
}
/**
* Send the initial query page.
*
* @param t the request handler
* @param filePath the html file
* @return nothing
*/
static sendPage(HttpExchange t, String filePath) throws IOException {
OutputStream os = null;
try{
def fPath = new File(basedir + filePath)
def uri = fPath.toURI()
Map>map = t.getResponseHeaders()
def binary = false
if(filePath.endsWith( ".js")){
map.set("Content-Type", "text/javascript; charset=UTF-8")
}else if(filePath.endsWith(".gif")){
map.set("Content-Type", "image/gif;")
binary = true
}else if (filePath.endsWith(".jpg")) {
map.set("Content-Type", "image/jpeg;")
binary = true
}
println("sending .... " + fPath)
if(binary){
byte[] bytes = readFile(fPath.getPath())
t.getResponseHeaders().set("Content-Encoding", "gzip")
t.sendResponseHeaders(HttpURLConnection.HTTP_OK,0)
GZIPOutputStream gos = new GZIPOutputStream(t.getResponseBody())
gos.write(bytes)
gos.finish()
t.close()
}else{
def response = fPath.getText()
t.sendResponseHeaders(HttpURLConnection.HTTP_ACCEPTED, response.length());
os = t.getResponseBody();
os.write(response.getBytes());
t.close()
}
}catch(FileNotFoundException ex){
println(ex.getMessage())
}catch(Exception ex){
ex.printStackTrace()
if(os){
println("close output stream ...")
os.close();
}
}
}
/**
* Read file into buffer.
* @param path
* @return
*/
static byte[] readFile(String path){
File file = new File(path)
FileInputStream inStream = new FileInputStream(file)
FileChannel inChannel = inStream.getChannel();
def bb = ByteBuffer.allocate(1024*1024)
while(true){
int bytesRead = inChannel.read bb
if(bytesRead == -1){
break;
}
}
return bb.array()
}
/**
* Send the resulting score based on response content.
* @param t
* @param answer
* @return
*/
static sendString(t, answer ) throws IOException {
t.sendResponseHeaders(HttpURLConnection.HTTP_OK, answer.length());
OutputStream os = t.getResponseBody();
os.write(answer.getBytes());
os.close();
}
/**
* Just followed example at:
* @see http://download.oracle.com/javase/6/docs/api/java/util
* /concurrent/ScheduledExecutorService.html
*/
def keepAlive(showProgressBar, Long maxTime){
def handleBeep = cancelExec.scheduleAtFixedRate(new Runnable(){
public void run(){
if(showProgressBar){
progressBar()
}
}
}, 1, 4, TU.SECONDS);
cancelExec.schedule(new Runnable(){
public void run(){
println("\ncancel beeping")
handleBeep.cancel(true)
stopServer()
System.exit(0)
}
},4, TU.MINUTES);
}
/**
* In shell console, ASCII spinner gives visual feedback of running server.
* Got idea for approach at
* @see http://blogs.msdn.com/b/brada/archive/2005/06/11/428308.aspx
* But, then took out the use of a switch. As Charles Moore would say,
* never use conditionals when it can be calculated.
*/
static def progressBar(){
print("\b${["/","-","\\","-"][counter++ % 4]}")
}
/** */
Object createObjectFromScript( String className, Object... args ) throws Exception {
println "Creating $className"
def gcl = new GroovyClassLoader(this.class.classLoader)
def path = "$scriptDir${className.replace('.','/')}.groovy"
def cl = gcl.parseClass( new File(path))
def ni = cl.newInstance(args)
return ni;
}
/**
* Get an unused port for server and browser url.
* If port is non-zero.
* BTW, at shell:
* On windows: netstat -an
* On linux: netstat -an | grep -i listen
*
* @see http://stackoverflow.com/questions/573361
* /how-can-i-detect-a-free-port-on-the-server-by-code-from-client-side
*
* I tried simpler ways, but they didn't work. Like using 0 as port.
*
* @param hostname
* @return port number
*/
static int unusedPort(String hostname) throws IOException {
if(port){
return port
}
int minPort = 8000
int range = 0xFFFF - 8000
while (true) {
int port = minPort + (int) (range * Math.random());
try {
Socket s = new Socket(hostname, port);
s.close(); // is this wise?
} catch (ConnectException e) {
return port;
} catch (IOException e) {
if (e.getMessage().contains("refused")){
return port;
}
throw e;
}
}
}
/** */
def ping(t){
def now = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(new Date())
sendString(t, "$now")
}
/** */
String getServerProperty(key){
return props.getProperty(key)
}
/** */
def start(){
server.start();
launchBrowser(url)
}
/** */
def launchBrowser(url){
new BrowserLauncher().openURLinBrowser(url)
}
/** */
def stopServer(){
print("\nStopping server ... ")
((HttpServer)server).stop(2)
print("stopped!")
System.exit(0)
}
/** */
static handleException(Exception ex){
println("ERROR: ${ex.getMessage()}")
ex.printStackTrace()
throw ex
}
/**
* Parse query into list of values array.
*
* @see http://stackoverflow.com/questions/1667278/parsing-query-strings-in-java
* @param query
* @return
*/
static Map parseQuery(final String query){
Map params = new HashMap();
if(!query || query.length() == 0){
return params
}
def key,val
for (String param : query.split("&")) {
String[] pair = param.split("=");
if(pair.length > 0){
key = URLDecoder.decode(pair[0], UTF_8);
}
val=""
if(pair.length > 1){
val = URLDecoder.decode(pair[1], UTF_8);
}
List values = params.get(key);
if (values == null) {
values = new ArrayList();
params.put(key, values);
}
values.add(!val ? "":val );
}
return params;
}
} // end SimpleServer
// the authenticator class. Should have been just a simple inner class.
class MyAuthenticator extends BasicAuthenticator {
/** */
public MyAuthenticator(String realm){
super(realm)
}
@Override
public Authenticator.Result authenticate(HttpExchange t){
return super.authenticate(t)
}
@Override
public boolean checkCredentials(String username, String password){
//printf("user=%s, pass=%s%n", username, password)
return true
}
} // end MyAuthenticator class
Listing 6 server.properties If there is a setting for a property file it will be loaded and used. This is an example:
# SimpleServer configuration # # context = FQCN,path[,authenticator FQCN, domain name]* controllerContext = main.AppContext,/question controllerContext.initialState = running # simple state transitions = state:next_state[,state:next_state]* controllerContext.transitions = init\:running,running\:end # Misc host=localhost stop_wait = 2 basedir= scriptdir= progressBar=true browserLauncher=main.BrowserLauncher
Listing 7 index.html The ‘app’ UI:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<!-- <script src="/src/jquery.blockUI.js" type="text/javascript"></script> --><script type="text/javascript" src="/src/scripts.js"></script><script type="text/javascript">// <![CDATA[
$(document).ready(function(){ //$(document).ajaxStart($.blockUI).ajaxStop($.unblockUI); pingServer(); stopServer(); });
// ]]></script></pre>
<div class="box middle lightGrey">
<div class="middle">Embedded HttpServer Demo <span class="tiny">(com.sun.net.httpserver)</span></div>
<hr />
<form id="form1" class="box internal grey" action="/question" method="get" name="form1">
<input id="mode" type="hidden" name="mode" value="mathInput" />
<table width="100%">
<tbody>
<tr>
<td></td>
</tr>
<tr style="margin: 12px;">
<td><span id="lblReply" class="heavy"> What is "4"+"2"? </span></td>
<td><input id="reply" type="text" name="reply" /></td>
<td><input id="submitButton" title="submit" type="submit" value="submit" /></td>
<td><input id="pingButton" type="button" value="ping" /></td>
<td><input id="stopButton" type="button" value="end" /></td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
</form></div>
<pre></pre>
<pre>
Listing 8 scripts.js JQuery stuff:
// file: scrips.js
// author: jbetancourt
//
// External JQuery use.
// technique reference: http://www.latentmotion.com/separating-jquery-functions-into-external-files-without-selectors/
/* <![CDATA[ */ var pingServer; var stopServer; (function($){ pingServer = function(){ $('#pingButton').click(function(){ $.get('/ping', {mode:"ping"}, function(data){ $('#target').append(" "+data) },"html") .error(function(response,status,xhr){ var msg = "Server does not responsd: "; $("#target").html(msg + " " + status + (xhr.status ? " xhr.status: [" + xhr.status + "] " + "] xhr.statusText: [" + xhr.statusText + "]" : "") ); }); }); }; })(jQuery); (function($){ stopServer = function(){ $('#stopButton').click(function(){ $("#submitButton").attr('disabled','disabled'); $("#pingButton").attr('disabled','disabled'); $("#stopButton").attr('disabled','disabled'); $('#target').load('/stop', function(response,status,xhr){ if(status == "error"){ var msg = "Server does not responsd; "; $("#target").html(msg + xhr.status + " " + xhr.statusText); } }); }); }; })(jQuery); /* ]]> */
.heavy{ font-weight:bolder;}
.box{ border:2px solid black;}
.middle{ margin-left:auto;margin-right:auto;width:60%;}
.internal{ margin:2em;background:#F8F8F8 ;}
.horzCenter { margin-left:auto;margin-right:auto;width:50%;}
.grey { background:#F8F8F8;} .lightGrey { background:#F0F0F0;}
.large{ font-size:xx-large;padding-top:4px; padding-bottom:4px}
body{ width:960px } .tiny{font-size:small;}
Listing 10 example app AppContext.groovy
/**
* File: AppContext.groovy
* Date: 20110320T1952-05:00
* Author: jbetancourt
*/
package main
import java.text.DateFormat;
import java.text.SimpleDateFormat
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
/**
* The context that hosts the application.
*
* @author jbetancourt
*
*/
class AppContext implements HttpHandler{
def SimpleServer server;
def static RUNNING = 'running'
def currentState
def transitions = [:]
/** */
AppContext(SimpleServer server){
this.server = server
currentState = server.getServerProperty("initialState")
def statesProperty = server.getServerProperty("transitions")
}
/**
* Handle the given request/response.
*
* The first response is the input form. The subsequent
* request evaluates the answer if any, and then the server
* is stopped. Any exception will also stop the server.
*
*/
@Override
public void handle(HttpExchange t) throws IOException {
try{
def uri = t.getRequestURI()
def final query = uri.getRawQuery()
def path = uri.getRawPath()
def params = server.parseQuery(query)
showInfo([query:query,uri:uri,path:path,currentState:currentState,params:params])
def mode = params.get("mode")
if(atState("running")){
if(mode){
if(mode[0] == "mathInput"){
def reply = params.get("reply")
evaluateAnswer(t,reply)
transitionNextState()
}else if (mode[0]=="ping") {
server.sendString(t,"huh?")
}
}
}
if(atState("end")){
server.stopServer()
}
}catch(Exception ex){
ex.printStackTrace()
server.stopServer()
throw ex;
}
}
/**
* And, send response.
*/
def evaluateAnswer(t,answer){
def reply
try{
reply = (answer[0] != '"23"') ? "Wrong!" : "Correct!"
}catch(Exception ex){
reply = "wrong"
}
server.sendString(t,"</pre>
<center>
<h1>$reply</h1>
</center>
<pre>")
}
/** */
def showInfo(info){
println "++++++++ AppContext +++++++++++++++++"
info.each{ k,v ->
println k + (v ? ': [' + v +']' : ": []")
}
println "-------------------------"
}
/** */
def ping(t){
def now = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(new Date())
server.sendString(t, "$now")
}
/** */
def setTransitions(s){
s.split(",").each{ tran ->
def kv = tran.split(":")
transitions.put(kv[0],kv[1])
}
}
/** */
def atState(s){
return currentState == s
}
/** */
def transitionNextState(){
print("currentState[$currentState],")
def ns = transitions[currentState]
currentState = (ns ? ns : "end")
println(" next state=[$currentState] ")
}
} // end AppContext class
Summary
Shown was a simple example of using the JDK 1.6 embedded HTTP server using the Groovy language.
Updates
- April 15, 2011: Added some beginnings of code to handle image resources.
- August 4, 2011: Just saw an old post on same subject. “Groovy++ in action: DSL for embedding HttpServer”. Added it to references. That one creates a DSL to use the embedded HTTP server. Nice.
- Dec 4, 2011: This post has an example of using Gretty via Groovy: Five Cool Things You Can Do With Groovy Scripts
- Feb 11, 2012: The internal JDK Http server is being used here: “How ION uses Virgo“.
Required Software
• Oracle Java JDK 1.6.0.24
• Groovy 1.8-rc3
• BrowserLauncher2
Dev Software
• Eclipse: Helios Service Release 2
• Windows 7 Pro, 64bit
• Mercurial 1.8.1
• TortiseHG 2.0.2
• MercurialEclipse 1.0.0
• Groovy-Eclipse 2.1.3
Further Reading
Duplicate blog post: Java’s HTTP Server for browser-based Groovy app
API
com.sun.net.httpserver
Other Servers
Gretty
“Java development 2.0: Ultra-lightweight Java web services with Gretty”
Jetty
- Exposing Functionality Over HTTP with Groovy and Ultra-Lightweight HTTP Servers
- Jetty
- Spark – A small web framework for Java
- Jetty/Tutorial/Embedding Jetty
- Grizzly
HTTP Implementations in other languages
Python
Lib/http/server.py
CherryPy
Misc
* Groovy++ in action: DSL for embedding HttpServer
* Java non-blocking servers, and what I expect node.js to do if it is to become mature
http://blogs.operationaldynamics.com/andrew/software/free-java/sun-secret-webserver.html
* Using com.sun.net.httpserver
http://elliotth.blogspot.com/2009/03/using-comsunnethttpserver.html
* Ratpack
* Mp3d project (which uses com.sun.httpserver)
http://code.google.com/p/enh/source/browse/trunk/mp3d/src/org/jessies/mp3d/Mp3d.java
* Groovy Goodness: Groovlets as Lightweight Servlets
http://mrhaki.blogspot.com/2009/10/groovy-goodness-groovlets-as.html
* Making a simple web server in Python.
http://fragments.turtlemeat.com/pythonwebserver.php
http://en.wikipedia.org/wiki/Embedded_HTTP_server
* Comparison of web server software
http://en.wikipedia.org/wiki/Comparison_of_lightweight_web_servers
* Groovlets
http://groovy.codehaus.org/Groovlets
* Practically Groovy: MVC programming with Groovy templates
http://www.ibm.com/developerworks/java/library/j-pg02155/
* HTTP server API in Sun’s Java SE 6
http://blogs.sun.com/michaelmcm/entry/http_server_api_in_java
* Using Sun Java 6 HttpServer to write a functional HTTP test
http://alistairisrael.wordpress.com/2009/09/02/functional-http-testing-with-sun-java-6-httpserver/
* Package com.sun.net.httpserver
* Example for Java HTTP Server API and Ruby WEBrick HTTP Server
http://dragonjoke.blogspot.com/2008/06/jax-ws-loopback-connections-leak.html
http://research.operationaldynamics.com/files/andrew/EchoServer.html
http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-com.sun/net/Catalognet.htm
* Java Documentation 6.0 JDK Modules
http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-sun/net/sun.net.httpserver.htm
* ServerImpl
http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-sun/net/sun/net/httpserver/ServerImpl.java.htm
* D. Ferrin resource access solution
http://marc.info/?l=groovy-user&m=121918550625904
* Simple Java HttpServer / Handler
http://www.itdevspace.com/2011/02/simple-java-httpserver-httphandler.html
http://www.sssg.org/blogs/hiro345/tag/com-sun-net-httpserver-httpserver
* Using com.sun.net.httpserver.HttpServer for comet/cometd
* Separating jQuery Functions into External Files (without selectors!)
http://www.latentmotion.com/separating-jquery-functions-into-external-files-without-selectors/
Groovy-Eclipse, compile and run are using different classloaders?
March 19, 2011In an Eclipse Groovy project, the order of compilation is causing Groovy classloader conflicts.
I just manually deleted the compiled Groovy classes, then ran the app. Works. Now I rerun still works. Now add a simple blank line to one of the sources and run. It died. Manually delete the output class files, works again.
Strange I don’t have “rebuild automatically” turned on. Also strange, in the project properties, for builders, only the Java builder is listed.
The console output when I get the error:
Caught: groovy.lang.MissingMethodException: No signature of method: static main.SimpleServerSupport.keepAlive() is applicable for argument types: (main.QuestionServer, java.lang.Long) values: [main.QuestionServer@b32ed4, 60000]
Possible solutions: keepAlive(main.QuestionServer, java.lang.Long)The following classes appear as argument class and as parameter class, but are defined by different class loader:
main.QuestionServer (defined by ‘groovy.lang.GroovyClassLoader$InnerLoader@16921fd’ and ‘org.codehaus.groovy.tools.RootLoader@42e816′)If one of the method suggestions matches the method you wanted to call,
then check your class loader setup.
at main.QuestionServer.main(QuestionServer.groovy:72)
Haven’t solved this yet. I can’t find any reference to something like it. Maybe I just have a config issue?
I now remember that the plugin adds hooks into the Java compiler. So is the compiler used different when you run the app with “run as Groovy script” then when Java builder executes, that is what the Classloader names would suggest? But, that makes no sense, since at run time, the classloader hierarchy has nothing to do with the compile, or does it, since Groovy precompiles at runtime?
Yes, I uninstalled the Groovy feature and reinstalled.
Running the same program (script) at the command line is fine.
Todo: Post some code that exhibits the issue. The current code is still at the “throw at wall and see what sticks” stage.
Updates
- 20110328T2010-5: Solved it. I moved a method from a support class, into the main SimpleServer class. This method was using an Executor.newScheduledThreadPool(1) to start a thread to limit the server’s lifetime, it also did a little console spinner to show that there is something running. I don’t see how that is related to classloaders.
Environment
Windows 7 64bit Professional
Eclipse Helios Service Release 2
Groovy-Eclipse Feature 2.1.3.xx-20110317-1200-e36
Java Dev Using Embedded Groovy Console in Eclipse
December 12, 2010In development, simple but powerful tools to get at the essence of a code source in order to understand, test, and extend it is essential. This is even more important in Test Driven Development (TDD). Eclipse’s Java Debugger is for most situations, powerful enough. Eclipse has an Expressions View available in the debug perspective to execute snippets of code. The Java Development Toolkit (JDT) also has a Scrapbook facility that allows the creation, storage, and running of experimental code. And, of course, all the other features of the debugger are excellent.
However, when you need it, it’s possible to embed a script engine and have new ways of analyzing and developing code. In listing 1, an app shows the use of the ConsoleWaiter class. When the code executes the waiter.run() at line 43, it opens the Groovy Console which allows the use Groovy shell scripting in a GUI frame, see figure 1. When the console is closed the app continues executing.
Listing 1
/*
* File: ExampleApp2.java
* @author jbetancourt
* Date: 20101213T1718-5
*
*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*
* @author jbetancourt
*
*/
public class ExampleApp2 {
static public String greeting = "Hello world!";
private static final List<String> nodes;
static {
nodes = new
ArrayList<String>(
Arrays.asList("one","two"));
}
private String title = "Example 2";
public String getTitle(){
return title;
}
/**
* @param args command line args
*/
public static void main(String[] args) {
ExampleApp2 app = new ExampleApp2();
ConsoleWaiter waiter = new ConsoleWaiter(app);
waiter.setVar("greet", greeting);
waiter.setVar("nodes", nodes);
waiter.setVar("title", app.getTitle());
waiter.run();
System.out.println("Done!");
}
}
This is awesome. In one project I had to examine the contents of a Properties object. Did it have an “email” value? I was stumped when using the Eclipse debugger, it did not show all entries in the Map, at the end was “…”. Sure, I could use the Expressions window, but with the Console I could not only do a get(key), but iterate using Groovy style closures and much more.
The magic that enables this is the ConsoleWaiter.groovy class shown below in listing 2 that was written by John Green. Since a Groovy script is a Java class underneath, in Eclipse you can call Groovy from Java easily (some compiler magic).
Listing 2
/**
* File: ConsoleWaiter.groovy
*/
import groovy.lang.Binding;
import groovy.ui.Console;
/**
* Provides a wrapper for the console.
*
* Based on source by John Green
* Adapted from: http://www.oehive.org/files/ConsoleWaiter.groovy
* Released under the Eclipse Public License
* http://www.eclipse.org/legal/epl-v10.html
*
* I added methods to allow use from Java.
*
* The run() method launches the console and causes this thread
* to sleep until the console's window is closed.
* Allows easy interaction with the objects alive at a given
* point in an application's execution, like in a debugger
* session.
*
* Example 1:
<pre> * new ConsoleWaiter().run()
*</pre>
*
* Example 2:
<pre> * def waiter = new ConsoleWaiter()
* waiter.console.setVariable("node", node)
* waiter.run()
*</pre>
*/
class ConsoleWaiter {
Console console
Object source
boolean done = false;
/** */
public ConsoleWaiter(Console inConsole){
this.console = inConsole
}
/** */
public ConsoleWaiter(Object source){
console =
new Console(getClass().classLoader,
new Binding())
this.source = source
console.setVariable("source", source)
}
/** */
public void setVar(String key, Object value){
console.setVariable(key, value)
}
/** */
public void setVar(String key, List values){
console.setVariable(key, values)
}
/** */
public void setVar(String key, Object[] values){
console.setVariable(key, values)
}
/** */
public void run() {
console.run()
// I'm a little surprised that this exit() can be private.
console.frame.windowClosing = this.&exit
console.frame.windowClosed = this.&exit
while (!done) {
sleep 1000
}
}
/** */
public boolean isDone(){
return done;
}
/** */
public void exit(EventObject evt = null) {
done = true
}
/** */
public Console getConsole(){
return console;
}
}
Eclipse Integration
The disadvantage of this approach is that you have to put extraneous code inside the tests or target class. Not only is this tedious and slow, what if code is accidentally deployed like this? A better approach is to just set a breakpoint in the code, and then have the ability to open a script console at that breakpoint, in the Java Stack Frame, that has access to the execution context and classpath. Is there an Eclipse add-in that does this? If not, there should be.
Conclusion
Shown was a simple example of embedding a Groovy console in Java code to allow scripting. Of course, this is not a new idea. It was even mentioned in an older JVM scripting language, Beanshell. Note that it is possible to instead of using a GUI console, to use the Groovy shell, InteractiveShell class. In the reading list below this approach is taken to allow remote scripting of a server hosted application.
Updates
-
Oct 10, 2011:
Interesting tool that could be relevant: YouDebug. - March 20, 2012: Not exactly same scenario, but the concept of an embedded script console is found in many products. Jenkins CI Server has one and it uses Groovy. Jenkins Script Console
Further reading
- http://groovy.codehaus.org/Groovy+Console
- http://groovy.codehaus.org/Embedding+a+Groovy+Console+in+a+Java+Server+Application
- Embedding a Groovy Console in a Java Server Application, http://69.89.31.118/~iterativ/wordpress/category/technology/
- Jenkins Script Console
- “Eclipse UI and Scripting”, http://www.oehive.org/book/export/html/911
- http://www.oehive.org/files/ConsoleWaiter.groovy
- http://jira.codehaus.org/browse/GRECLIPSE-499
- http://groovy.329449.n5.nabble.com/groovy-shell-in-windows-exits-immediately-when-run-from-within-Eclipse-td391970.html
- http://groovy.codehaus.org/Embedding+Groovy
- YouDebug
What is Eclipse’s Current Workspace?
October 7, 2010Maybe someone knows the answer. Unless you start Eclipse with the “-showLocation” option there is no way to know what the current workspace location is.
One reason to know is that when I go to create a new project, do I specify the workspace or is the current workspace the one I want? I don’t remember if the workspace is shown or specified on project creation, will have to check.
Maybe I’m missing some internal Eclipse reason for this (similar to that crazy bug when the copyright name was changed inside Java) and there is no way for Eclipse to know this. Still, seems lame.
Update
17JAN2011: Found the answer, see below. I was on the right track. If I read the FAQ entry correctly, the current project is accessible (even though there can be many active projects), it is just not exposed in the Eclipse UI?
Further reading
What is Eclipse’s Current Workspace?
FAQ How do I access the active project?
http://dev.eclipse.org/newslists/news.eclipse.platform/msg70488.html
Maria Pia de Vito with John Taylor & Ralph Towner – I Knew It was you
Posted by josefB 


