Sometimes you may want to quickly generate graphs programmatically and view/analyze those. Examples include, inheritance/type relation diagrams of an object oriented program, function call graphs and any other domain specific graphs (reporting chain of your organization chart for example). I find GXL very useful for this. GXL stands for Graph eXchange Language. It is a simple XML format to specify graphs. A simple graph stating that "JavaFX" language is related to "Java" language is as follows:
File: Test.gxl<gxl> <!-- edgemode tells this is directed or undirected graph --> <graph id="langs" edgemode="directed"> <!-- write your nodes --> <node id="java"/> <node id="javafx"/> <-- now write your edges --> <edge from="java" to="javafx"/> </graph> </gxl>
You can also add number of "attributes" to nodes and edges - like color of the edge, style of the edge and so on. For example, "red" color can be specified for an edge as follows:
<edge from="java" to="javafx"> <attr name="color"><string>red</string></attr> </edge>
Now that we have written a simple graph with two nodes and a single edge between them, we may want to view it. There are number of tools/libraries to view GXL documents -- I've used Graphviz. Graphviz displays it's own native format called ".dot". Graphviz comes with a set of command line tools. One such tool is "gxl2dot", which as you'd have guessed, can be used to convert a .gxl file to a .dot file.
gxl2dot Test.gxl > Test.dot
Once converted the .dot file can be opened in Graphviz GUI and we can export it to .pdf/.jpg/.png and so on. This way you can email the graphs to others and/or publish in your blogs/webpages easily.
The converted .pdf file for the above simple graph is here: test.pdf
I've used GXL graphs in a recent debugging tool related to JavaFX compiler. More on that later...
Note I have split the resources and news links off from this GlassFish v3 Announcement into the first of one of a series of resources and links entries. The new arrangement is more manageable and also simplifies the creation of additional entries as more resources and news are posted on the release.
It has been 4 and a half years since we announced GlassFish during JavaOne 2005 (PR) and today we are making available our most important release: GlassFish v3 is now available for download!
Our first release was during JavaOne 2006, we released GlassFish v1, the first Java EE 5 compliant App Server (family overview) and the second generation of GlassFish came out in September 2007 (family overview). While still based on JavaEE 5, GFv2 leveraged on Sun's (too) long history of App Servers to add the benefits of an enterprise product (quality, performance, scalability) to those of an open source community (agility, ease of use, supportive teams, pricing).
While the transition between GlassFish v1 and v2 was evolutionary, the transition from v2 to v3 is a major change that includes a whole new set of JCP specifications, JavaEE 6, and a new modular, OSGi-based, architecture that expands significantly the applicability of GlassFish.
|
Key links available now:
•
GlassFish v3
Main Product Page
We are hosting several events in the next few days; we hope to see many of you at our Virtual Conference on Dec 15th, and in one of our Community Parties. |
Below are lists of posts relevant to the launch and the release; they will be updated through the day to incorporate news as they happen. Updates will also be posted to @glassfish at Twitter. If you use Twitter we recommend you to use #glassfish to facilitate discovery. Some level of geotagging would help visualize the spread of the community.
Announcements
GlassFish v3 - Index to Announcement, Resources and Links
This is one of a series of resources and links related to the new GlassFish v3 release. Each entry starts with a section with key links; the resources are then grouped into categories.
GlassFish v3 - Index to Announcement, Resources and Links
|
Key links
Events
Real-Time News
|
Press
Overviews, Appreciation, Analysis
Non-English Posts
Technical Posts
import groovyx.net.ws.WSClient
class ShakesWsClient {
String play, speaker, words
void findQuote(searchString){
def proxy = new WSClient("http://www.xmlme.com/WSShakespeare.asmx?WSDL", ShakesWsClient.class.classLoader)
proxy.initialize()
def speech = new XmlParser().parseText(proxy.GetSpeech(searchString))
play = speech.PLAY.text()
speaker = speech.SPEAKER.text()
words = speech.text()
}
}
That allows me to get at the play, speaker, and text from my Java code as follows:
public class Demo {
public static void main(String[] args) {
ShakesWsClient client = new ShakesWsClient();
client.findQuote("fair is foul");
System.out.println(client.getPlay());
System.out.println(client.getSpeaker());
System.out.println(client.getWords());
}
}
Ant output:
12 Dec 2009 4:04:10 PM org.apache.cxf.endpoint.dynamic.DynamicClientFactory outputDebug INFO: Created classes: com.xmlme.webservices.GetSpeech, com.xmlme.webservices.GetSpeechResponse, com.xmlme.webservices.ObjectFactory 12 Dec 2009 4:04:11 PM groovyx.net.ws.AbstractCXFWSClient getBindingOperationInfo WARNING: Using SOAP version: 1.1 MACBETH ALL Fair is foul, and foul is fair: Hover through the fog and filthy air. BUILD SUCCESSFUL (total time: 6 seconds)
Anyone out there with suggestions for how to improve my Groovy code (even further)?
By the way, I believe that Groovy's web service support is the best thing about Groovy, especially if you mainly want to continue working in Java.
I stopped by the Tokyo OpenSolaris Study Group meeting in Yoga today. The guys were running two consecutive sessions on ZFS, Solaris Internals, and Driver Development. Good turn out for a Saturday afternoon, too. About 35 people came to the sessions with another 30 or so contributing on IRC at #opensolaris-jp on Freenode. Here are some images:
The Tokyo OpenSolaris Study Group grew out of the Japan OpenSolaris
User Group. Here are some links to more information about the OpenSolaris
community in Japan. And here is a stash of several years of images from OpenSolaris in Japan.
The latest Sun HPC Newsletter is out. Don't miss an issue--Subscribe today!
The result is displayed in a BeanTreeView, using BeanNodes, synchronized with the Properties window. Double-click a node and you bring up a dialog containing the retrieved text, as shown above. There's also a progress bar to avoid the situation where the UI is blocked during the processing of the web service.
private void findButtonActionPerformed(java.awt.event.ActionEvent evt) {
Thread t = new Thread(new WSRunnable());
t.start();
}
private class WSRunnable implements Runnable {
@Override
public void run() {
ProgressHandle p = ProgressHandleFactory.createHandle(
"Fetching the Shakespeare quote for " +
"'" +searchField.getText() + "'");
p.start();
QuoteBean bean = new QuoteBean();
ShakesWsClient client = new ShakesWsClient();
bean.setName(client.getSpeaker(searchField.getText()));
bean.setPlay(client.getPlay(searchField.getText()));
bean.setSpeech(client.getSpeech(searchField.getText()));
bean.setSearch(searchField.getText());
content.add(bean);
p.finish();
}
}
Above, in bold, is all the code needed to integrate with the progress bar!
And here's the same scenario as above, using an AbstractNode instead of a BeanNode, which gives you more freedom, but also more responsibility:
A full tutorial to describe all of the above will be on NetBeans Zone soon.
In other news. All the code for the above, plus a bit more, is available here on Кеnai: http://kenai.com/projects/shakespeareannotater
Ed Plese has kindly provided OpenSolaris x86 binaries for the Arduino development environment. This includes all the necessary dependencies such as avr-gcc. and will work on OpenSolaris x86 build snv_113 onwards. The tarball is hosted on the Sun Download Centre, see the page at OpenSolaris.org for more details and links to the downloads.
Thanks to Ed for doing the work necessary to make this available for the OpenSolaris community.
A bunch of great new releases and updates to Sun Software has been
announced. The following are the highlights from these releases
[Disclaimer – I am not the author of these writeup's, just a aggregator of information
]
The availability of the Java EE 6 and GlassFish Enterprise Server v3, the first Java EE platform-compatible application server and the most downloaded Java EE application server in the world.
Java EE 6 is a significant release of the enterprise Java standard that delivers major productivity enhancements as well as the Web Profile, a lightweight subset of the full platform optimized for Web applications.
Sun GlassFish Enterprise Server v3 enables faster time to market with rapid iterative development, the ability to run dynamic language applications, and enhanced monitoring and management.
GlassFish Enterprise Server v3 is a flexible, easy-to-use, open-source enterprise platform.
It offers businesses the ability to easily manage costs and reduce the complexity of their existing enterprise server deployments.
GlassFish Enterprise Server v3 is based on the Java EE 6 reference implementation and is the first application server to support the full Java EE 6 platform.
GlassFish Enterprise Server does not add proprietary extensions and stays true to the Java EE standard, lowering the barrier to entry.
GlassFish is the most downloaded Java EE platform-compatible application server, with more than 24M downloads since 2006. It is focussed on improving developer productivity and providing an enterprise-grade, open-source application server solution for customers.
GlassFish Enterprise Server v3 continues to innovate by providing a lightweight, flexible platform based on an OSGi-based runtime that improves startup time and reduces resource utilization. The flexibility of GlassFish Enterprise Server v3 and the Web Profile distribution enables organizations to begin consolidating Tomcat, Java EE application server, and dynamic language application infrastructure into a single, manageable runtime.
GlassFish Enterprise Server v3 delivers dramatically increased productivity that comes as part of the Java EE 6 specification and enables rapid iterative development on multiple languages.
GlassFish Enterprise Server v3 is production-ready.
GlassFish Enterprise Server v3 offers a huge range of benefits to enterprises because of its open-source approach, which ensures a large talent pool of developer expertise and a strong partner ecosystem. It also provides transparency that enables enterprises to align initiatives with upcoming product releases.
Developers can easily take advantage of these new features through NetBeans IDE 6.8, the first IDE to provide complete support for the Java EE 6 platform and GlassFish Enterprise Server v3.
Developers using Eclipse can use the GlassFish Tools Bundle for Eclipse 1.2, enhanced to support the Java EE 6 platform and GlassFish Enterprise Server v3. Download it!
Flexible pricing options are available.
Sun Message Queue 4.4 Update 1
MQ 4.4u1 is now shipping and is available for immediate download and purchase. 4.4u1 is included in GlassFish v3.
These are the highlights of the new features of MQ 4.4u1:
JMS Bridge -- for integrating to any JMS 1.1 compliant provider
STOMP Bridge -- a text oriented interface that can be used by scripted as well as programmed client applications
Embedded support for custom solutions -- Customers can now embed the MQ broker into their own application
IPS support -- Support for update center 2.2 as well as enabling MQ support for all types of Solaris Zones
A new transaction log implementation provides a 1.5x boost for persistent transactional messages for clustered configurations as well as other general improvements. You can learn more by reading the updated documentation available at [http://docs.sun.com/coll/1307.7].
Finally, all the details are available in the technical training webinar which was recorded and is available at these links:
Part 1 - https://slx.sun.com/1179275731 - This section covers the overview of MQ4.4 and JMS bridge
Part 2 - https://slx.sun.com/1179275732 - This section focuses on STOMP protocol support, UMS updates, and IPS packaging
Part 3 - https://slx.sun.com/1179275733 The conclusion
Community users can also refer to the development information available at https://mq.dev.java.net/4.4.html.
The NetBeans IDE 6.8 is available for download free of charge at www.netbeans.org.
KEY UPDATES TO THE NETBEANS 6.8 IDE
Complete Java EE 6 Support: Java EE 6 language features simplify Java application development with less XML configuration, more annotations and more POJO-like development.
GlassFish v3 Support: Developers can easily target and deploy to GlassFish v3, including the new lightweight GlassFish v3 Web Profile.
JavaFX(TM): The latest version of the NetBeans editor provides improved code completion, hints and navigation for JavaFX.
PHP Support: The NetBeans IDE expands its support of dynamic languages with support for PHP 5.3 and the Symfony framework.
Tighter Integration with Project Kenai: Project Kenai, a collaborative environment for hosting open source projects, now delivers full support for JIRA and improved instant messenger and issue tracker integration. For more information visit www.kenai.com.
C/C++ Profiling: The new Microstate Accounting indicator and I/O usage monitor help developers profile and tune C/C++ applications.
NetBeans Platform: As a rock-solid application framework for Swing applications, the platform saves developers a huge amount of time and effort by providing commonly-used facilities such as menu items, toolbar items, keyboard shortcuts, and window management out of the box.
Additional information is available at:
NetBeans 6.8 IDE - http://netbeans.org/community/releases/68/
Tonight I stumbled across a website for Mark Mail, a “free service for searching mailing list archives.” I tried searching for “Discovering Identity” and found nine entries, two of which referred to this blog. I suppose that means this blog is waaaaay out in the long tail of the Mark Mail economy.
But I still like the name.
|
This new Java ME Game called, Sing to the Dawn, reminds me a lot of the old 1980s video arcade game, Joust. The same horizontally scrolling, jump on floating rocks type of thing--but, this video has a really, really bad soundtrack. Ugh.
See:
|
I get one every three years now and just got back from the latest, which means that you get a reminder too. Because first of all, colon cancer kills many, and colonoscopy really fucking works. And it’s not that much of a hassle. So if you’ve got any of the risk factors (over fifty? eat red meat? couch potato? alcohol?) go talk to your doctor already. Be good about this or next time I’ll run the screen-grab they gave me of my wholesome pink innards, and you just know you won’t be able to avoid looking.
It would be a cool tagline to use for their advertising, "Warm things up with AstraSync for your BlackBerry". But, I think Astroglide personal lubricant already has that tagline (without the 'your BlackBery' part though). Oh well. Just make sure you don't mix up the two.
See: Don't mix up AstraSync w/Astroglide Here's a quote: AstraSync performs two-way over- the-air synchronization of email, calendar and contact data with Exchange ActiveSync compatible servers including Microsoft Exchange, MailSite Fusion, CommuniGate Pro, Zimbra, Scalix, FirstClass, Open-Xchange, Kerio MailServer, Google Sync and Gmail.Hey, using Java ME technology-enabled AstraSync to do all that two-way syncing is just sinfully fun, dontcha think? Or, at least for some ...with their BlackBerries... |
With the release of the GlassFish v3, we have built a Java EE 6 application server that is :
I am not going to dwell on a long laundry list of features we support or changed in this release, this would require a book (seriously, we rewrote so many parts, it's monumental) so I will just demonstrate some of these extension points by adding a new container to GlassFish. This new container will run a new component type called the Wombat component. Therefore I am proposing to write a wombat-container implementation in this entry. Sources can be found here.
A wombat component is just a POJO annotated with a @Wombat annotation. The annotation looks like :
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
public @interface Wombat {
/**
* Name to disambiguate different wombats
*
* @return a good wombat name
*/
public String name();
}
Nothing fancy here, there is a mandatory name attribute that need to be set to disambiguate various wombat components your application might package. Each wombat component has a set of public methods that make up its interface and can be called from any client code. The lifecycle of the wombat components is managed by the wombat container and such wombat components should be injectable in any Java EE components (that supports injection of course) without much effort.
Let's have a look at my first Wombat component :
@Wombat(name="simple") public class SimpleWombat { public String saySomething() { return "Bonjour"; }}
When implementing a GlassFish container extension, you need to implement 4 distinct interfaces, let's review them now :
Still with me ? Good, it's almost over with the theory, one more thing : It's important to understand how everything works when dealing with applications containing several component types. For instance, take a war file containing a servlet and a wombat component. In such cases, each sniffer will pick up the application, a container of each type will be instantiated and the application will be deployed using each deployer returned by each container. At the end, deployment will end up with a number of ApplicationContainer instances (2 in the war example above).
Let's look now how this is implemented, first the sniffer :
@Service(name="wombat")
public class WombatSniffer implements Sniffer {
public boolean handles(ReadableArchive source, ClassLoader loader) {
return false;
}
public Class<? extends Annotation>[] getAnnotationTypes() {
Class<? extends Annotation>[] a = (Class<? extends Annotation>[]) Array.newInstance(Class.class, 1); a[0] = Wombat.class; return a; }
public String[] getContainersNames() {
String[] c = { WombatContainer.class.getName() };
return c;
}
The interesting methods are handles() and getAnnotationTypes(). getAnnotationTypes() should return all annotations that identify components implemented by this container. In our example it's the @Wombat annotation type. You can imaging for instance that the EJBSniffer is returning @Stateless and other EJB related annotations. The returned annotation types are used by the deployment infrastructure to scan for all annotations in one pass rather than relying on each sniffer doing a pass for its annotation types. handles() should return true if the sniffing of the deployable artifact revealed any component supported by this container, this is useful when component can be defined in xml deployment descriptors. In this particular case, it returns false all the time since we only use annotations.
Once the sniffer handles() returns true or if one of the annotation returned by getAnnotationTypes() has been spotted, the Container identified by getContainerNames() is instantiated. Let's look at that code :
@Service(name="org.glassfish.examples.extension.WombatContainer")
public class WombatContainer implements Container {
public Class<? extends Deployer> getDeployer() {
return WombatDeployer.class;
}
public String getName() {
return "wombat";
}
}
As you can see the wombat container does not have many things to do when it's brought into memory, our web container for instance is slightly more complicated... The interesting method is the getDeployer(), let's look at the deployer code now :
@Service
public class WombatDeployer implements Deployer<WombatContainer, WombatAppContainer> {
public boolean prepare(DeploymentContext context) {
return false;
}
public WombatAppContainer load(WombatContainer container, DeploymentContext context) {
WombatAppContainer appCtr = new WombatAppContainer(container);
ClassLoader cl = context.getClassLoader();
ReadableArchive ra = context.getOriginalSource();
Enumeration<String> entries = ra.entries();
while (entries.hasMoreElements()) {
String entry = entries.nextElement();
if (entry.endsWith(".class")) {
String className = entryToClass(entry);
try {
Class componentClass = cl.loadClass(className);
// ensure it is one of our component
if (componentClass.isAnnotationPresent(Wombat.class)) {
appCtr.addComponent(componentClass);
}
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
return appCtr;
}
public void unload(WombatAppContainer appContainer, DeploymentContext context) { }
public void clean(DeploymentContext context) { }
private String entryToClass(String entry) {
String str = entry.substring("WEB-INF/classes/".length(), entry.length()-6);
return str.replaceAll("/", ".");
}
As you can see, Deployer has 4 important methods, prepare, load, unload and clean. Prepare is called when the application is loaded, application containers cannot rely on the final class loader to be available during the prepare phase. The load phase loads the component container but does not start the component, it should not be possible to make client invocations yet. Unload and clean are the undeployment/unloading counterparts of the prepare and load methods. The load() method implementation is rather not sophisticated, it loads all classes from the archive and checks if the class is annotated with the @Wombat annotation. If so, it keeps track of all classes that are wombat components.
Finally, the last part, the ApplicationContainer implementation :
public class WombatAppContainer implements ApplicationContainer {
final WombatContainer ctr;
final List<Class> componentClasses = new ArrayList<Class>();
public WombatAppContainer(WombatContainer ctr) {
this.ctr = ctr;
}
void addComponent(Class componentClass) {
componentClasses.add(componentClass);
}
public boolean start(ApplicationContext startupContext) throws Exception {
for (Class componentClass : componentClasses) {
try {
Object component = componentClass.newInstance();
Wombat wombat = (Wombat) componentClass.getAnnotation(Wombat.class);
ctr.habitat.addComponent(wombat.name(), component);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
return true;
}
public boolean stop(ApplicationContext stopContext) {
for (Class componentClass : componentClasses) {
ctr.habitat.removeAllByType(componentClass);
}
return true;
}
public boolean suspend() {
return false;
}
public boolean resume() throws Exception {
return false;
}
}
As you can see the code is fairly straightforward once again. On start, we instantiate all wombat components the deployer found, then we add them to the habitat so they can be looked up using the NamingManager. The stop command undo what the start command did and we don't support suspend/resume in this example.
We now have all the code necessary to implement our wombat container. Let's look now at the optional features one might want to add to a GlassFish V3 container.
it's of course important to add configuration for our new wombat container and have that configuration store in our central configuration file, the domain.xml. This is particularly important to users so that they feel the extension is well integrated with the rest of GlassFish. Also by using the configuration infrastructure, you get REST access to the configuration for free and other freebies. To be able to save your configuration to the domain.xml, you only need to declare a few annotated interfaces (similar to JAXB interfaces). So let's take the following configuration format :
<wombat-container-config number-of-instances="5">
<wombat-element foo="something" bar="anything"/>
</wombat-container-config>
As you can see, this xml snippet is just defining the content of the wombat container, it is agnostic under which element in the domain.xml it will added to or even where it will be stored, that magic is handled by the GlassFish configuration.
Let's have a look at our 2 annotated interfaces defining this configuration :
@Configured
public interface WombatContainerConfig extends Container {
@Attribute
public String getNumberOfInstances();
public void setNumberOfInstances(String instances) throws PropertyVetoException;
@Element
public WombatElement getElement();
public void setElement(WombatElement element) throws PropertyVetoException;
}
@Configured
public interface WombatElement extends ConfigBeanProxy {
@Attribute
public String getFoo();
@Attribute
public String getBar();
}
It's pretty much self-explanatory, 2 classes for the 2 elements. The parent element define a sub-element annotated with @Element interface, the attributes are annotated with @Attribute. This is all you need to do read and store configuration data from our domain.xml. The configuration backend will take care of implementing these interfaces with the necessary hooks to read and write the XML correctly (or whatever format we might choose in a future release). The wombat container can use the getter methods to access the configuration as it is defined in the domain.xml it is running with.
One last thing, how can you get the configuration added to the domain.xml when the container has been newly added (first time access). Let's revisit the sniffer class with some new methods since it is the natural place to handle first time initializations. I am not repeating the methods I already mentioned above :
@Service(name="wombat")
public class WombatSniffer implements Sniffer {
@Inject(optional=true)
WombatContainerConfig config=null;
@Inject
ConfigParser configParser;
@Inject
Habitat habitat;
public Module[] setup(String containerHome, Logger logger) throws IOException {
if (config==null) {
URL url = this.getClass().getClassLoader().getResource("init.xml");
if (url!=null) {
configParser.parseContainerConfig(habitat, url, WombatContainerConfig.class);
}
}
return null;
}
The key here is that we have an optional dependency on WombatContainerConfig so if is not present in the domain.xml, the instance variable will remain null. When the first wombat deployment is under way, deployment infrastructure will call setup(). Within the setup method implementation, if the instance is null, that mean there is no wombat container configuration present in the domain.xml and we add it using the small xml snippet mentioned above (and packaged in the container jar file in the init.xml). The config parser is a utility API that can be used to parse a random xml snippet and add it to the right location in the domain.xml. By the way, location, location, yes but how is that location defined ? Look at WombatContainerConfig, it extends the Container interface, that's the marker interface that tell the configuration backend that it's a container configuration (we have a few documented extension hooks like this). After set up is called, the domain.xml will look like :
<domain....>
....
<configs>
<config name="server-config">
<wombat-container-config number-of-instances="5">
<wombat-element foo="something" bar="anything" />
</wombat-container-config>
<http-service>
....
</domain>
as you can see wombat-container-config element was added to the right location under config so that when clustering is enabled, the wombat container config can be referenced or have values specific to a node or a configuration.
Now that we have added configuration, it would be nice to be able to change it. The simplest way to do that is to add a CLI command, but you can also add an admin GUI plugin if you feel more adventurous, it's not any harder. Let's look at the CLI admin command implementation.
@Service(name="wombat-config")
public class WombatConfigCommand implements AdminCommand {
@Param
String instances;
@Inject
WombatContainerConfig config;
public void execute(AdminCommandContext adminCommandContext) { try { ConfigSupport.apply(new SingleConfigCode<WombatContainerConfig>() { public Object run(WombatContainerConfig wombatContainerConfig) throws PropertyVetoException, TransactionFailure { wombatContainerConfig.setNumberOfInstances(instances); return null; } }, config); } catch(TransactionFailure e) { } } }
As you can see, he too gets the Wombat configuration injected and the command is defining a single parameter (instances) which will be used to change the number of instances attribute on the wombat configuration. Like any configuration change in GlassFish V3, the command must use a Configuration change transaction to ensure some ACID properties to the configuration change.
This command can be invoked by doing :
asadmin wombat-config --instances 10
and you will see the wombat-config xml snippet in domains/domain1/config/domain.xml change from 5 (it's initial value) to 10. There are more extensions capability like I mentioned earlier, you can add an admin GUI plugin, you can have some code run when the user creates a new domain (to get once again some default configuration stored in the newly created domain.xml) and few other advanced goodies.
So we have now a complete container implementation for wombat components, let's build it and install it in glassfish :
cd wombat-container mvn install cp target/wombat-container.jar <glassfishv3>/glassfish/domains/domain1/autodeploy/bundles
Now we need to create some wombat components and use them inside a client like a servlet. To do that, I am defining a web application which will contain a simple servlet and a single wombat component. Please note that this servlet is a converged application since it contains both Java EE artifacts like the servlet and foreign components like the Wombat component. The structure of this application is however a simple war file, no need to have to package the wombat components in a different file.
./pom.xml
./src
./src/main
./src/main/java
./src/main/java/components
./src/main/java/components/SimpleWombat.java
./src/main/java/HelloWorld.java
./src/main/webapp
./src/main/webapp/WEB-INF
./src/main/webapp/WEB-INF/web.xml
let's look at the sources, SimpleWombat.java first :
@Wombat(name="simple")
public class SimpleWombat {
public String saySomething() {
return "Bonjour";
}
}
and the servlet :
@WebServlet(urlPatterns={"/hello"})
public class HelloWorld extends HttpServlet {
@Resource(name="Simple")
SimpleWombat wombat;
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
PrintWriter pw = res.getWriter(); try { pw.println("Injected service is " + wombat); if (wombat!=null) { pw.println("SimpleService says " + wombat.saySomething()); pw.println("<br>"); } } catch(Exception e) { e.printStackTrace(); } } }
to use the client, just build and deploy
cd webclient
mvn install
asadmin deploy target/webclient.war
and access the page at http://localhost:8080/webclient/hello
As you can see, I reuse the same @Resource type of dependency I used to inject my OSGi declarative services in my previous blog so you can really use only Java EE APIs to use extended features.
In this blog entry, I demonstrated how easy it can be to add a new container for new component types to GlassFish V3. You might ask yourself why would you ever need to do that and in all honesty, very few people will need to but the truth is that certain domain specific problems could be easily resolved by added domain specific components with their specific lifecycle, responsibilities or invocation methods. Also with the various web related framework flourishing, the scripting languages bases solutions, there are more and more application types these days. One more thing, we used the infrastructure described above to implement all of the Java EE containers (like EJB, Web, JPA, WebServices...) and others like our Rails containers so I am pretty confident you can leverage these features, we tested them well...
The image is smaller than downloading the complete DVD Media Kit iso image. This appliance image is just under 1.5Gb. It also starts up and imports much quicker than doing a normal DVD install.
The image is taken from a default installation of Solaris 10 10/09. Before the image was exported to OVF format, the
sys-unconfig command was ran on the image.
When you import this image and start it up for the first time, you will be prompted to select several parameters for your installation (keyboard layout, networking, root password, time zone, etc.).
This is the first time that Sun has made a Solaris 10 appliance images available, and hopefully this will benefit our customers. Let me know if you have any feedback on this effort for future improvements. One option we had considered was to provide a minimum installed version of Solaris 10 (no windowing and GUI). This was much smaller at just over 300Mb in size, but it may not be very useful to the average user.
We don't have a Christmas tree yet. We are thinking of buying a live tree and then donating it to Our City Forest for planting in January. We hosted the Silicon Valley Lines Model Railroad Club annual holiday party last week. Tonight, we host the Spiral holiday dinner party. We will also host Christmas dinner, a party to celebrate my daughter Jessica's 21st Birthday and Engagement, plus New Year's Eve. In addition to our own celebrations, my husband John Plocher has been helping Santa Maria Urban Ministry (SMUM) with their holiday events and food distribution. I have been working on the St. Andrew's Medical Assistance (SAMA) Christmas craft sale of goods from the Holy Land.
Busy times!
Waiting for food at SMUM
|
Filling SMUM food boxes
|
In the SMUM food line
|
Office building window lights
|
Neighborhood Deer Lights
|
Our house - train lights with the moon
|
Christmas night lights
|
Same house during day
|
Flat daytime Santa
|
SAMA mother of pearl
|
SAMA sale
|
SAMA sale - camels
|
SAMA sale
|
SVL party train
|
Christmas cockatiels
|
SMUM Santa
|
SMUM Christmas
|
Images Copyright 2009 Katy Dickinson and John Plocher
A debate started up in our hallway over the last few days, and while I am aware that this is water under the bridge, I am curious - am I the only person that likes answering questions while installing an OS?
Before I came to Sun, I was a system administrator. I administered systems running AIX, HPUX, IRIX, Solaris, SunOS, WinNT, Win95, and Win3.1. When installing the OS or any software, I always choose "custom install" or "advanced install". I like having that choice, as the software invariably makes the wrong choices for me. At the very least, I like being able to validate the choices the software has made before they are committed to disk. I am impressed when the software can correctly figure most things out, if it can, but no software, in my opinion, can possibly predict the correct answers for all installations.
There is a lot of lore here in Sun that system administrators and developers don't like all the questions we used to ask during installation of Solaris, which is why this has changed so drastically for OpenSolaris. My experience, though, is limited only to my own and those administrators I worked with at Intel and Amoco (BP, now), so I'm curious - what do you think? Do you abhor questions during install time of software? Or would you rather have the option to review the choices it made for you? Or make the choices yourself?
The 2009 Space Coast Marathon was great, my third marathon this year
(of a planned two). I had bib 472 and finished in 4:26:55 which is
about 20
minutes better than my previous best (my first, Baltimore 2008) and just shy of an hour
better than Baltimore this year (about 40 days prior) with a low grade
fever and upper
respiratory infection.
My official stated goal was a 4:30:00 (10:18/mi) and I started out aiming for
a 4:28:00 (10:13/mi) with a 4:25:00(10:06/mi) being my stretch goal. I
entertained the thought of 4:22:00 (10:00/mi but that was ridiculous).
My notes for the race:
Weather was perfect. Beautiful course a bit more hilly than I was
expecting in the first half for a "mostly flat course". Pre-driving on
Friday was a great idea. Pacing was a little erratic particularly in
the dark and generally faster than plan. Warmup was poor and basically
getting the bag to drop-off. Targeting ~10:13/mi. Looking to drop 5-10s/mi
at 16/17 and again at ~23/24 with a level effort sprint from ~26 - end.
0.25 Splits show closer to 10:00 with a substantial number < 10:00
1.00 Splits show closer to 9:55
Up through the half it felt like almost nothing. Best half ever at 2:12
(by 2-3min and effectively on pace). Paced back up to Rebecca (race partner I found on the
road) from 13.5 to around mi 17 (1min toilet). A couple of slightly
slower miles running recovery (10:16,10:20). Last 10K tried to pick up
to minimum 10:00/mi and had to dig to maintain. Last few miles felt
more hilly, walked water from cup to finished drinking on last 5Kish.
Took a walk towards the end of mile 24 ~ 30s for the final miles. From
~25.5 - end I pushed picking up speed to the line. Nearly tossed my
cookies at an avg of 7:27/mi for the last 1/4 mile.
Used Hammer Perpetuem orange and cafe late (caffeinated) at ~2 scoops/hr.
Concentrated to 1hr per-fuel belt bottle switching bottles at the half. Took a risk here going with a thinner concentration and adding in the new flavor w/caffeine without training with it.
After the south turn had some "cold stomach" and a few times a little
bit of stomach discomfort that passed relatively quickly. At this pace
water stops were about perfectly placed with generous portions (too
much at times). With 1hr fuel bottles I didn't take as much (or always)
water with fuel every 20. Last 10K reduced water consumption to ~2
swallows while running. ~3 while walking.
May have had tail wind on the south bound leg, definite head/cross wind
from ~22 felt very strong from ~24 (probably wasn't). Need to get
faster to finish before the wind picks up.
Had a 4-5 small slices of pizza and killed remaining fuel (very little,
good job staying on plan!) right after I crossed the line.
Hit the recoverite almost immediately after finish. Next time remember
blender bottle and don't freeze recoverite. Didn't thaw at all in race
bag. Mixed up emergency supply in bag and tore off the corner to drink.
Hit my legs with the T-roller while I sat and cheered people over the
line. Noticed after cheering for a string of people my HR elevated and
the tip of my nose was slightly numb. HR stayed elevated (in general)
and raising legs over head was good for nearly instant 20bpm drop. Went
to medical just in case and BP was generally normal.
Left foot and shin ache, muscles feel fine, achilles a little tight two
days on. Stairs seem like nothing (better training and recoverite?)
All gear worked out, wore disposable running gloves from Baltimore but
didn't dispose of them. New Nimbus 10, Halo hat, short shorts and LAWS
half shirt, L/R low cut socks, fuel belt, Garmin 305 and RoadID.
Switching bottles at the half was great, thinner fuel was easier to
take when I wasn't feeling as fresh. Tried mixing things up wearing headphones and listening to music for the first time in a race (I think it help me keep up the pace later).
May need a smaller fuel belt. This one starts to bounce half way
through longer runs (water weight loss slims me down?). Some inner
thigh chafing, think I lost some bodyglide taking off shell pants
before start. Blister on pad of 4th left toe, faster gait for longer
distance, different stride pattern due to shin and foot discomfort?
Forgot to put on sunscreen got a bit of sun not burnt and can't tell
anymore. Missed having C- on the course cheering glad she went fishing
with her Pop.
Other Thoughts:
I'm very glad I didn't try to go with the 4:30 pace group. They passed me around 2.2mi stuck with them for about .25 noticed the pace was closer to 9:18 than 10:18 and watched them disappeared into the distance. Caught up at the north turn around ~6.6 to hear the leader say oops, looks like we are a minute fast again as the remains of the group started walking. (In the end I see a group of people 4-5 finished right on 4:30 including the pacer but I think the group started much larger)
I ended up talking to a few people who noticed the 4:30:00 pace sign on my back who observed that they couldn't hang with the 4:30 group and got dropped out the back. I allowed that the group seemed way too fast and while I was running a bit faster than 10:18 targeting around a 10:13 that I would be happy for some company. This was how I found my race partner (Rebeca) from miles 4 - 22.
This is the first time that I strictly ran my own race. I picked a pace and a plan (and tried to stick to them). Went out on pace but ended up going faster than plan on the intervening miles even with checking my pace regularly and trying to adjust. Not surprisingly my pace kept drifting towards 9:45/mi which is a pace I currently find comfortable for medium to slightly longer distance runs. The music was OK, with non-isolation headphones I was holding conversations just letting the beat be some background noise. I would love to be able to have the otherwise identical race again sans music to see how it would have gone.
I need to thank my wife for putting up with me scheduling a last minute marathon in the middle of our thanksgiving vacation and all the neurosis that come with the last few days of pre-marathon prep. Not to mention needing to pack for a marathon on top of everything else. I also need to thank everyone from Potomac River Running and the Ashburn Area Running club for all the support and company on the road during training this year.

Powered by ScribeFire.
| //Script to count the total
number of requests received request_params = java.lang.reflect.Array.newInstance(java.lang.String, 6); request_params[0]="appName"; request_params[1]="hostName"; request_params[2]="serverName"; request_params[3]="serverPort"; request_params[4]="contextPath"; request_params[5]="servletPath"; nrequests = 0; function requestStartEvent(appName,hostName,serverName,serverPort,contextPath, servletPath){ nrequests=nrequests+1; client.print("js> New request received. Total count = " + nrequests + "\n"); } scriptContainer.registerListener('glassfish:web:http-service:requestStartEvent', request_params , 'requestStartEvent'); |

| //This script will calculate the
time taken by each request for an App //requestStartEvent request_params = java.lang.reflect.Array.newInstance(java.lang.String, 6); request_params[0]="appName"; request_params[1]="hostName"; request_params[2]="serverName"; request_params[3]="serverPort"; request_params[4]="contextPath"; request_params[5]="servletPath"; var startTime; var object = new Object(); var nrequestStartEvent=0; function requestStartEvent(appName,hostName,serverName,serverPort,contextPath, servletPath){ nrequestStartEvent=nrequestStartEvent+1; startTime = (new Date()).getTime(); //insert the request time in Map key = java.lang.Thread.currentThread().getId(); object[key] = startTime; client.print( 'Count: '+ nrequestStartEvent +'\n'+ 'Event: glassfish:web:http-service:requestStartEvent' +'\n'+ 'Application: '+appName+'\n'+ 'Host: ' + hostName +'\n'+ 'Server: ' + serverName +'\n'+ 'HTTP Port: ' + serverPort +'\n'+ 'Context Path: ' + contextPath +'\n'+ 'Servlet Path: ' + servletPath + '\n' + 'Current Thread: ' + java.lang.Thread.currentThread().getId() + '\n\n'); } scriptContainer.registerListener('glassfish:web:http-service:requestStartEvent', request_params , 'requestStartEvent'); //requestEndEvent request1_params = java.lang.reflect.Array.newInstance(java.lang.String, 7); request1_params[0]="appName"; request1_params[1]="hostName"; request1_params[2]="serverName"; request1_params[3]="serverPort"; request1_params[4]="contextPath"; request1_params[5]="servletPath"; request1_params[6]="statusCode"; var nrequestEndEvent=0; function requestEndEvent(appName,hostName,serverName,serverPort,contextPath, servletPath,statusCode){ nrequestEndEvent=nrequestEndEvent+1; key = java.lang.Thread.currentThread().getId(); startTime = object[key]; if (startTime == null) client.print("Error getting the startTime for thread = " + key); else delete[key]; totalTime = (new Date()).getTime() - startTime; //insert the request time in Map object[key] = startTime; client.print( 'Time Taken: ' + ((new Date()).getTime()-startTime) + ' ms\n' + 'Count: '+nrequestEndEvent+'\n'+ 'Event: glassfish:web:http-service:requestEndEvent' +'\n'+ 'Application: '+appName+'\n'+ 'Host: ' + hostName +'\n'+ 'Server: ' + serverName +'\n'+ 'HTTP Port: ' + serverPort +'\n'+ 'Context Path: ' + contextPath +'\n'+ 'Servlet Path: ' + servletPath +'\n'+ 'Status Code: ' + statusCode + '\n' + 'Current Thread: ' + java.lang.Thread.currentThread().getId() + '\n' + '\n\n'); } scriptContainer.registerListener('glassfish:web:http-service:requestEndEvent', request1_params, 'requestEndEvent'); |

In my unit tests I often want to know the name of the test that is executing. For example, I often want to have the golden file (expected test output) computed automatically from the testname. As another example in my JavaFX testing, I often generate screenshots inside failing tests and it's useful to name these screenshots by the failing tests.
In JUnit 3 this was simple, since your testcases would extend a builtin JUnit class which had a method you could call to return the current test. However, with JUnit 4 that's no longer possible. I've googled and found the "correct" way to do it - using a special @RunWith to run the test class - but I find that solution unsatisfying. My utility methods which are invoked to read golden files and screenshot etc are in one place and I now have to decorate all my tests. Besides, I already have a @RunWith annotation on my tests because I want to run them on the event dispatch thread so I have a special test runner for that.
So, I've found a better way to do it. Better for me I mean - this may have problems and limitations I'm not aware of, but for all of my tests this worked wonderfully, and doesn't have the @RunWith requirements (though note that I don't do multithreading in my tests, other than invoke them on the event dispatch thread, so if you try to call this from a thread that didn't invoke the test it probably won't work):
public static String getTestName() {
// Try to find a method on the stack which is annotated with @Test -- if so, that's the one
StackTraceElement[] elements = new Throwable().fillInStackTrace().getStackTrace();
for (int i = 1; i < elements.length; i++) {
StackTraceElement element = elements[i];
try {
Class clz = Class.forName(element.getClassName());
Method method = clz.getMethod(element.getMethodName(), new Class[0]);
for (Annotation annotation : method.getAnnotations()) {
if (annotation.annotationType() == org.junit.Test.class) {
return element.getMethodName();
}
}
} catch (NoSuchMethodException ex) {
} catch (SecurityException ex) {
} catch (ClassNotFoundException classNotFoundException) {
}
}// Just assuming it's the calling method
return elements[1].getMethodName();
}
TestUtils, which I statically import from my test cases such that I can simply reference the test name getter like I would in the JUnit 3 days:
import static org.junit.Assert.*;
import static my.package.name.TestUtils.*;/* ... */
screenshot(scene, getTestName());
public static File screenshot(Scene scene, String fileName) throws Exception {
BufferedImage image = (BufferedImage) scene.renderToImage(null);
if (!fileName.endsWith(".png")) {
fileName = fileName + ".png";
}
File file = new File(getScreenshotDir(), fileName);
file.createNewFile();
ImageIO.write(image, "png", file);
return file;
}
Presented by Jeremy Week at the Sun HPC Consortium in Portland, November 14, 2009. Recorded by Deirdre Straughan.
More presentations can be found at the Sun HPC Consortium site. Download for iPod
One of the many cool new features in Java EE 6, is support for the DataSourceDefinition annotation.
The DataSourceDefinition annotation provides a way to define a DataSource and register it with JNDI. The annotation provided annotation elements for the commonly used DataSource properties. Additional standard and vendor specific properties may also be specified.
So let us look at an example:
@DataSourceDefinition(name = "java:global/MyApp/myDS",
className = "org.apache.derby.jdbc.ClientDataSource",
portNumber = 1527,
serverName = "localhost",
databaseName = "testDB",
user = "lance",
password = "secret",
properties = {"createDatabase=create"}) )
The data source will be registered using the value specified in the name element and can be defined in any valid Java EE name space, determining the accessibility of the data source from other components.
The properties element is used to specify less frequently used standard DataSource properties as well as vendor-specified properties using the format :
{"property1=value", "property2=value" ...}
Using the newly defined DataSource is as simple as:
@Resource(lookup = "java:global/MyApp/myDS")
private DataSource ds;
You can also define multiple DataSources using the DataSourceDefinitions annotation:
@DataSourceDefinitions({
@DataSourceDefinition(name = "java:global/MyApp/myDS",
className = "org.apache.derby.jdbc.ClientDataSource",
portNumber = 1527,
serverName = "localhost",
databaseName = "testDB21",
user = "lance",
password = "secret",
properties = {"createDatabase=create"}),
@DataSourceDefinition(name = "java:global/MyApp/myDS2",
className = "com.mysql.jdbc.jdbc2.optional.MysqlDataSource",
portNumber = 3306,
serverName = "localhost",
databaseName = "dogDB",
user = "luckyDog",
password = "shhh",
properties = {"pedantic=true"})
})
So let's look at a simple web application, DataSourceDefWebApp, which utilizes the DataSourceDefinition. The application is provided as a NetBeans project that was created with NetBeans 6.8.
The application when deployed, will create a DataSource for Java DB.
When you go to run the application, you will need to make sure that you have the Java DB client JDBC driver accessible to your appserver, which it will be for Glassfish V3 and the Java DB server started.
To run the application after you have deployed it, go to the following URL using your favorite browser:
http://<host>:<port>/DataSourceDefWebApp
When you first run the application, you will see the following menu. Select the menu option "Initialize the Database", to create the Java DB database and create two initial contacts.

After initializing the database you can select "Add a Contact" to add a new contact to your database.

When you click the "Add Contact", button you will be taken to the displayContacts page.
,
The application defines the DataSource in the DataSourceDefServlet:
@DataSourceDefinition(name = "java:global/MyApp/myDS",
className = "org.apache.derby.jdbc.ClientDataSource",
portNumber = 1527,
serverName = "localhost",
databaseName = "testDB",
user = "lance",
password = "secret",
properties = {"createDatabase=create"})
@WebServlet(name = "DataSourceDefServlet", urlPatterns = {"/DataSourceDefServlet", "/displayContacts", "/addContact", "/initDB"})
public class DataSourceDefServlet extends HttpServlet {private ServletContext context;
@Resource(lookup = "java:global/MyApp/myDS")
private DataSource ds;
@Resource(lookup = "java:global/MyApp/myDS")
private DataSource ds;
You can also override the settings that you have specified in the DataSourceDefinition annotation by adding the data-source element to your web.xml. For example, in order to use a MySQL database instead of Java DB, you can create a web.xml and add the following (remember to adjust the properties as necessary):
<data-source> <description>DataSource for MySQL</description> <name>java:global/MyApp/myDS</name> <class-name>com.mysql.jdbc.jdbc2.optional.MysqlDataSource</class-name> <server-name>localhost</server-name> <port-number>3306</port-number> <database-name>testDB</database-name> <user>lance</user> <password>secret</password> <property> <name>x</name> <value>y</value> </property> <property> <name>y</name> <value>x</value> </property> <login-timeout>500</login-timeout> <transactional>false</transactional> <isolation-level>TRANSACTION_READ_COMMITTED</isolation-level> <initial-pool-size>2</initial-pool-size> <max-pool-size>5</max-pool-size> <min-pool-size>1</min-pool-size> <max-idle-time>500</max-idle-time> <max-statements>100</max-statements> </data-source>
In the top level directory of the DataSourceDefinitionWebApp, you will find a web.xml that you can move to the web/WEB-INF folder of the project. Adjust the properties for the data-source to correctly point to your MySQL database, then rebuild and deploy.
When you go to display the data, you will notice that the the output from displayContacts indicates thatthe database that is being used in MySQL
The DataSourceDefinition annotation is a simple yet powerful addition to Java EE 6. Enjoy!
References:
GlassFish v3 was released today, you can download it here. Part of the release includes a new version of the Admin Console. This blog discusses some experimenting done with Ajax in this release.
When we started planning for the GlassFish v3 Admin Console release, we set out to improve our UI design. One of our goals was to get rid of frames.
Each frame is treated as a separate document. This means the browser makes a separate request for each page (and the frameset page itself), often leading to loading the same script, css, and other resources multiple times. When using JS frameworks, and JSF components which require multiple images, and several other resources... the number of files requested from the server can be staggering for an application like the GlassFish v3 Admin Console. Sure, you can use expires headers and implement other caching techniques which help a ton, but don't entirely solve the problem.
The problem with using frames doesn't end with requesting too many files:
So for those reasons, and probably more, we resolved to not use frames in the GlassFish v3 Admin Console. Next, we thought we'd introduce "menus" and "tagging" to replace our tree -- giving us more real estate and modernizing the application a bit. However, feedback we got from the community (sarcastic: Thanks guys!) was loud and clear: keep the tree. So we were now left with very limited development time, a commitment to use our old Look & Feel (header, tree, and content frame), but a decision to move our application into the 21st century by ditching frames. So thanks to Jason Lee, we quickly whipped up a design leveraging the YUI Layout Manager. This gave our application the features of frames, without the baggage frames brings with it.
All was good again, right? Nope.
We had traded one set of problems for new ones, which mostly centered around performance. At this point we were loading the entire page for every click made in the browser. While a full browser page loaded much faster than before, each click now required everything to be loaded whereas before just the content frame was loaded. This meant our giant tree (that we wanted to remove) was haunting us every time we clicked a button / link, in addition to our page header and content area. Pages were taking 6-10 seconds on my (admittedly slow 4yr-old) laptop.
Ajax was not new to our team (nor do I expect it is new to most of you reading this blog -- if it is, you're probably reading the wrong blog). However, we had not used it too extensively in our application in the past (we generated bread crumbs, calculated a server restart message, and refressed tree nodes when server state changed). To solve our performance problem, we decided to Ajax was our best hope (or going back to frames -- and that was NOT going to happen!).
Here are some of the ideas we initially considered:
Approach #1 brought back some of the problems with frames (full document object again, duplicates some of the resources, JS across the iframe was complicated again), so we saved #1 as a last resort. #2 was very complicated -- especially if we had non-JSF content. While I still think this approach (implemented correctly) is one of the better approaches, it's not the most flexible or simplest approaches -- so we passed on it too.
We did try approach #3. The advantage of #3 over #1 is that the "page" has no visible frames so the frames problems #1 introduces were eliminated -- well mostly. When implementing #1, we ran into issues getting the JS copied over correctly and getting inline JS to execute properly. We were solving those issues, but it became clear that we were working too hard to get a good solution working. We abandoned this approach before we got all the kinks out.
Approach #4 didn't too promising, so we took on approach #5. This involved thinking of the 3 former-frame areas -- which I shall call "header", "tree", and "content" -- as separate pages. According to the browser, however, the three areas are simply 3 different <div>'s with HTML in them. On the first page requested by the browser, we make use of Facelet's ui:composition concept (albeit via JSFTemplating) to serve a page in a single request composed of all 3 areas. When the user navigates to a new "page", however, we make an Ajax GET request for the next page with a flag indicating that we don't need everything:
http://localhost:4848/common/applications/applications.jsf?bare=true
Each of our pages (in this case applications.jsf) uses the Facelets ui:composition to refer to the "default.layout" template. That template is responsible for deciding whether to send everything... or just the bare minimum. It does so with its 'template' property of its own ui:composition:
template="/templates/#{pageSession.bare == 'true' ? 'bareLayout.xhtml' : 'treeLayout.xhtml'}"
The bareLayout.xhtml file -- used when the bare=true flag is set -- sends back the bare minimum (it doesn't even send back the required .js files in most cases since those are already present in the browser). treeLayout.xhtml, as you've already guessed, sends back everything (FYI, we also used to have a "menuLayout.xhtml" file which used a menu system instead of a tree).
Back in the browser, the JavaScript used to handle the Ajax response gets invoked and we replace the old content area with the new stuff. It would be great if we were done at this point, however, this strategy requires each link (and button click) to be converted into an Ajax request -- so we iterate over the new DOM elements and modify them to make Ajax requests so they too can repeat this process.
Form submits are a slightly more complicated. We changed each button to invoke JavaScript which submits the data via JSF2 Ajax. However, JSF2 Ajax expects UIComponents to simply be "refreshed" and if you navigate or redirect a whole new page is shown -- meaning any tree/header stuff that you didn't want to get updated is lost. So, we had to override the JSF2 server-side behavior by telling JSF that the "PartialRequest" as not a "PartialRequest":
FacesContext.getFacesContext().getPartialViewContext().setPartialRequest(false);
This gave us complete control to return exactly what we wanted from the server. Although now that we've changed response format and are not really updating UIComponents, but instead a content area which represents a completely new JSF page in many cases -- we now had to replace the JSF2 JavaScript that handled the Ajax response. We were able to accomplish this by setting a custom function to the "onComplete" property of the "options" object that is passed to the JSF2 "jsf.ajax.request" function. In our custom function we had to de-queue the JSF2 request to help JSF2 maintain its state correctly (since the default JSF2 JavaScript was not going to be called). We were then able to swap the content area with the new content fromt the Ajax response. Phew! 
Instead of pages averaging 6-10 seconds, page requests are closer to 0.2 to 0.5 seconds!!
Fine print: I made a lot of other performance related improvements which may account for a large part of this improvement, and the server itself has increased in speed. However, the biggest impact was by far was implementing this Ajax strategy.
This blog is titled "The Ajax Experiment" because that's exactly what we did, but also because I don't think we're done learning. We ended up using Ajax in a very different way than what is proposed by frameworks like JSF2 (for which Jason and I are both EG members), so that makes me wonder how JSF2 should adapt to welcome this type of model. I know I'm far from the first to try something like this (look at Google Apps: docs, maps, wave, etc.), but having finally experimented with it myself, I think this is the path to the future of the web (but not the destination). Lets to continue to experiment and see where this leads us...
Ken
GlassFish v3 is Now Available!
Personally, I am very proud to this GlassFish V3 release.
We (as the whole GlassFish team and the community) have spend a lot of time working on this release. Besides, those new specifications, new features and better performances, "quality" is one of the most important area we all focus and concern. We want our community and customer have the latest Java EE 6 implementation for application development and then put into commercial use daily.
The whole team truly spend a lot of time and effort working towards one goal and we all deliver. We do our best. And if there is room to improve in any way, please give us valuable feedback.
From J2EE beta software release (1999) to now JavaEE 6 (2009), it is a long journey, and I believe we still have a long way to go forward.
Come and join us at http://glassfish.dev.java.net and also visit http://java.sun.com/javaee for more latest JavaEE news and more..........
Here are few url links:
The Aquarium Blog url:
http://blogs.sun.com/theaquarium/entry/glassfish_v3_is_now_available
GlassFish v3 - Download and get it now
https://glassfish.dev.java.net/downloads/v3-final.html
http://developers.sun.com/appserver/
http://developers.sun.com/appserver/downloads/index.jsp
http://java.sun.com/javaee/
http://java.sun.com/javaee/downloads/index.jsp
http://java.sun.com/javaee/6/docs/api/
http://java.sun.com/javaee/reference/code/
http://java.sun.com/javaee/6/docs/tutorial/doc/
Build more JavaEE 6 applications or just a simple web apps or even a php application using MySQL.......... And you could do more...........
Automated tests on milestone OO320m7 are finished. Automated testing team reported a 'green state' for all automated tests. Just a small problem in w_updt.bas bother the consistent picture of all platforms marked green in QUASTe. This issue wasn't easy to find but at the end we solved the problem in showstopper CWS 'jl146' with issue 107038. Depending on desktop respectively OpenOffice.org window size the document is middle or left aligned with automatic view layout (which is default). This lead to the problem sometimes the objects in writer document were drawn outside of the documents area by autotest. Finally we found and fixed it by correcting view layout before testcases run. Some additional minor fixes for more stability were also done in this CWS. Punctually with release of RC1 next week the autotests are expected to deliver a 'green state' on initial testrun.
Stay tuned for updates on this....



The January 2010 issue of Linux Journal is devoted to Ham Radio!
There’s a lot of software out there for amateur radio applications. But up to now most of it has been for Windows PCs. Which is strange, because amateur radio is really about doing things yourself, outside the box. For which Linux and the whole Open Source movement seems a natural. In fact, the lead article in the January issue of Linux Journal calls amateur radio the “first open source project”.
I just hope more ham radio software migrates over to Linux. I hate seeing some really exciting ham radio apps offered Windows-only. More and more apps are appearing for the Mac, which also seems more natural than Windows.
For example there are some really good apps for learning and exercising Morse Code. But most of the best are still on the PC/Windows. So I have to keep one system around with Win/XP just to run those apps. This is silly. I bet if the apps were written in Java they could run on any system.
Lets see more Linux apps out there.
GlassFish V3, the first application server in the world that supports JavaEE6 is released !!!! For the JDBC users, there are some great features introduced in the newest version of GlassFish.
New features
Flush Connection Pool
To reinitialize aged/old connections in a connection pool. There is no need to reconfigure the pool to kill/destroy live connections.
Ping
The existing Ping button in admin console and asadmin ping-connection-pool reveal the unsupported values of configured attributes of a connection pool only at the time of usage (or runtime). A pool configured with "ping" attribute identifies erroneous values at the time of creation of the pool.
java.sql.Driver based Pooling Support
Mainly for applications that use java.sql.Driver implementations, to configure non-compliant jdbc drivers.
Disable Pooling
Disable connection pooling by just setting a flag "pooling" to false. The existing system property com.sun.enterprise.connectors.SwitchoffACCConnectionPooling was useful only for application clients. This feature is for the non appclient pools.
Statement Caching
Cache Statement, PreparedStatement, CallableStatement objects executed repeatedly by applications to improve performance. Some JDBC drivers do not support caching and this feature comes in handy.
Custom Validation
Specify your own implementation for performing a connection validation. A custom implementation could be made available to the application server and used to perform validation when connection validation is turned ON. Validation routines could be performance oriented or database specific.
Init SQL
Execute a SQL query during connection creation. Mainly to set request/session specific properties.
Introspection of JDBC Drivers
A really useful feature that introspects and lists datasource/driver classnames based on the database vendor and resource type in the administration console. User does not need to remember the classnames anymore for a strange uncommon JDBC driver used with GlassFish.
Tracing SQL Statements
Trace SQL statements executed by your application using a jdbc connection pool. Administrators can filter the server.log for easier SQL statement analyses.
What has changed in GlassFish V3
Back in June I posted my initial entry on email time management with my intention of allocating time windows for email instead of spending all day on that alone. In August I posted some observations and a pie chart of the data so far.
As 2009 winds down, I now have about seven months of data so seems like a good time to revisit the numbers. I'll start with the bottom line, how much time went to what?
So the email timesuck has continued to be the problem it ever was, with 45% of the time between May to December spent on that alone. No matter how I slice it, that's really bad. My observations from the August entry are as valid as then. The relentless email firehose is hard to shut down so keeping it at a reasonable percentage of time is seemingly impossible. But at least segregating email reading into well-defined time windows during the day does help a great deal.
The really sad story in that pie chart is that the two slices which represent Real Work - the fun part of software engineering - add up to less than 10% of the total! The blue slice is Web Stack engineering work (8%) and the green slice is Web Server engineering work ( ploticus obscured the text but it's about 1.5%). So there you have it, about 90% of the time of a product architect/senior engineer at Sun is spent on email and overhead.
Put that way, those numbers are appalling beyond words. Clearly this must change, so I'm going to change it. Starting this week I will cut down email time down to 90-120 minutes a day (I've been doing well over three hours minimum) and start to prioritize Real Work higher on my task list above TPS report-kind of work.
Can this plan succeed? Well I guess you can read my update in a few months to see. I'm looking forward to a much more reasonably balanced pie chart...
Over the past several months I've been working on integrating our Sun Storage 7000 Appliances into monitoring products from other companies. The monitoring work I'm doing is a combination of software writing (via a plug-in for a data center monitoring product that will see it's release in conjunction with our next Sun Storage 7000 Appliance Software Release) and "consulting" with our customers directly about monitoring the appliances they install after purchase.
The Sun Storage 7000 Appliance comes with a variety of mechanisms for monitoring:
- SNMP (via several different MIBs using traps or GETs)
- Email Alerts
- Remote Syslog
A variety of software and hardware faults delivered internal to the system as Fault Management Architecture (FMA) events get pushed to the monitoring environment via the above mechanisms.
As valuable as these capabilities are, customers always have more advanced monitoring needs that require customization of the environment. Some customers want to tune the information available for significant digits, get more significant digits than we surface in the CLI, or gather data from our industry leading analytics capabilities delivered with the appliance. Some may want to integrate with an ITIL-style Configuration Management Database, others may want to create a billing system based on user capacity and accounting for levels of service (guaranteed space, thin-provisioned space, etc...).
All of these customizations can easily be achieved using simple SSH navigation of the appliance's environment or more advanced manipulation of the environment using the embedded JavaScript environment on each Sun Storage 7000 Appliance via scripts or Workflows.
Over the next few weeks, I'm going through my Email Archives (not a pretty sight to be honest) and I'm going to mine the greatest hits as I've sent out information to specific audiences on monitoring boxes and customizing the environment based on specific monitoring application use cases. Other articles will be focused on how I achieved the monitoring environment for the upcoming plug-in that will hit the download center with the next software release.
With all of that lead-in, I am going to kick off my monitoring guidance with what I tell everyone right out of the chute, "Use the Built-in Sun Storage 7000 Appliance Help Wiki to get up to speed on these topics and get the latest information". After all, this blog post will age with each release of the Sun Storage 7000 Appliance whereas the Help Wiki is updated with each release.
On a running Sun Storage 7000 Appliance, use the following URLs (substituting the address of the appliance where I put [hostname]):
You can download the latest Sun Storage 7000 Appliance Storage Simulator and follow these instructions as well.
In case the pages have moved, be sure to use the Search feature in the Help Text that comes with the Wiki.
There are always cases that customers want more hardcore examples tailored to environments of each of the above or a slightly different take on learning these topics. And that, my friends, is what the next few weeks will be about. I'll give more examples and approaches, similar to what I did with my Fun with the FMA and SNMP article.
![]() |
NetBeans 6.8 NetBeans 日本語コミュニティ |
SAP created benchmarks that measure transaction performance. One of them, the SAP SD, 2-Tier benchmark, behaves more like real-world workloads than most other benchmarks, because it exercises all of the parts of a system: CPUs, memory access, I/O and the operating system. The other factor that makes this benchmark very useful is the large number of results submitted by vendors. This large data set enables you to make educated performance comparisons between computers, or operating systems, or application software.
A couple of interesting comparisons can be made from this year's results. Many submissions use the same hardware configuration: two Nehalem (Xeon X5570) CPUs (8 cores total) running at 2.93 GHz, and 48GB RAM (or more). Submitters used several different operating systems: Windows Server 2008 EE, Solaris 10, and SuSE Linux Enterprise Server (SLES) 10. Also, two results were submitted using some form of virtualization: Solaris 10 Containers and SLES 10 on VMware ESX Server 4.0.
The first interesting comparison is of different operating systems and database software, on the same hardware, with no virtualization. Using the hardware configuration listed above, the following results were submitted. The Solaris 10 and Windows results are the best results on each of those operating systems, on this hardware. The SLES 10 result is the best of any Linux distro, with any DB software, on the same hardware configuration.
| Operating System | DB | Result (SAPS) |
|---|---|---|
| Solaris 10 | Oracle 10g | 21,000 |
| Windows Server 2008 EE | SQL Server 2008 | 18,670 |
| SLES 10 | MaxDB 7.8 | 17,380 |
(Note that all of the results submitted in 2009 cannot be compared against results from previous years because SAP changed the workload.)
With those data points, it's very easy to conclude that for transactional workloads, the combination of Solaris 10 and Oracle 10g is roughly 20% more powerful than Linux and MaxDB.
| Operating System | Virtualization | DB | Result (SAPS) |
|---|---|---|---|
| Solaris 10 | Solaris Containers | Oracle 10g | 15,320 |
| SLES 10 | VMware ESX | MaxDB 7.8 | 11,230 |
Some of the 36% advantage of the Solaris Containers result is due to the operating systems and DB software, as we saw above. But the rest is due to the virtualization tools. The virtualized and non-virtualized results for each OS had only one difference: virtualization was used. For example, the two Solaris 10 results shown above used the same hardware, the same OS, the same DB software and the same workload. The only difference was the use of Containers and the limitation of 8 vCPUs.
If we assume that Solaris 10/Oracle 10G is consistently 21% more powerful than SLES 10/MaxDB on this benchmark, than it's easy to conclude that VMWare ESX has 13% more overhead than Solaris Containers when running this workload.
However, the non-virtualized performance advantage of the Solaris 10 configuration over that of SLES 10 may be different with 8 vCPUs than with 8 cores. If Solaris' advantage is less, then the overhead of VMware is even worse. If the advantage of Solaris 10 Containers/Oracle over VMware/SLES 10/MaxDB with 8 vCPUs is more than the non-virtualized results, than the real overhead of VMware is not quite that bad. Without more data, it's impossible to know.
But one of those three cases (same, less, more) is true. And the claims by some people that VMware ESX has "zero" or "almost no" overhead are clearly untrue, at least for transactional workloads. For compute-intensive workloads, like HPC, the overhead of software hypervisors like VMware ESX is typically much smaller.
What does that overhead mean for real applications? Extra overhead means longer response times for transactions or fewer users per workload, or both. It also means that fewer workloads (guests) can be configured per system.
In other words, response time should be better (or maximum number of users should be greater) if your transactional workload is running in a Solaris Container rather than in a VMware ESX guest. And when you want to add more workloads, Solaris Containers should support more of those workloads than VMware ESX, on the same hardware.
Of course, the comparison shown above only applies to certain types of workloads. You should test your workload on different configurations before committing yourself to one.
SAP wants me to include the results:
Best result for Solaris 10 on 2-way X5570, 2.93GHz, 48GB:
Sun Fire X4270 (2 processors, 8 cores, 16 threads) 3,800 SAP SD Users, 21,000 SAPS, 2x 2.93 GHz Intel Xeon x5570, 48 GB memory, Oracle 10g, Solaris 10, Cert# 2009033.
Best result for any Linux distro on 2-way X5570, 2.93GHz, 48GB:
HP ProLiant DL380 G6 (2 processors, 8 cores, 16 threads) 3,171 SAP SD Users, 17,380 SAPS, 2x 2.93 GHz Intel Xeon x5570, 48 GB memory, MaxDB 7.8, SuSE Linux Enterprise Server 10, Cert# 2009006.
Result on Solaris 10 using Solaris Containers and 8 vCPUs:
Sun Fire X4270 (2 processors, 8 cores, 16 threads) run in 8 virtual cpu container, 2,800 SAP SD Users, 2x 2.93 GHz Intel Xeon X5570, 48 GB memory, Oracle 10g, Solaris 10, Cert# 2009034.
Result on SuSE Enterprise Linux as a VMware guest, using 8 vCPUs:
Fujitsu PRIMERGY Model RX300 S5 (2 processors, 8 cores, 16 threads) 2,056 SAP SD Users, 2x 2.93 GHz Intel Xeon X5570, 96 GB memory, MaxDB 7.8, SUSE Linux Enterprise Server 10 on VMware ESX Server 4.0, Cert# 2009029.
SAP, R/3, reg TM of SAP AG in Germany and other countries.
Addendum, added December 10, 2009:
Today an associate reminded me that previous SAP SD 2-tier results demonstrated
the overhead of Solaris Containers. Sun ran four copies of the benchmark on one
system, simultaneously, one copy in each of four Solaris Containers. The system
was a Sun Fire T2000, with a single 1.2GHz SPARC processor, running Solaris 10
and MaxDB 7.5:
The same hardware and software configuration - but without Containers - already
had a submission:
2005047
The sum of the results for the four Containers can be compared to the single result for the configuration without Containers. The single system outpaced the four Containers by less than 1.7%.
Second Addendum, also added December 10, 2009:
Although this blog entry focused on a comparison of performance overhead, there are other good reasons to use Solaris Containers in SAP deployments. At least 10, in fact, as shown in this slide deck. One interesting reason is that Solaris Containers is the only server virtualization technology supported by both SAP and Oracle.
So lets start talking about current identity issues.
The first that comes to mind is the us of Agent Smith, SOD (from the Separation of Duty Services Department).
Several months ago, there was a discussion about building "persona" on the web by my colleague Mark Dixon. This was as the rising tide of social networking was rising. Similar to a user account, which is prevalent inside the corporate firewall, the persona was instantiation of a user's , being across the web. Its "what you project you are" through your online presence, represented by the intersection of your different entities on the web.
So this got my attention. Not only are we the sum of our user accounts on emails, Blogs, Facebook, YouTube, Twitter, etc., but what we do with them. And most interesting is we can be what we choose to be. We can be what we are in person or we can "avatar" up our image to be what we want to project. Any online gamer knows "ColBiggles" probably doesn't have any military experience. But I can follow his progress, listen to his rants, read his prognostications and even talk directly to his disembodied voice without ever really knowing who or what is really driving the online persona.
This led me to think of Agent Smith from the Matrix movies, a rogue computer program that become sentient and keeps growing in power in the Matrix, learning and adding to his capabilities. Eventually, he becomes enemies with both the human and machine worlds.
So why bring this up in a blog about identities. Because this idea of persona can be used to help implement one of the hardest of identity projects, Separation of Duties. SOD policies are usually simple to dream up, but a devil to implement.
The idea is no one user should have certain combinations of attributes that allows that one user the ability to commit fraud or damage. The classic case is the ability to create a vendor in the accounts payable system and release payments to that vendor. Else, my cousin may suddenly find himself being sent sizeable checks to his fictious company to cash and enjoy.
Okay, simple. Set an SOD policy that says one user, regardless of how they acquired the abilities (via assignment or roles), cannot have that particular combination of entitlements or at least it is recorded as a exception for the auditors. Its fairly simple to do if the accounts payable system is the same enterprise system that releases the checks. But many times, SOD conflicts can occur accross systems.
The problem is trying to figure out if an enterprise has the correct SOD policies and monitoring in place. Imagine having to monitor a major bank IT operation of 8,000 different systems, 100,000's of entitlements across those systems. First is the daunting task of thinking of all the combinations of SOD entitlements and then building in the rules/policies into the provisioning, role management, and compliance systems to test and find these rogue users. Just standing it up the first time could be a career. And as entitlement management becomes more prevalent, this will only grow in significance and complexity.
And then remember that identity domains in the enterprise are amorphous. They are constantly changing. Users are coming and going, changing jobs, and the dreaded SOD scenario of transfer between business units (often requires them to have overlapping SOD capabilities until the transition is complete). New businesses are acquired, new systems are brought on line. Local admins add capabilities on the fly without seeing the bigger security picture Often, an SOD conflict is only discovered after the fact, after the venerability has been exploited.
And once the SOD fabric has been laid onto the identity topology of the enterprise, how do you test it. How can you be sure your systems are working? Most identity suites, including ours, have SOD monitoring in their compliance packages, not in their provisioning engines. So there is a built in lag where a user can gain SOD violation status and not be detected for a cycle when the compliance review is run.
Also, testing in production is tough to do. In staging, you can create an SOD situation for a user and test to see if the violation is flagged. But in production, if you create a SOD test on a production system, particularly on a SOX or HIPPA controled system, it becomes an auditing event. The security and audit teams will be notified and someone will have to remediate the condition. Up go the incident levels on your dashboards and everyone gets involved.
And lastly, even if everything is up and running 100%, how do you monitor if delegated administrators are doing their job during compliance reviews? The weakest link in any security system is the human factor. Had a situation recently dealing with a contracting manager who ran the third party bench of contractors. In the identity system, she had 384 direct reports with access to a variety of entitlements across the enterprise. For certification reviews, she had no idea, would do a "select all" and approve.
So how to test accross the production environment without sending up SOD violations to answer for? This is where Agent Smith comes in. Create a rogue user persona, a la Agent Smith, that everyone is aware of and knows is a non-existant user of the company's systems. Actually create this user account downstream of your HR system (the company would not want to fund healthcare or stock benefits to a non-existant employee) and use that one user account to test your controls and monitoring.
As new SOD policies are enacted, try and see if your Agent Smith can attain an entitlement status that triggers the monitoring policy. If the violation is triggered, security and auditing will realize, from seeing the Agent Smith persona as the violator, that it is a test account and will not raise an official violtion instance.
Also encourage delegated administrators to try and utilize the Agent Smith persona to improve its capabilities and entitlements. Have them have Agent Smith request access to systems they should not to see if the human approvers are doing their job. Anyone looing down the list of user entitlements should be able to pick out First Name: Agent, Last Name: Smith and deny them certification.
Granted Agent Smith, if properly treated as a real person, will consume real resources. They will get issued a laptop or email account, they will consume an ERP seat license, a MS Office allocation, etc. This could run into several thousands of dollars (what you would spend on a real human), but this is a small cost compared to an SOD violation. Well worth the investment.
And yes, you will have system admins, security, and auditing teams complaining about having a ficticious persona within their systems. But they will have to understand that for the good of the SOD review at an enterprise level, it is the only way to be sure.
But be forewarned. Just like the Agent Smith in the Matrix movies, it can take on a dangerous life of its own. Most SOD policies involve powerful entitlements and a malicious person could assume the Agent Smith persona (this is different from the movies where the Agent assimilated humans) and actually commit fraud using his capabilities. So, if you choose to unleash an Agent Smith, insure accees to that account is considered root level enterprise status. Only a few should have access to the login and insure the password is religiously reset on at a minimum a weekly basis. Be sure to test deactivating the good agent regularly and be ready to morph that one account at least once a year into Agent Jones or whatever to insure the good agent hasn't "gone rogue" within your enterprise systems.

I’ve been working on, and writing about, running Clojure Wide Finder code. But I was never satisfied with the absolute performance numbers. This is a write-up in some detail as to how I made the code faster and also slower, including lessons that might be useful to those working on Clojure specifically, concurrency more generally, and with some interesting data on Java garbage collection and JDK7.
[Update: My relationship with the JVM is improving, based on good advice from the Net. This article has been partly re-written and is much more cheerful.]
[This is part of the Concur.next series and also the Wide Finder 2 series.]
In a comment on my last piece, Alexy Khrabrov noted “I saw WF2 has a pretty good Scala result, apparently better than Clojure's — and that's a year-old Scala.” Alexy is right; my best times were mostly over 30 minutes, while Ray Waldin’s Scala code ran in under 15. There’s no obvious reason I can see why Clojure should be significantly slower than Scala, and while I stand by my Eleven Theses on Clojure, I was puzzled and irritated.
The following are organized roughly chronologically; if the narrative isn’t all that coherent, that would be an indicator of me having done considerable thrashing about.
The information you can get from the JVM with the
-Xprof argument is not brilliant, but it’s a whole lot better
than nothing. What you want to see in profiling output is a big fat obvious
culprit, and I did, and it was the code fragment below, which breaks up
buffers into lines; text is the text we’re wrangling,
first-nl and last-nl are the first and last places
where a newline character(whose value, note, is
10) appears in the block. destination is the user-provided
payload function.
(loop [ nl first-nl ]
(let [ from (inc nl) to (. text indexOf 10 from) ]
(if (< from last-nl)
(do
(destination (new String (. text substring from to)) accum user-data)
(recur to)))))))
This sucker was burning well over half of all the CPU. There are a few things wrong with it. First of all, since I was already using Java to split up the text, why not do it all at once like this?
(let [chunks (. #"\n" split text)
Yep, that helped. (I’d actually had it that way in a previous iteration but had unrolled it while fighting a memory leak that turned out to be unrelated).
Lesson: Any time you can package up a bunch of work as a single call into Javaland, that’s probably a good idea.
The second thing that was wrong was that I was iterating at all. Lisps
want you to think in terms of lists not their members, and I wasn’t.
What I was actually wanted to do was to call the payload function on each line
of text, passing the output of each invocation to the input of the next. And
of course Clojure, like any decent functional language, has a nice
reduce function. So let’s just add a line to that fragment:
(let [chunks (. #"\n" split text)
; ... turn "chunks" into "lines" by stripping leading/trailing fragments ...
accumulator (reduce per-line nil lines)
Lispers are now nodding their heads in a despairing
of-course-the-moron-should-have-done-it-that-way way. Me, I like it when a profiler
shows me where I’m being stupid. Some non-Lispers are probably thinking
“That’s slick”. Most modern languages, not just Lisps, have some sort of a
reduce equivalent.
I’m a bit amused here: this code has (basically) a map/reduce architecture,
except for I’m using reduce in the map phase.
Lesson: Operate on lists instead of iterating.
The code was now running visibly faster; time for another whack at the
profiler. I saw a whole lot of time being sucked up by
java.lang.Class.forName0. This suggested to me that the Clojure
runtime was spending a bunch of time trying to figure out
what type of thing was crossing some method-dispatch barrier. I already had a
wrapper around the user-provided payload function because it has three
arguments and reduce wants just two, and to protect myself from
Java
issue 4513622.
I seemed to remember from
somewhere that Clojure has “type hints”, so I looked that up and decorated the
wrapper:
(let per-line (fn [accum #^String line] (destination (new String line) user-data accum))
See that #^String goober? It’s a hint telling Clojure
to assume that the incoming line argument is a Java string.
It helped too, quite a bit. I was sort of irritated at having to hold
the system’s hand like this. But I think this may be a Release-1.0 symptom
rather than a Clojure design flaw. It feels to me like there’s quite a bit
more scope for type inferencing, maybe even JIT inferencing at run-time.
Lesson: A little static typing can go a long way.
My first cut at this problem used Java’s NIO subsystem; I’d noted that
java.nio.channels.FileChannel advertises itself as being
thread-safe and furthermore had a map() method for mapping stuff
into memory. So I had this pretty slick (I thought) setup where multiple
threads would just get dealt out an offset and block size and map successive
regions of the file, then do the string-i-fying and splitting.
I was twiddling buffer sizes and thread counts and not observing any real
helpful patterns and wondered if I was maybe overthinking the problem. So I
made another version that uses a Clojure agent to synchronize
sucking in the data with good old-fashioned
java.io.FileInputStream.read() and fires off a new thread for
each block. Right off the bat, it was faster.
Experimenting with this one seemed to suggest that it ran faster and faster
the smaller I made the buffers. I’d started with 64M and eventually went all
the way down to 2M; 1M wasn’t any faster. I hypothesize that with the big
buffers, the big String.split operation illustrated above was
creating too many short-lived transient objects that were overloading the
garbage collector.
Lesson: Disk really is the new tape.
Early on, when I was fighting a memory leak, Rich Hickey suggested using a smaller heap size. I did that, and was astounded.
I was now seeing throughput on the order of 50-60M/sec. But as I watched
the program run, I could see that as the program built up its heap to the
ceiling (set via java’s -Xmx argument), it was running much
slower, as slow as a tenth of that speed. When it hit the ceiling, absent
other pathologies, it would ramp up to production speed, I assume as the GC
got into balance with the rest of the program’s work.
Since it can easily take minutes for the JVM to expand to fill a 10G-or-bigger heap, you really can shave a couple of minutes off your run time by giving it a whole lot less. Yes, this is profoundly counter-intuitive.
Lesson: Measure, don’t guess.
At this point, I was starting to see run-times down well below fifteen minutes, and profiler output that looked like this (the primitive -Xprof facility gives you a little dump every time a thread exits, which turns out to work really well for me as I’m running through hundreds of ’em):
Flat profile of 29.63 secs (259 total ticks): Thread-58
Interpreted + native Method
0.4% 1 + 0 java.util.Arrays.copyOf
0.4% 1 + 0 sun.nio.cs.UTF_8.updatePositions
0.4% 1 + 0 java.lang.StringCoding$StringDecoder.decode
1.2% 3 + 0 Total interpreted
Compiled + native Method
57.1% 148 + 0 java.util.regex.Matcher.search
17.0% 1 + 43 java.util.regex.Pattern.split
8.1% 0 + 21 clojure.lang.APersistentVector$Seq.reduce
5.8% 3 + 12 java.util.regex.Pattern.matcher
3.1% 0 + 8 clojure.lang.ArraySeq.next
2.7% 0 + 7 clojure.core$conj__3121.invoke
1.2% 1 + 2 clojure.lang.PersistentHashMap$FullNode.assoc
0.8% 2 + 0 clojure.core$next__3117.invoke
0.4% 0 + 1 clojure.core$re_find__4554.invoke
0.4% 1 + 0 org.tbray.paralines$record__54.invoke
0.4% 0 + 1 clojure.core$assoc__3148.invoke
0.4% 0 + 1 clojure.lang.PersistentHashMap$BitmapIndexedNode.assoc
97.3% 156 + 96 Total compiled
Stub + native Method
0.8% 0 + 2 java.lang.System.arraycopy
0.8% 0 + 2 java.lang.Object.getClass
1.5% 0 + 4 Total stub
In other words, the program is spending most of its time using Java’s regex machinery to grind away at all that text input; which is I think what you’d like to see.
This was around 10PM last Friday, and I was crowing exultantly on Twitter, feeling like a rockin’ sockin’ functional-programming’ concurrin’ homoiconic wizard. “Faster than Scala” I uttered, incautiously.
Lesson: Read some Classics in transition from the archaic Greek and learn to fear the punishment for hubris, especially public hubris.
Because, you see, I was actually running a Wide Finder 1 program, just computing one little statistic, whereas Ray Waldin’s Scala code, and the others on the results page, were working on the benchmark from Wide Finder 2. It’s a lot more complex and computes five different statistics which require looking at a much higher proportion of the data.
Well, I thought, How hard can it be?
Lesson: [Never mind. We’ve all been there.]
I now have one, because it seemed like a lot more work than it should be to code this up.
The stats you want to compute could be called “hits”, “bytes”, “referers”,
“404s”, and “fetchers”. So I accumulated results in a map whose keys were
:hits, :bytes, :referers,
:404s, and :fetchers; the values were maps whose
keys were the URIs and values the in-progress statistics. So
if you want to add increment the :hits value for
some URI, you say:
(bump accumulator :hits uri 1)
Here’s the bump function:
(defn bump [accum stat uri increment]
(let [totals (accum stat)
currently (if-let [total (totals uri)] total 0)]
(assoc accum stat (assoc totals uri (+ currently increment)))))
In Ruby it’d all be a one-liner...
accumulator[stat][uri] += increment
...but then I’d be promiscuously mutating state and condemning myself to single-threadedness. Which is what this series is all about trying to avoid. On the other hand, it says exactly what I want to say without any ceremony or extra arm-waving. Is there a middle way?
Anyhow, here’s my gripe: I started sketching in the code to gather the five Wide Finder 2 stats Sunday while I was watching football. I spent all day Monday, until late in the evening, getting it all to work; admittedly, I’m a relative Clojure newb, but I’m not that terrible a programmer and I think I’m actually fairly quick at learning new things. This is way too long.
The result-merging step in particular gave me heartburn. If you can merge
two maps with Clojure’s elegant merge-with and you can turn a
list-or-vector into another list-or-vector with map, why can’t
you run a map on a map and get a
map?!?
Now, the situation wasn’t helped by the fact that Clojure is after all 1.0, so its tracebacks are not models of helpful transparency; also, the code is running in dozens of threads in parallel which made for extra work in tracking down where what provoked that NullPointerException or ClassCastFailure.
Lesson: Some combination of faults in Clojure and faults in your humble correspondent is interacting badly.
Improved, but not terribly satisfying.
The wrong collection of JVM options can drive this sucker
into Garbage-Collection hell. This is painfully obvious when it’s going on;
suppose you’re using a simple monitoring tool like top(1)
while you monitor the output, you
can see it trundling along processing 30 to 50 MB/sec and reporting a CPU
burn rate anywhere between 1200% and 3000%, which means you’re keeping all
the cores and threads pretty darn busy. Then all of a sudden the CPU drops
to around 100% and the output just stops. For like 90 seconds or more. If
you’ve picked a bad combination of options, this happens more and more
frequently until you’re spending way more time garbage-collecting than
actually computing.
[Update:] Someone who wishes to remain anonymous read the first version of this piece had a discussion with me about JVM options and suggested simply taking all of them out, except for -Xms and -Xmx to ensure there’s enough heap; letting it manage its own GC strategy.
This person turned out to be smarter than the tribal lore I’d picked up over the years and around the net, and I’ve managed to stay out of GC Hell for the last couple of days.
On the other hand, after all the profiling and adjusting, my code has grown tons of extrusions and decorations; here’s the bit that actually does the work of processing a line of logfile:
1 (defn proc-line [line so-far accum-1]
2 (if (nil? line)
3 (send so-far merger accum-1)
4 (let [accum-2 (if accum-1 accum-1 (new-accum))
5 fields (. #" " split line)
6 ; [client _ _ _ _ _ uri _ bstring status ref] (. #" " split line)
7 #^String uri-1 (aget fields 6) #^String uri (. uri-1 intern)
8 #^String status (aget fields 8)
9 accum-3 (if (= status "404") (bump accum-2 :404s uri 1) accum-2)
10 #^String bstring (aget fields 9)
11 accum-4 (if (re-find #"^\d+$" bstring)
12 (bump accum-3 :bytes uri (new Integer bstring))
13 accum-3)]
14 (if (re-find re uri)
15 (let [accum-5 (bump accum-4 :hits uri 1)
16 #^String ref (aget fields 10)
17 accum-6 (if (or (= ref "\"-\"") (re-find #"tbray.org/" ref))
18 accum-5 (bump accum-5 :referers ref 1))
19 #^String client (aget fields 0)
20 accum-7 (bump accum-6 :fetchers client 1) ]
21 accum-7)
22 accum-4))))
Boy, that ain’t pretty. At one point, I was pulling out the fields with
fragments like (get fields 6) but that led to some
XxxArrayAccessor method bubbling to the top of the profile output.
I attempted to replace that with “destructuring”, as in the commented-out Line
6, but that turns out to be just a macro that apparently generates about the
same calls.
I settled on aget, apparently specialized for fishing around
in Java arrays. But you still have to type-hint what comes out of it.
Feaugh.
In Line 7, you can protect yourself from our old friend 4513622 by either
calling new String on the uri, or by interning it, as above.
The former causes more memory stress but, if you can spare the memory, runs
faster.
Lesson 1: I’m not sure there’s a clear one here, but it makes me nervous when application code that should be simple is hard to get right, and so far Clojure’s not making this developer happy the way Matz designed Ruby to.
Lesson 2: The Concurrency Tax is too high.
Fallback hypothesis: I’m just Doing It Wrong.
I accidentally ran an experiment that showed me where a lot of my GC pain was coming from. Reminder: this works by having one Clojure agent read blocks sequentially and handing them off to threads to process, and build those tables of tables with the results. When each thread is done, it sends its table off to another agent to merge.
One time, I had a bug that turned the merger into a no-op, the agent was invoked all right but simply ignored the incoming table. This version ran very fast; not as fast as the simple Wide Finder 1 code I’d been working with earlier, but not bad at all, with a lot less GC overhead. So that code above may be ugly but it actually runs OK.
Here’s the code that does the merge:
(defn merger [current incoming]
(loop [keys (keys current) output {}]
(if-let [key (first keys)]
(let [merge-1 (merge-with + (current key) (incoming key))]
(recur (rest keys) (assoc output key merge-1)))
output)))
It’s iterating all right, but only over the keys of the top-level map, of
which, remember,
there are only 5: :hits, :bytes, and so on. Not
much to it, and reasonably idiomatic I think. But boy does it ever generate
garbgae.
I note that in Ray Waldin’s
nicely-performant Wide Finder 2 code he relied on a
java.util.concurrent.ConcurrentHashMap. I suppose it’s
unsurprising that that would outperform the sort of pure functional/dynamic
code above, but it feels a bit like cheating.
My best times for the full WF 2 run are now around 30 minutes. 29:38 with JDK7, 35:10 with Java 6. The results of tinkering with GC options and generation sizes and so on seem insignificant-to-damaging. In particular then new “G1” garbage collector in JDK7 doesn’t seem appropriate for this problem.
Use a ConcurrentHashMap like Ray did.
Bring VisualVM to bear on the problem and really do a deep-dive on what’s happening inside this code.
Try refactoring the app some more.
I dunno. I still like Clojure and stand by my 11 Theses, but that impedence mismatch with my conventional procedural object-oriented programer’s mind grows fatiguing.
GlassFish v3 est désormais disponible en version finale et du coup Java EE 6 est lui aussi désormais final (depuis les votes récents, il manquait l'implémentation de référence et le TCK, c'est maintenant chose faite!).
Bien entendu il y a le support complet de Java EE 6 (ejb 3.1, jax-rs 1.1, jsf 2.0, cdi 1.0, etc...) et son profil web (40MB tout mouillé) qui apporte une flexibilité à tous les serveurs d'applications qui en ont besoin, mais il y a beaucoup de choses dans GlassFish v3 qui vont bien au delà de la spécification et du rôle d'implémentation de référence. Il y a les fonctionnalités pour le développeur (temps de démarrage hyper-rapide) et préservation de session sur redéploiement (lui aussi très rapide), son coeur HK2/Grizzly et ses fonctionnalités, la modularité et le support de OSGi (Apache Felix par défaut), le système de packaging IPS (à la apt-get) et son update center, le monitoring basé sur Btrace, ou encore son support dès maintenant dans les trois outils de développement qui comptent: NetBeans, Eclipse et IntelliJ.
Cette sortie du produit c'est selon moi le début d'une nouvelle ère à plusieurs égards. Bien entendu il y a cette nouvelle architecture modulaire qui donne à GlassFish un pérennité technologique que d'autres produits concurrents nous envie, mais c'est aussi un aboutissement d'une histoire mouvementé des serveurs d'applications chez Sun. Je suis rentré il y a 10 ans chez Sun avec pour objectif de "vendre" du NetDynamics (on ne parlait pas de J2EEà l'époque), un produit leader sur son marché et racheté par Sun. Quelques mois plus tard AOL rachète Netscape et Sun hérite du serveur d'application du même nom (lui aussi avec beaucoup de parts de marché) et qui sera finalement choisit au détriment de NetD. S'en suivent les années iPlanet, mauvais souvenirs d'un mauvais produit et beaucoup de projets avec BEA WebLogic...
Avec Sun Application Server 7, c'est un vrai reboot technologique qui sera complété par l'approche Open Source de GlassFish en 2005. La route fût longue (détails ici), beaucoup avaient enterré Sun (difficile de leur en vouloir) sur ses chance de survivre dans ce marché. Le renaissance se sera faite au prix d'un effort important en trois étapes: GlassFish v1 en 2006 (conformité à Java EE 5 et Open Source), GlassFish v2 (qualité des produits commerciaux au prix de l'open source), GlassFish v3 (innovation et business model en place). Le parallèle entre GlassFish et J2EE/JavaEE est d'ailleurs frappant. Les critiques étaient sévères (et méritées) dans les années 2000-2006 avant que Java EE 5 et GlassFish ne viennent changer radicalement les avis. Bien entendu la question de l'avenir sous un bannière potentielle Oracle se pose maintenant. Si vous ne l'avez pas déjà fait, je vous invite à lire le passage qui concerne GlassFish dans cette FAQ d'Oracle. Coté Java EE non plus je pense qu'il n'y a aucun souci à se faire.
Vous devriez voir dans les prochaines 24 heures tout le florilèges des annonces de presse, des articles, de posts sur twitter, des blogs (entre autre par Sun que vous pouvez suivre avec les balises glassfishv3 et javaee6), et autres commentaires. Pour vous faire votre propre idée, téléchargez donc GlassFish v3 maintenant! Enfin, je vous invite à ne pas oubliez la conférence virtuelle Java EE 6 / GlassFish v3.
To celebrate the GlassFish v3 launch, I've posted the following three GlassFish Podcast episodes :
• Episode #038 - Java EE 6 released! Interview with Roberto Chinnici
• Episode #039 - GlassFish v3 is out! With tooling! Interview with Ludo Champenois
• Episode #040 - JSF 2.0 discussion with Ed Burns and Roger Kitain
I have at least one more coming up tomorrow (most likely).
Now be careful with this, but here is a simple bash shell script that will do Mercurial hg commands on a forest pretty quickly. It assumes that the forests are no deeper than 3, e.g. */*/*/.hg. Every hg command is run in parallel shell processes, so very large forests might be dangerous, use at your own risk:
#!/bin/sh
# Shell script for a fast parallel forest command
tmp=/tmp/forest.$$
rm -f -r ${tmp}
mkdir -p ${tmp}
# Only look in specific locations for possible forests (avoids long searches)
hgdirs=`ls -d ./.hg ./*/.hg ./*/*/.hg ./*/*/*/.hg 2>/dev/null`
# Derive repository names from the .hg directory locations
repos=""
for i in ${hgdirs} ; do
repos="${repos} `echo ${i} | sed -e 's@/.hg$@@'`"
done
# Echo out what repositories we will process
echo "# Repos: ${repos}"
# Run the supplied command on all repos in parallel, save output until end
n=0
for i in ${repos} ; do
n=`expr ${n} '+' 1`
(
cline="hg --repository ${i} $*"
echo "# ${cline}"
eval "${cline}"
echo "# exit code $?"
) > ${tmp}/repo.${n} ; cat ${tmp}/repo.${n} &
done
# Wait for all hg commands to complete
wait
# Cleanup
rm -f -r ${tmp}
# Terminate with exit 0 all the time (hard to know when to say "failed")
exit 0
Run it like: hgforest status, or hgforest pull -u.
As always should any member of your IMF forest be caught or killed, the secretary will disavow all knowledge of your actions. This tape will self-destruct in five seconds. Good luck Jim.
-kto
Many thanks to my good friend Jonathan Gershater for sending me the link to another excellent post about Identity and Healthcare. I particularly like his illustration of using Federated Identity to facilitate trusted exchange of medical records between different medical service providers.
A user of any (Healthcare) ServiceProvider, who has been issued a digital identity by the trusted IdentityProvider, may seamlessly interact with the healthcare providers (SPs). The user will present the digital identity issued by the IdP, the SP will verify the Identity, and the user will be granted access to the Service Provider’s application. However, based on the user’s attributes and role, the functionality available to the user will vary. A physician may alter a medical record but only within their specialty ( a dermatologist cannot alter a prescription for spectacles). A pharmacist may view but not alter the prescription for insulin in a healthrecord. A patient may only view but not alter their medical record.
Jonathan Gershater recently published an interesting blog post exploring the conceptual differences between the National Health Information Network (NHIN) infrastructure, “a collection of standards, protocols, legal agreements, specifications, and services that enables the secure exchange of health information over the internet,” and an alternate approach known as the Health Internet, “an open-market standards-based approach to enable the exchange and sharing of electronic health data, using existing Internet standard protocols and web technologies.”
Jonathan referenced two informative posts on The Health Care Blog and Practice Fusion’s blog. I’m still trying to wrap my mind around the significance of these two architectural directions, but it certainly appears that Identity is a critical part of the solution, regardless of what alternative approach or derivatives thereof may emerge. Any Electronic Health Record (EHR) system must be based upon secure, flexible and scalable Identity Management system.
Thank, Jonathan, for the excellent reference.
Last week I had a stimulating conversation with Jim Kinchley and Chris Madsen, executives of Trufina, a “provider of online identity verification and identity management services, enabling individuals to verify their identity attributes online, and providing the identity management tools for sharing that verified identity information with individuals and websites across the Internet.”
In October, I posted an article entitled Identity Trend 4: Identity Assurance, one of a series of posts about important trends in the Identity Management industry. In that post I proposed, “With the continual expansion of online fraud and other threats to online security and privacy, the need for Identity Assurance methods are rising. Being able to certify the that the correct Identity credentials are issue to the correct user before access is attempted is an increasingly critical issue.”
A few days after I authored that post, I became aware of Trufina, signed up for an account, paid a small fee, and had my Identity verified through a series of online questions drawn from publicly available information about me that presumably only I would know. As evidence of that successful vetting process, I posted a Trufina badge on this blog (see right column). This badge visually represents that my identity had been verified by Trufina, and provides a way that blog visitors could request a Trufina ID Card with details I elect to share. Do you want to see how it works? Please click on the Trufina badge or click here, enter your email address, and I’ll send you a link to see my Trufina-verified Identity Card.
Trufina provides a public API to allow websites to take advantage of Trufina identity validation services. For example, the Naymz online Professional Reputation Network allows members to link their Trufina Verified ID to the Naymz profile. In such a case, the Trufina Verified ID badge is shown on the Naymz member profile. I don’t use the Naymz network as extensively as LinkedIn or Facebook, but neither of those more popular social networks have validated my Identity as well as Naymz has done, thanks to the Trufina process.
I look forward to seeing how Trufina progresses in the marketplace. We really need a critical mass of easily accessible, yet secure, Identity validation services to increase the level of trust and confidence in online relationships.
As promised I’ve posted a straw-man proposal to extend Java with first-class functions, function types, and lambda expressions (informally, “closures”) to the newly-created Project Lambda page.
Please direct further comments, questions, and suggestions to the lambda-dev mailing list. (If you haven’t already subscribed to that list then please do so first, otherwise your message will be discarded as spam.)
As you can imagine, there has been a lot of activity in the blogosphere resulting from our launch today of Java EE 6 and GlassFish v3. A sampling:
Today we released Java EE 6 and the Java EE 6 SDK. In addition, we've also released GlassFish Enterprise Server v3, the first Java EE 6 compatible application server.
This is the culmination of over 3 years of work by many members of the JCP, community, and engineers at Sun and other companies that have contributed to the specifications and implementations of them, and interestingly comes nearly 10 years to the day since J2EE 1.2 was released in December of 1999. My thanks go to all involved, particularly the members of my team that made this all possible.
Naturally, one might ask, why is this important? You can see the Java EE 6 and GlassFish Enterprise Server v3 press releases for more details, but I'll highlight some of the important things here.
Java EE 6 is important for many reasons, not the least of which is that it continues the development, maturation, and innovation of the standard for enterprise Java development. Past releases of Java EE have continued to add few features and capabilities from servlets, EJBs, and JMS in early releases, to rich Web services support and ease of development features like annotations and EJB 3.0 in Java EE 5 three years ago. Java EE 6 continues to add new features like RESTful Web services, dependency injection, and annotation additions for Servlets further reducing the amount of code a developer must write, but also aims to provide a more extensible and more flexible platform through the introduction of profiles and pruning.
With the Web Profile, there is now a standard set of components defined as part of the specification that will allow compatible implementations optimized for modern Web applications where the full Java EE stack is not required. This will result in lighter weight servers requiring fewer resources that start in a fraction of time past Java EE servers have required.
But a fantastic specification is of little use without a commercial product being available that customers can confidently deploy their applications to knowing that it is ready for such use and that has the backing of an organization ready to support it. This is why GlassFish Enterprise Server v3 is so important, as it is available today, at the same time as the SDK. And with the introduction of the GlassFish v3 Web Profile, developers and organizations can use a platform optimized for modern Web applications while at the same time knowing they are using a standard and product that will allow them to move up to full Java EE 6 at any time without requiring any changes or re-implementation.
While a straight forward implementation of Java EE 6 would be very valuable given the strides it has made, GlassFish Enterprise Server v3 goes much further in a number of areas. These include a modular runtime based on OSGi providing for a faster startup and loading of only those components that are required, the ability to run containers for other languages like JRuby and Jython, an Update Center for updating components and adding new components through an easy to use console, and new iterative development features that enable and edit->save->refresh development cycle for Web applications where redeployment is not required and session state information is preserved.
But realizing the benefits of a great server is only enhanced when you have great tooling. That is why the announcement of the release of NetBeans 6.8 is also very important, as just like GlassFish is providing a full commercial Java EE 6 implementation at the same time as the SDK is released, NetBeans is also providing full support for Java EE 6 with this new release. For those that prefer Eclipse, there is also a new GlassFish Tools Bundle for Eclipse that has been enhanced to add support for Java EE 6.
I can only write so much in a blog entry, and those that have made it this far are probably interested in learning more, and so I'm also pleased to announce that there will be an on-line virtual conference next Tuesday December 15th. Please visit the registration page to sign-up and prepare to participate in a number of sessions covering a summary of what is in Java EE 6 and GlassFish v3 as well as detailed sessions on EJB 3.1, JPA 2.0, JSF 2.0, OSGi, and much more. The spec leads and other developers and experts will be on-line to answer your questions as well.
In summary, visit our Java EE 6, GlassFish v3, and NetBeans 6.8 sites to learn more and download the bits, and register for the conference to take advantage of the information and access that will provide you. We are confident you will like what you see!
| ProbeProvider as a class import org.glassfish.external.probe.provider.annotations.*; import org.glassfish.external.probe.provider.StatsProviderManager; import org.glassfish.external.probe.provider.PluginPoint; @ProbeProvider (moduleProviderName="glassfish", moduleName="samples", probeProviderName="ProbeServlet") public class ProbeServlet extends HttpServlet { @Probe(name="myProbe") public void myProbe( @ProbeParam("probeArg") String s) { if (StatsProviderManager.hasListeners("glassfish:samples:ProbeServlet:myProbe")) System.out.println("Firing the probe (listener(s) exist): " + s); else System.out.println("Listeners Doesn't exist, the probe will not be fired: " + s); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { myProbe("Hello #" + counter.incrementAndGet()); |
| ProbeProvider as an xml <probe-provider moduleProviderName="glassfish" moduleName="samples" probeProviderName="ProbeServlet" > <probe name="myProbe" <class>com.sun.samples.ProbeApp.ProbeServlet</class> <method>myProbe</method> <signature>void (String)</signature> <probe-param type="String" name="probeArg"/> <return-param type="void" /> </probe> </probe-provider> |
| @ManagedObject public class MyProbeListener { private CountStatisticImpl requestCount; public MyProbeListener() { requestCount = new CountStatisticImpl( "RequestCount", StatisticImpl.UNIT_COUNT, "Request count"); } @ManagedAttribute(id="requestCount") public CountStatistic getRequestCount() { return requestCount; } @ProbeListener("glassfish:samples:ProbeServlet:myProbe") public void probeListener( @ProbeParam("probeArg") String s) { requestCount.increment(); System.out.println("PROBE LISTENER HERE. Called with this arg: " + s); } |
| Registering
a
StatsProvider Object public void init() throws ServletException { try { StatsProviderManager.register("web-container", PluginPoint.APPLICATIONS, "myapp", new MyProbeListener()); } catch(Exception e) { throw new ServletException("Error initializing", e); } |
| Making your App an OSGI bundle ... <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.1-alpha-2</version> <configuration> <archive> <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile> <manifestEntries> <Bundle-ClassPath>WEB-INF/classes/</Bundle-ClassPath> </manifestEntries> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <version>2.0.0</version> <configuration> <supportedProjectTypes> <supportedProjectType>jar</supportedProjectType> <supportedProjectType>bundle</supportedProjectType> <supportedProjectType>war</supportedProjectType> </supportedProjectTypes> <instructions> <Probe-Provider-Class-Names>com.sun.samples.ProbeApp.ProbeServlet</Probe-Provider-Class-Names> <DynamicImport-Package>org.glassfish.flashlight.provider</DynamicImport-Package> <Web-ContextPath>/prober</Web-ContextPath> <Private-Package>com.sun.samples.ProbeApp.ProbeServlet</Private-Package> </instructions> |







| Javascript example (appRequest.js) var nRequests=0; function requestReceived(probeArg) { nRequests = nRequests + 1; client.print( '\n js> Request received event called, ' + ' arg= ' + probeArg + ' and count = ' + nRequests); } params = java.lang.reflect.Array.newInstance(java.lang.String, 1); params[0]="probeArg"; scriptContainer.registerListener('glassfish:samples:ProbeServlet:myProbe', params, 'requestReceived'); |

Today we are releasing GlassFish v3 (community) and Sun GlassFish Enterprise Server v3 (commercial), following the release of Java EE 6 a few days ago. Java EE is 10 years old - nearly to the day. GlassFish v3 - the project - is 4.5 years old (although the code base for GlassFish v3 is much older).
We've come a long way with GlassFish v3, and there are quite a few "firsts" in this release (correct me if I'm over zealous - I'm living on caffeine right now):


| TO: |
Sun
Microsystems Potential or Current Auto Service Request (ASR) Customer |
|||
| RE: |
YOU'RE
INVITED: Sun Microsystems Auto Service Request (ASR) Customer Information Forum |
|||
| DATE: |
Wednesday,
November 11, 2009 |
|||
| QUESTIONS: |
Sun Microsystems Auto Service
Request (ASR) Inquiries |
| Auto
Service Request, or
ASR (as we commonly refer to the technology), is designed to automate
the creation and routing of your Service Requests on qualified storage
and server products. Through the use of telemetry and fault information
directly from the device, we are able to more quickly troubleshoot and
resolve issues - saving you time and cost while also improving your
overall service experience with Sun. To learn more about ASR, click here and take a minute to review
the attached letter that contains additional information for our
customers.
We want to
ensure you are aware of the benefits and latest developments of ASR. You are invited to attend an
upcoming Sun
Microsystems Auto Service Request (ASR) Customer Information Forum.
The objective of these sessions is to review the ASR technology with
you in an open forum with a variety of customers and to provide you
with an opportunity to ask questions about ASR connection. The Sun Microsystems Auto Service
Request (ASR) Customer Information Forum sessions are scheduled
as follows to accommodate customers across the globe:
To
help us plan accordingly, we ask that you register for one of the
sessions at first opportunity (by Monday, November
16, 2009 if you plan to attend the Wednesday, November 18, 2009 session)
via the
above individual session links. You will receive
additional meeting details upon registration. If you have any questions about the Sun Microsystems Auto Service Request (ASR) Customer Information Forum sessions, please contact us. We look forward to your attendance and participation at an upcoming forum. Regards, Sun Microsystems Auto Service Request (ASR) Team |
Today marks the release of GlassFish v3.0 which complies with the Java EE 6 specification! Other postings highlight a number of other areas. I'll talk briefly about the app client container (ACC) in v3. Much of this information appears in the release notes accessible from the main v3 page as well, but here it's all focused on the ACC.
The v3 ACC is feature-compatible with the v2 ACC. You should see no difference in functionality, whether you launch using the appclient script or the built-in Java Web Start support...except for some exceptions I've described below. Below I've noted a few highlights that users might find useful or interesting: stricter access from clients to other JARs in the EAR, a change in the downloaded file format, and the new embeddable ACC.
Stricter JAR Access
The Java EE 6 spec imposes stricter rules than Java EE 5 about what JARs in an EAR an app client should have access to. In v2 an app client would see EJB modules as well as any JARs at the top level of the same EAR. In v3 this is no longer true by default when you deploy an EAR. You can add elements to the client manifest's Class-Path to refer to such JARs, or for library JARs move them to the library directory in the EAR (/lib by default or settable using the <library-directory> element in the application.xml).
You can request the older, v2 behavior by specifying --property compatibility=v2 on the deploy command when you deploy an app. Note that if you have deployed an app under v2 and then use the upgrade tool then v2 compatibility happens automatically.
Downloaded File Changes
When you deploy an app and specify --retrieve localdir, or use the get-client-stubs command, GlassFish downloads not just the app client but other application files the client needs -- such as library JARs and some files GlassFish generates. In v2 GlassFish would group all of these files into a single, large JAR file and download that. Then, as the first step in any app client launch, the ACC had to expand that large JAR file into a temporary directory before it could start the client. GlassFish v3 does not package all these files into a single large JAR. Instead, GlassFish downloads these files individually into a subdirectory below the directory you specify on the deploy or get-client-stubs command.
This helps the ACC launch the client faster, because there's no need to expand any files first.
You still launch the client using the exact same command as in v2. For example, if you deploy myApp.ear which contains the app client myClient.jar, then in v3 as in v2 you launch the client using
appclient -client downloaddir/myAppClient.jar
Note: We have never officially published or documented the format or content of the downloaded directory, but in v2 some users have copied downloaded app clients by simply copying the single downloaded myAppClient.jar file. This no longer works in v3. Instead, use the get-client-stubs command to download the client files to the new location.
Embedded ACC
Beginning in v3 you can "call" the ACC from inside a running Java application of your own. (For many users the appclient command or the built-in Java Web Start support will continue to meet their needs.) The functional spec for the v3 ACC described the API, as does the published javadoc, but the basic programming model is that your application creates an app client container builder, invokes methods on that builder to configure the app client container (security, etc.) then gets the app client container from the builder. Your application can then pass the app client to be run to the just-configured ACC's launch method, and the client class starts with the full support of the ACC behind it.
In fact, the appclient command implementation itself uses the embedded ACC API.
JSF Component Authoring Made Easy
Frustrated with the complexities of writing a JavaServer Faces component? Jason Lee and I wrote an article which was published on Java.sun.com earlier this month and is now featured on the homepage. While it's still on the homepage, you can find it here:
Or you can access it directly:
http://java.sun.com/developer/technicalArticles/J2EE/jsf_templating/
Try it out and send me your feedback, I'd love to hear what you think!
I would like to especially thank Rick Palkovic for his great editing skills and making the article look and sound good. Thanks Rick!
If you're at JavaOne 2008 you've probably already heard about the "Plug into GlassFish v3 Contest". I'm going to give a few hints here to help get you started.
First, attend the "Plugin into GlassFish with JavaServer Faces and jMaki" lab. Unfortunately this lab is difficult to get into, but don't worry! If you are unable to attend the lab on Wednesday night from 6:30PM - 8:30PM, you can visit booth #175 and ask for a copy of the lab. You can then do the lab exercises on your own time. Or, if you attend another Hands-on Lab during JavaOne 2008, you can find the GlassFish plugin lab on the DVD (lab #4520).
Ok, now that you've worked on the lab, let me point out a few important things you need to know to be successful.
If you get stuck, get help. You can post a question on this blog, email [email protected], or visit the GlassFish Pod #175. We'll be happy to help get you unstuck.
For those of you not at JavaOne, you won't be able to participate in this contest, however, this may be a good way to contribute to GlassFish. By contributing to GlassFish you may qualify for the GlassFish Awards Program. Check the GAP program rules for details and earn your share of the $175,000.
Good luck!
Today, along with the announcement of Sun GlassFish Enterprise Server 2.1 (docs, download), Sun is pleased to announce Sun GlassFish Enterprise Manager!
Sun has lead the GlassFish community in delivering fully documented, full featured, production quality enterpise software -- for no cost. In addition, Sun has offered valuable support contracts for indemnification and help beyond that provided by the GlassFish community; it's great to have someone to call when you really need help! Sun GlassFish Enterprise Manager just upped the value of purchasing support with the introduction of tuning and self-management tools.
I was privileged to help devleop the Performance Advisor "Tuner" feature of the Enterprise Manager. The Tuner typically improves performance by 300% or more, and on Sun's CoolThreads hardware the performance gain can be greater than 600%! The performance tuner does this by taking into account the hardware configuration, and how it is used. It then recommends configuration changes that will improve your system's performance. Here's what the tool looks like:
As you can see, the UI is intuitive with lots of inline help to guide you. Your hardware will be automatically inspected to see if you have a homogeneous environment (a cluster of like-hardware machines), if not, you'll be informed about customizing specific instances which have different numbers of cores, RAM, etc. Reasonable defaults are pre-populated in the form, making it easy to know approximately what the correct response is likely to be. After you are satisified, click "Next" and you are presented with the list of recommendations. This includes the steps required to manually apply the changes if you'd rather do it yourself versus allowing the Tuner to do it for you. If you let the Tuner to do it, it is kind enough to backup your old configuration so you can compare -- or revert -- your original settings. Many of the settings are configured with "tokens" which can be independently configured per instance in your cluster -- making settings easy to modify for machines which need special settings.
That's it... it really is that simple. After the changes are applied, you can enjoy tremendous performance gains. The Sun GlassFish Enterprise Manager Performance Tuner is a must-have for anyone deploying serious applications with GlassFish.
To learn more, check out Anissa's screencast of the Performance Advisor features. This includes a Performance Tuner demo, plus many of the other features in the Enterprise Manager product.
Enjoy!



).
So... as you can see we're not looking for bugs, but rather general feedback on the navigation and Look-and-Feel. So post your thoughts and help make GlassFish better. 
Thanks for taking a look!
JaveOne is 1 week away! Hurray! What are you going to be doing at JavaOne? Reply with what you're looking forward to seeing at JavaOne, I'm curious. 
One cool thing during JavaOne that I suspect many people didn't know existed, are the Hands-on Labs. Everyone knows about the traditional sessions where you hear a good (usually) speaker talk about an interesting topic (or where you can relax and check email in peace). However, the Hands-on Labs are the hidden treasure of JavaOne.
The Hands-on Labs take a topic and let you learn about them by doing. Topics range from several JavaFX labs (REST, WebServices, Mobile, and more), to cloud computing, to SIP applications, or the lab that I co-authored: Building OSGi Plugins for the GlassFish v3 Administration Console. Each lab is either presented in a Bring Your Own Laptop (BYOL) format, or has machines already configured with the lab software ready to go at JavaOne. Regardless of format, they provide step-by-step instructions on how to complete the lab.

The building OSGi plugins lab that I helped write shows how the GlassFish Admin Console web application was written to take advantage of OSGi bundles. The lab walks you through the process of creating several OSGi plugin bundles which add new features to the web application. You have a chance to create a twitter plugin (thanks to Ryan Lubke), make a Jeopardy game, add a tagging capability to the console, and more. And best of all, the concepts in the lab can be applied to your own GlassFish web applications. Here's a screenshot of what the tagging plugin looks like after you're done (also with a "notes" plugin installed):

So... if you didn't know about the JavaOne Hands-on labs, or you haven't checked them out in the past. Give them a shot this year -- you won't be disappointed. Remember to Bring Your Own Laptop to the ones listed as BYOL when you search Schedule Builder (the Building OSGi plugins lab will be in a machine-provided room on Wed at 1:35PM).
Whether you choose a Hands-on Lab or not, I hope everyone attending JavaOne has a great time. Don't forget to reply and post what you're looking forward to seeing at JavaOne this year. Also, if you're planning on attending my OSGi plugins lab, let me know!
See you at JavaOne!
That's Lombok... i.e., forget about typing (and updating!) getters, setters, hashCode, toString, because Lombok does that for you. All you need to do is add an annotation to the class, type the names of your variables, and then, under the hood, everything is generated into the bytecode!
Thanks to Jan Lahoda for the NetBeans integration.
Here's the interview (from where I took the screenshot above, which is by me):
http://netbeans.dzone.com/interview-lombok
...and here's the screencast by Alexis that shows you a complete Java EE 6 demo with Lombok:
http://netbeans.dzone.com/news/screencast-lombok-netbeans-ide
Whoever ends up 'owning' Java, the first thing they should try and accomplish is integrate Lombok into the JDK.
GlassFish v3 is go!
This is a biggie. It's been about 3 years in the making. It is a modularized OSGi container. It implements Java EE 6. It's 70Mb compared to 700Mb. It could make coffee if i programmed it so... but realistically is not likely to win the Nobel prize for peace (although... <joke>given the current awardee perhaps there is a chance?</joke>). Even so, i think v3 is going to be very popular.
GlassFish v3 includes Jersey 1.1.4.1 that implements JAX-RS 1.1.


As indicated in the previous posts, we have started to redesign a few really basic interactions in OpenOffice.org Impress in order to reduce the overall complexity of the UI. Currently, we focus on navigation through slides in various contexts, the visual appearance of different slide selection states and the handling of slide layouts. Today, I want to share some thoughts about a different way how to assign slide layouts.
At present, OpenOffice.org Impress offers five ways how to change the layout of an existing slide. However, four of those merely trigger or point to the task pane. Consequently, there is only one “real” way how a user can pick and apply a slide layout, and there is no way doing that without the task pane. Thinking about a common scenario of creating a presentation, adding new slides, modifying existing ones, adjusting their layouts, one can imagine that switching the task pane on and off over and over again is an unwanted interruption. Keeping the task pane permanently alive is of course an option. Yet, if you want to concentrate more on the content of your work instead on the tools at hand, you’d rather prefer to disable the task pane since it consumes quite a lot of screen real estate.
![]() |
| Von OOo UI - Ideas and Mock-Ups |
In addition, there is no way to insert a slide with a favored layout in only one step. Currently, the default work flow requires a user to insert a slide first, decide if the layout meets the expectations and then assign the preferred layout if expectations are not met. From our point of view, there should be a more elegant solution to that, too.
Another drawback of the current implementation of slide layouts is that their sheer number exceeds a practical amount that covers most use cases without getting too difficult to work with. Including the vertical layouts OpenOffice.org Impress 3.2 Beta offers 27 slide layouts. That is challenging for two particular reasons. The 27 slide layouts have to go somewhere in the UI, namely into the task pane, where they consume a lot of space. Since they are so many, it is often necessary to scroll through the task pane in order to get an overview what is available and during search. Picking one is also not always easy because in a worst case a user has to look through 27 options and then decide which one to pick. That takes time.
Since OpenOffice.org Impress already has a dedicated “Presentation” toolbar that contains an “Insert Slide” and a “Slide Layout” button, the Renaissance i-Team started working on a solution that offers a technique to change slide layouts without the necessity to constantly use the task pane. Motivated by the visual concepts in our prototypes, we will try to add a preview pane into the toolbar such that users can directly pick a layout from a drop down toolbox, in the context of the task (insert slide, change slide layout). In parallel, we have decided to add more value to that particular “Presentation” toolbar by reducing its functionality to support the most important tasks only (insert slide, change slide layout, change slide design, set slide transition, start presentation).
![]() |
| Von OOo UI - Ideas and Mock-Ups |
We have also considered options to handle slide layouts from various mouse context menus. However, this seems to be very challenging from an implementation point of view. Although we already have some design mock-ups, we need to explore the feasibility of that solution first on all platforms. So for now, the development team is investigating our options.
![]() |
| Von OOo UI - Ideas and Mock-Ups |
One way to reduce the amount of slide layouts is to offer object placeholders in each layout that can be used to insert images, charts, tables and the like where usually text content would appear. That would make the need to create slide layouts with tables, images or charts separately obsolete.
Overall, these changes may seem small or less significant compared to other troubles such as the inability to create own slide layouts. However, having the goal of thinning out the current UI in mind, these redesigns and the sum of all forthcoming incremental improvements of the work flow will eventually keep us on the right track. For details about the ongoing work check out the Renaissance i-Team Wiki.
Best,
Andreas
As the Copenhagen Climate Change summit kicks off, the US Environmental Protection Agency declared carbon dioxide to be a pollutant dangerous to human health, thus giving itself power to regulate CO2 emissions. President Obama preponed his trip to the summit, his previous arrival date being the last day of the summit. A glimmer of hope that something might actually happen? A big change since the APEC conference, where the backpedaling from various APAC leaders was already starting on what could - or more appropriately - could not be accomplished in Copenhagen.
This month's travels took me to Edinburgh Scotland, where I spoke at RBS's International Risk Congress on "Innovation in Mobile Financial Services". Speaking to the audience on Mobile Payments, NFC payments, non-traditional players in payments such as Telcos, PayPal, Apple etc. made for an interesting talk. Using an example of location based services often given by my colleague Carl Morath - a movie poster over which you would wave your iPhone, which would pop up a list of theaters within a mile of your current location, allowing you to buy tickets using your phone, storing the tickets on your phone, and offering you coupons for restaurants around the theater where you use your tickets - made everyone realize the power of mobile payments.
I then headed over to London, and repeated the talk at one of RBS's many locations. I had an interesting debate with someone from the audience about the core competence of established banks, and whether transactional banking was moving into an area where banks did not have much value-add. We also had a conversation about Web2.0 properties and virtual monies - why would Facebook need anyone to go to a bank to send e-flowers to a facebook user? For those of you who are not following statistics, Facebook now as 350M registered users. That by the way, is the population of the United States.
The best part of this trip - the two excellent bottles of Distiller's Edition of Lagavulin gifted to me, yummy!
Monday and tuesday of this week were spent in Toronto, meeting with some key partners and customers. Fidelity Information Services is a great partner, we work on lots of initiatives together including their core banking and wealth management platforms. I had a very interesting and thought provoking conversation with Interac - the Canadian equivalent of NYCE and PLUS - a non-profit organization connecting the Canadian financial institutions together. We spoke about all the non-traditional players in payments like Telcos, Paypal, Apple and NFC payments and location based services etc. etc. I ended the day with ITG, another great customer that supplies solutions to Capital Markets companies for Trading, Wealth Management, Risk etc. We spoke at length about Solaris on x86 (HP or Sun), their market data infrastructure that runs entirely on Solaris, and other new projects that they are planning.
The Canadian banks just keep chugging along. They are seriously revamping their capital markets operations, spending lot of time and money on all trading desks - Derivatives in particular.
Oh, and I did get to see a hockey game - Canadians as as nuts about this game as us Indians are about cricket. The local team won, which I am sure was why I could make it back to my hotel by 10:00pm!
| 142900-xx 142901-xx |
newest patchid sparc newest patchid x86 |
requires 141444-09 SunOS 5.10: kernel patch requires 141445-09 SunOS 5.10_x86: kernel patch |
| 141444-09 141445-09 |
Solaris 10 10/09 Update8 sparc Solaris 10 10/09 Update8 x86 |
requires
139555-08 requires 139556-08 |
| 141414-10 141415-10 |
highest release sparc highest release x86 |
Obsoleted by: 141444-09 SunOS 5.10: kernel patch Obsoleted by: 141445-09 SunOS 5.10_x86: kernel patch |
| 139555-08 139556-08 |
Solaris 10 05/09 Update7 sparc Solaris 10 05/09 Update7 x86 |
requires
137137-09 requires 137138-09 |
| 138888-08 138889-08 |
highest release sparc highest release x86 |
Obsoleted by: 139555-08 SunOS 5.10: Kernel Patch Obsoleted by: 139556-08 SunOS 5.10_x86: Kernel Patch |
| 137137-09 137138-09 |
Solaris 10 10/08 Update6 sparc Solaris 10 10/08 Update6 x86 |
requires
127127-11 requires 127128-11 |
| 137111-08 137112-08 |
highest release sparc highest release x86 |
Obsoleted by: 137137-09 SunOS 5.10: kernel patch Obsoleted by: 137138-09 SunOS 5.10_x86: kernel patch |
| 127127-11 127128-11 |
Solaris 10 05/08 Update5 sparc Solaris 10 05/08 Update5 x86 |
requires
120011-14 requires 120012-14 |
| 127111-11 127112-11 |
highest release sparc highest release x86 |
Obsoleted by: 127127-11 SunOS 5.10: kernel patch Obsoleted by: 127128-11 SunOS 5.10_x86: kernel patch |
| 120011-14 120012-14 |
Solaris 10 08/07 Update4 sparc Solaris 10 08/07 Update4 x86 |
requires
118833-36 requires 118855-36 |
| 125100-10 125101-10 |
highest release sparc highest release x86 |
Obsoleted by: 120011-14 SunOS 5.10: Kernel Update patch Obsoleted by: 120012-14 SunOS 5.10_x86: Kernel Update patch |
| 118833-36 118855-36 |
highest release sparc highest release x86 |
this is a must have for Solaris 10 11/06 Update3 sparc this is a must have for Solaris 10 11/06 Update3 x86 |
| 118833-33 118855-33 |
Solaris 10 11/06 Update3 sparc Solaris 10 11/06 Update3 x86 |
|
| 118833-17 118855-14 |
Solaris 10 06/06 Update2 sparc Solaris 10 06/06 Update2 x86 |
|
| 118822-30 118844-30 |
highest release sparc highest release x86 |
Obsoleted by: 118833-36 SunOS 5.10: kernel Patch Obsoleted by: 118855-36 SunOS 5.10_x86: kernel Patch |
| 118822-25 118844-26 |
Solaris 10 01/06 Update1 sparc Solaris 10 01/06 Update1 x86 |
|
| 118822-10 118844-11 |
Solaris 10 03/05 HW1 sparc Solaris 10 03/05 HW1 x86 |
|
| Solaris 10 sparc Solaris 10 x86 |
The Java EE 6 compatible Glassfish v3 is released today! In addition to provide v2 feature parity, the v3 deployment implements the new Java EE 6 spec requirements which include the deployment of ejb lite (EJBs packaged inside the war), the portable naming (where you can define application name and module name in the deployment descriptors and then use them in JNDI lookup) and etc.
Among many changes that went into v3 deployment, the most important piece is the new pluggable/extensible deployment framework. This pluggable deployment framework allows you to plug in new module/container types with the container SPIs (see Add-On Component Development Guide for more details). The JSR 299 (Context and Dependency Injection) RI was integrated through the framework. The Java EE standard module/container types were also re-written to retro-fit into the framework. This deployment framework also sends application lifecycle events at various points of the deployment to allow application developers to perform tasks (such as application initialization/clean up work) as needed at those points.
In v3, the code paths of the application loading during deployment and server start up have been converged to provide users more consistent behaviors (which also helps make code maintenance easier). As a result, we don't write out the generated deployment descriptors (merged version from the original deployment descriptors and the annotations) by default any more. If you need to use the generated deployment descriptors for debugging purpose, you can use the system property (-Dwriteout.xml=true) to write them out.
x86 kernel patch 142901-02
Sparc kernel patch 142900-02.
Sun Alert 271519 should be updated soon.
Presented by Happy Sithole, PhD, Director, Centre for High Performance Computing. Recorded at the Sun HPC Consortium in Portland, November 14, 2009, by Deirdre Straughan. Download for iPod
More presentations at the Sun HPC Consortium site.
| Reviews
Interactive recently spoke with José
Rubi-Gonzalo from WhiteStone
Technology
about how the company is currently using JavaFX in the Workflow
component of its Consolidated Service Desk and IT Service Management
product. Specifically, WhiteStone utilized JavaFX to create an
intuitive tool with a rich set of functionalities that allows users
to create complex business processes using a visual approach.
José
points out that “UI
design is key for a successful application,”
and noted that JavaFX has helped WhiteStone differentiate from other
competitors in the service desk industry by giving them the
capabilities to create a visually rich UI that not only helps users
be more comfortable, but productive as well. José said the JavaFX technology was announced at a time when the WhiteStone was already looking to update its Workflow tool which José said “needed to evolve,” to add more functionality without limiting growth. He said the technology “matched exactly our needs – a Java based language that fit nicely into our existing J2EE framework, multi-platform, and multi-screen.” José said there was a very fast adoption of the technology by the development team noting: “JavaFX is very easy to pick up for Java developers so our team was writing code on JavaFX in no time.” |
| José
said a simple integration process was another key factor in selecting
JavaFX because WhiteStone needed to protect its past technology
investments. However, since the original application was developed
on J2EE, José said introducing JavaFX was “straightforward.”
José said WhiteStone is now able to deliver more features on a
faster timeline “because our development capability has grown
very significantly with the technology change.” When asked
about what he liked most about using JavaFX in the service desk
application José responded: “For me, personally, is the
peace of mind that JavaFX gives me, because I know we have the
ability to maintain and grow our application with the level of
quality interaction and visual design that our users expect.” Looking to the future, José said the company is looking to continue incorporating JavaFX into the rest of the service desk application while also exploring the potential of using JavaFX for a mobile platform to extend the capabilities of field service users. WhiteStone is also working on deploying a system with a software UI developed entirely in JavaFX for one of the leading hospitals in Spain, that will help increase quality of life for patients. As José pointed out, when starting work on this new project “we knew we could not just write another web interface...with JavaFX we had the capacity to produce the application we envision, mixing an innovative interactive design with great visual capabilities.” To learn more about WhiteStone's experience with JavaFX, read the full interview here. |
Update 10.Dec.2009:
Support of Solaris 10 10/09 Update8 with Sun Cluster 3.2 1/09 Update2 is now announced. The recommendation is to use the 126106-39 (sparc) / 126107-39 (x86) with Solaris 10 10/09 Update8. Note: The -39 Sun Cluster core patch is a feature patch because the -38 Sun Cluster core patch is part of Sun Cluster 3.2 11/09 Update3 which is already released.
For new installations/upgrades with Solaris 10 10/09 Update8 use:
* Sun Cluster 3.2 11/09 Update3 with Sun Cluster core patch -39 (fix problem 1)
* Use the patches 142900-02 / 142901-02 (fix problem 2)
* Add "set nautopush=64" to /etc/system (workaround for problem 3)
For patch updates to 141444-09/141445-09 use:
* Sun Cluster core patch -39 (fix problem 1)
* Also use patches 142900-02 / 142901-02 (fix problem 2)
* Add "set nautopush=64" to /etc/system (workaround for problem 3)
It's time to notify that there are some issues with these kernel patches in combination with Sun Cluster 3.2
1.) The patch breaks the zpool cachefile feature if using SUNW.HAStoragePlus
a.) If the kernel patch 141444-09 (sparc) / 141445-09 (x86) is installed on a Sun Cluster 3.2 system where the Sun Cluster core patch 126106-33 (sparc) / 126107-33 (x86) is already installed then hastorageplus_prenet_start will fail with the following error message:
...
Oct 26 17:51:45 nodeA SC[,SUNW.HAStoragePlus:6,rg1,rs1,hastorageplus_prenet_start]: Started searching for devices in '/dev/dsk' to find the importable pools.
Oct 26 17:51:53 nodeA SC[,SUNW.HAStoragePlus:6,rg1,rs1,hastorageplus_prenet_start]: Completed searching the devices in '/dev/dsk' to find the importable pools.
Oct 26 17:51:54 nodeA zfs: [ID 427000 kern.warning] WARNING: pool 'zpool1' could not be loaded as it was last accessed by another system (host: nodeB hostid: 0x8516ced4). See: http://www.sun.com/msg/ZFS-8000-EY
...
b.) If the kernel patch 141444-09 (sparc) / 141445-09 (x86) is installed on a Sun Cluster 3.2 system where the Sun Cluster core patch 126106-35 (sparc) / 126107-35 (x86) is already installed then hastorageplus_prenet_start will work but the zpool cachefile feature of SUNW.HAStoragePlus is disabled. Without the zpool cachefile feature the time of zpool import increases because the import will scan all available disks. The messages look like:
...
Oct 30 15:37:45 nodeA SC[,SUNW.HAStoragePlus:8,nfs-rg,zpool1-rs,hastorageplus_validate]: [ID 148650 daemon.notice] Started searching for devices in '/dev/dsk' to find the importable pools.
Oct 30 15:37:45 nodeA SC[,SUNW.HAStoragePlus:8,nfs-rg,zpool1-rs,hastorageplus_validate]: [ID 148650 daemon.notice] Started searching for devices in '/dev/dsk' to find the importable pools.
Oct 30 15:37:49 nodeA SC[,SUNW.HAStoragePlus:8,nfs-rg,zpool1-rs,hastorageplus_validate]: [ID 547433 daemon.notice] Completed searching the devices in '/dev/dsk' to find the importable pools.
Oct 30 15:37:49 nodeA SC[,SUNW.HAStoragePlus:8,nfs-rg,zpool1-rs,hastorageplus_validate]: [ID 547433 daemon.notice] Completed searching the devices in '/dev/dsk' to find the importable pools.
Oct 30 15:37:49 nodeA SC[,SUNW.HAStoragePlus:8,nfs-rg,zpool1-rs,hastorageplus_validate]: [ID 792255 daemon.warning] Failed to update the cachefile contents in /var/cluster/run/HAStoragePlus/zfs/zpool1.cachefile to CCR table zpool1.cachefile for pool zpool1 : file /var/cluster/run/HAStoragePlus/zfs/zpool1.cachefile open failed: No such file or directory.
Oct 30 15:37:49 nodeA SC[,SUNW.HAStoragePlus:8,nfs-rg,zpool1-rs,hastorageplus_validate]: [ID 792255 daemon.warning] Failed to update the cachefile contents in /var/cluster/run/HAStoragePlus/zfs/zpool1.cachefile to CCR table zpool1.cachefile for pool zpool1 : file /var/cluster/run/HAStoragePlus/zfs/zpool1.cachefile open failed: No such file or directory.
Oct 30 15:37:49 nodeA SC[,SUNW.HAStoragePlus:8,nfs-rg,zpool1-rs,hastorageplus_validate]: [ID 205754 daemon.info] All specified device services validated successfully.
...
If the ZFS cachefile feature is not required AND the above kernel patches are installed, problem a.) is resolved by installing Sun Cluster core patch 126106-35 (sparc) / 126107-35 (x86).
Solution for a) and b):
126106-39 Sun Cluster 3.2: CORE patch for Solaris 10
126107-39 Sun Cluster 3.2: CORE patch for Solaris 10_x86
Sun Alert 272669: A Solaris Kernel Change Stops Sun Cluster Using "zpool.cachefiles" to Import zpools Resulting in ZFS pool Import Performance Degradation or Failure to Import the zpools
This is reported in Bug 6895580
2.) The patch breaks probe-based IPMP if more than one interface is in the same IPMP group
After installing the already mentioned kernel patch:
141444-09 SunOS 5.10: kernel patch or
141445-09 SunOS 5.10_x86: kernel patch
then the probe-based IPMP group feature is broken if the system is using more than one interface in the same IPMP group. This means all Solaris 10 systems which are using more than one interface in the same probe-based IPMP group are affected!
After installing this kernel patch the following errors will be sent to the system console after a reboot:
...
nodeA console login: Oct 26 19:34:41 in.mpathd[210]: NIC failure detected on bge0 of group ipmp0
Oct 26 19:34:41 in.mpathd[210]: Successfully failed over from NIC bge0 to NIC e1000g0
...
Workarounds:
a) Use link-based IPMP instead of probe-based IPMP
b) Use only one interface in the same IPMP group if using probe-based IPMP
See the blog "Tips to configure IPMP with Sun Cluster 3.x" for more details if you like to change the configuration.
c) Do not install the listed kernel patch above. Note: Fix is already in progress and can be reached via a service request. I will update this blog when the general fix is available.
Solution:
142900-02 SunOS 5.10: kernel patch
142901-02 SunOS 5.10_x86: kernel patch
Sun Alert 271519: Solaris 10 Kernel Patches 141444-09 and 141445-09 May Cause Interface Failure in IP Multipathing (IPMP)
This is reported in Bug 6888928
3.) When applying the patch Sun Cluster can hang on reboot
After installing the already mentioned kernel patch:
141444-09 SunOS 5.10: kernel patch or
141511-05 SunOS 5.10_x86: ehci, ohci, uhci patch
the Sun Cluster nodes can hang within boot because the Sun Cluster nodes has exhausted the default number of autopush structures. When clhbsndr module is loaded, it causes a lot more autopushes to occur than would otherwise happen on a non-clustered system. By default, we only allocate nautopush=32 of these structures.
Workarounds:
a) Do not use the mentioned kernel patch with Sun Cluster
b) Boot in non-cluster-mode and add the following to /etc/system
set nautopush=64
Sun Alert 273610: Solaris autopush(1M) Changes (with patches 141444-09/141511-04) May Cause Sun Cluster 3.1 and 3.2 Nodes to Hang During Boot
This is reported in Bug 6879232
|
It's been a while since we've mentioned Sang Shin's "Java Passion" classes. Sang is a tireless creator of material for training and hands-on labs (HOL) with detailed step-by-step instructions. The already very long list of hands-on labs now includes :
• GlassFish Programming/Development (with Passion!) Online Course (main page)
|
but also :
• Ajax/Comet Lab with GlassFish
• Java EE 6 samples
• Servlet 3.0 samples
.. and there's even more to come : Managed Bean, Interceptors, Bean Validation, CDI, JPA 2.0, JSF 2.0, and EJB 3.1. These are likely to come after Sang is done with Sun Tech Days in Brazil (São Paulo), starting this Tuesday (December 8th).
The final approval ballot for the Connectors 1.6 specification and the Java EE 6 platform closed yesterday and the EC has approved the specification and the platform. As Roberto shared in his blog, the final release happens on December 10 along with the release of the reference implementation, GlassFish v3.
The Connector Architecture in the Java EE platform enables an enterprise application to work with disparate enterprise information systems (EIS), like databases, MoM products, transaction monitors etc.
The Connector 1.6 specification developed through the JSR 322 expert group, builds upon the the earlier Connector 1.5 specification in the following areas:
I had provided brief overviews of these features in previous blog entries and presentations. There are more articles/tutorials on the technology coming up in the next few weeks.
I would like to take this opportunity to thank all those who have helped in this version of the specification -- the expert group members of JSR 322, the spec-leads and EG members of related JSRs, the reference implementation (RI) and the technology compatibility kit (TCK) teams and all those from the community who had provided feedback and suggestions on the previous milestone drafts.
Edit: Jagadish Ramu, the Connectors RI lead, blogs about the release here.
Developer Snapshot build OOo-Dev DEV300_m67 is available for download.
DEV300 is the development codeline for the upcoming OOo 3.x releases.
If you find severe issues within this build please file them to OpenOffice.org's bug tracking system IssueTracker.
Please use the following download page:
http://download.openoffice.org/next
Release Notes:
http://development.openoffice.org/releases/DEV300_m67_snapshot.html
MD5 checksums:
http://download.openoffice.org/next/md5sums/DEV300_m67_md5sums.txt
I was having a conversation with an OpenBSD user and developer the other day, and he mentioned some ongoing work in the community to consolidate support for RAID controllers. The problem, he was saying, was that each controller had a different administrative model and utility -- but all I could think was that the real problem was the presence of a RAID controller in the first place! As far as I'm concerned, ZFS and RAID-Z have obviated the need for hardware RAID controllers.
ZFS users seem to love RAID-Z, but a frustratingly frequent request is to be able to expand the width of a RAID-Z stripe. While the ZFS community may care about solving this problem, it's not the highest priority for Sun's customers and, therefore, for the ZFS team. It's common for a home user to want to increase his total storage capacity by a disk or two at a time, but enterprise customers typically want to grow by multiple terabytes at once so adding on a new RAID-Z stripe isn't an issue. When the request has come up on the ZFS discussion list, we have, perhaps unhelpfully, pointed out that the code is all open source and ready for that contribution. Partly, it's because we don't have time to do it ourselves, but also because it's a tricky problem and we weren't sure how to solve it.
Jeff Bonwick did a great job explaining how RAID-Z works, so I won't go into it too much here, but the structure of RAID-Z makes it a bit trickier to expand than other RAID implementations. On a typical RAID with N+M disks, N data sectors will be written with M parity sectors. Those N data sectors may contain unrelated data so adding modifying data on just one disk involves reading the data off that disk and updating both those data and the parity data. Expanding a RAID stripe in such a scheme is as simple as adding a new disk and updating the parity (if necessary). With RAID-Z, blocks are never rewritten in place, and there may be multiple logical RAID stripes (and multiple parity sectors) in a given row; we therefore can't expand the stripe nearly as easily.
A couple of weeks ago, I had lunch with Matt Ahrens to come up with a mechanism for expanding RAID-Z stripes -- we were both tired of having to deflect reasonable requests from users -- and, lo and behold, we figured out a viable technique that shouldn't be very tricky to implement. While Sun still has no plans to allocate resources to the problem, this roadmap should lend credence to the suggestion that someone in the community might work on the problem.
The rest of this post will discuss the implementation of expandable RAID-Z; it's not intended for casual users of ZFS, and there are no alchemic secrets buried in the details. It would probably be useful to familiarize yourself with the basic structure of ZFS, space maps (totally cool by the way), and the code for RAID-Z.
ZFS uses vdevs -- virtual devices -- to store data. A vdev may correspond to a disk or a file, or it may be an aggregate such as a mirror or RAID-Z. Currently the RAID-Z vdev determines the stripe width from the number of child vdevs. To allow for RAID-Z expansion, the geometry would need to be a more dynamic property. The storage pool code that uses the vdev would need to determine the geometry for the current block and then pass that as a parameter to the various vdev functions.
There are two ways to record the geometry. The simplest is to use the GRID bits (an 8 bit field) in the DVA (Device Virtual Address) which have already been set aside, but are currently unused. In this case, the vdev would need to have a new callback to set the contents of the GRID bits, and then a parameter to several of its other functions to pass in the GRID bits to indicate the geometry of the vdev when the block was written. An alternative approach suggested by Jeff and Bill Moore is something they call time-dependent geometry. The basic idea is that we store a record each time the geometry of a vdev is modified and then use the creation time for a block to infer the geometry to pass to the vdev. This has the advantage of conserving precious bits in the fixed-width DVA (though at 128 bits its still quite big), but it is a bit more complex since it would require essentially new metadata hanging off each RAID-Z vdev.
When the user requests a RAID-Z vdev be expanded (via an existing or new zpool(1M) command-line option) we'll apply a new fold operation to the space map for each metaslab. This transformation will take into account the space we're about to add with the new devices. Each range [a, b] under a fold from width n to width m will become
[ m * (a / n) + (a % n), m * (b / n) + b % n ]
The alternative would have been to account for m - n free blocks at the end of every stripe, but that would have been overly onerous both in terms of processing and in terms of bookkeeping. For space maps that are resident, we can simply perform the operation on the AVL tree by iterating over each node and applying the necessary transformation. For space maps which aren't in core, we can do something rather clever: by taking advantage of the log structure, we can simply append a new type of space map entry that indicates that this operation should be applied. Today we have allocated, free, and debug; this would add fold as an additional operation. We'd apply that fold operation to each of the 200 or so space maps for the given vdev. Alternatively, using the idea of time-dependent geometry above, we could simply append a marker to the space map and access the geometry from that repository.
Normally, we only rewrite the space map if the on-disk, log-structure is twice as large as necessary. I'd argue that the fold operation should always trigger a rewrite since processing it always requires a O(n) operation, but that's really an ancillary point.
At the same time as the previous operation, the vdev metadata will need to be updated to reflect the additional device. This is mostly just bookkeeping, and a matter of chasing down the relevant code paths to modify and augment.
With the steps above, we're actually done for some definition since new data will spread be written in stripes that include the newly added device. The problem is that extant data will still be stored in the old geometry and most of the capacity of the new device will be inaccessible. The solution to this is to scrub the data reading off every block and rewriting it to a new location. Currently this isn't possible on ZFS, but Matt and Mark Maybee have been working on something they call block pointer rewrite which is needed to solve a variety of other problems and nicely completes this solution as well.
After Matt and I had finished thinking this through, I think we were both pleased by the relative simplicity of the solution. That's not to say that implementing it is going to be easy -- there's still plenty of gaps to fill in -- but the basic algorithm is sound. A nice property that falls out is that in addition to changing the number of data disks, it would also be possible to use the same mechanism to add an additional parity disk to go from single- to double-parity RAID-Z -- another common request.
So I can now extend a slightly more welcoming invitation to the ZFS community to engage on this problem and contribute in a very concrete way. I've posted some diffs which I used sketch out some ideas; that might be a useful place to start. If anyone would like to create a project on OpenSolaris.org to host any ongoing work, I'd be happy to help set that up.
| @ManagedObject public class MyProbeListener { HashMap<Long, Long> requestMap = new HashMap(); private AverageRangeStatisticImpl averageRequestTime = new AverageRangeStatisticImpl(0L, Long.MIN_VALUE, Long.MAX_VALUE, "TotalRequestTime", AverageRangeStatisticImpl.UNIT_MILLISECOND, "Average request time", 0L, -1L); @ManagedAttribute(id="averageRequestTime") public AverageRangeStatistic getAverageRequestTime() { return averageRequestTime; } @ProbeListener("glassfish:web:http-service:requestStartEvent") public void requestStart( @ProbeParam("appName") String s, @ProbeParam("hostName") java.lang.String hostName, @ProbeParam("serverName") java.lang.String serverName, @ProbeParam("serverPort") int serverPort, @ProbeParam("contextPath") java.lang.String contextPath, @ProbeParam("servletPath") java.lang.String servletPath) { long threadId = Thread.currentThread().getId(); //if the request is not for my app, then ignore the event if (!s.equals("com.sun.samples.probe-app_3.0.0.SNAPSHOT")) return; System.out.println("requestStarted for app: " + s + " , ThreadID = " + threadId); requestMap.put(threadId, new Date().getTime()); } @ProbeListener("glassfish:web:http-service:requestEndEvent") public void requestEnd( @ProbeParam("appName") String s, @ProbeParam("hostName") java.lang.String hostName, @ProbeParam("serverName") java.lang.String serverName, @ProbeParam("serverPort") int serverPort, @ProbeParam("contextPath") java.lang.String contextPath, @ProbeParam("servletPath") java.lang.String servletPath, @ProbeParam("statusCode") int statusCode) { long threadId = Thread.currentThread().getId(); //if the request is not for my app, then ignore the event if (!s.equals("com.sun.samples.probe-app_3.0.0.SNAPSHOT")) return; System.out.println("requestEnded for app: " + s + " , ThreadID = " + threadId); Object startTimeObj = requestMap.get(threadId); if (startTimeObj == null) { //No start recorded. Just discard the event return; } long totalTime = new Date().getTime() - requestMap.get(threadId); requestMap.remove(threadId); System.out.println("totalTime taken for app: " + s + " , ThreadID = " + threadId + " : " + totalTime); averageRequestTime.setCurrent(totalTime); } |



Today, Sun announced the immediate availability of GlassFishTM Application Server v3 Prelude and its commercially supported counterpart, Sun GlassFish Enterprise Server v3 Prelude.
GlassFish v3 Prelude uses the new lightweight monitoring framework to expose the monitoring data. It moves away from the 'container's collect statistics' theme to 'container's emit events and interested listeners will collect them'. This allows the statistics to be collected in a much cleaner way and makes it more flexible to collect different variations of statistics for the same set of container events. For Prelude we expose the Web Container, Application and JVM statistics, using the asadmin CLI utility and Admin GUI. The Monitoring chapter in Administration Guide, give details of the exhaustive list of statistics that are available in v3 Prelude.
Also It is very easy to extend the monitoring in V3 Prelude, either to emit your own events for a custom component, or to write a new set of listeners thus exposing new statistics for existing container's. Check out here on how to do this.
Following are the other links related to GlassFish v3 Prelude
release:
Press release:
http://www.sun.com/aboutsun/media/index.jsp
http://www.sun.com/aboutsun/media/pressreleases.jsp
http://www.sun.com/aboutsun/pr/2008-11/sunflash.20081106.1.xml
Site:
http://www.sun.com/software/products/glassfishv3_prelude/index.xml
http://www.sun.com/software/products/glassfishv3_prelude/get.jsp
(download page)
Announcement and videos on jsc/javaee and
dsc/appserver:
http://java.sun.com/javaee/index.jsp
http://java.sun.com/javaee/downloads/index.jsp
http://java.sun.com/javaee/community/glassfish/
(under What's
New)
http://java.sun.com/javaee/overview/screencasts.jsp
(new videos listed under GlassFish
Videos)
http://developers.sun.com/appserver/index.jsp
http://developers.sun.com/appserver/downloads/index.jsp
http://developers.sun.com/appserver/overview/wn_archive.jsp
http://developers.sun.com/appserver/overview/screencasts/
(new videos listed under GlassFish
Videos)
http://developers.sun.com/appserver/reference/index.jsp
http://developers.sun.com/appserver/reference/techart/index.jsp
Announcement
and videos on SDN Program News
blog:
http://blogs.sun.com/SDNProgramNews/

New poverty estimates released in August 2008 show that about 1.4 billion people in the developing world (one in four) were living on less than $1.25 a day in 2005. Microfinance has been recognized worldwide as a simple but powerful tool that enables the poor to pull themselves out of poverty. Most commonly, it involves making small loans to the working poor in developing countries. The loans are used to establish or expand small businesses that generate additional income for the family, enabling them to buy food, access healthcare, educate their children, put aside savings and lay the foundation for a better future. The microfinance organizations need capital to expand and reach more of the working poor. At the same time, millions of everyday people here in the United States are looking for ways to make investments that yield a financial return while making a positive impact on the world.
MicroPlace (an eBay inc., company) is involved in a remarkable effort in connecting the investors to the working people in poverty thus providing more microfinance to the poor and addressing the poverty of the world. MicroPlace, launched in 2007, is a website that enables everyday people to invest in the world’s working poor. This online investment site, whose mission is to alleviate global poverty, facilitates investments in microfinance that have proven to be an effective way of transforming people on the margins of society into economically productive individuals. MicroPlace is championing a model that fuses people’s instincts to be philanthropic with the efficacy of investing to raise microfinance capital. To date, microfinance has enabled a billion people to lift themselves out of poverty. MicroPlace aims to extend microfinance’s helping hand to the next billion people working in poverty-- one investment at a time.
While building a regulatory infrastructure is one big task (explained in next section), establishing a “back-office” capacity of the website is an essential and integral part for the success of the business. MicroPlace benefits from the lessons eBay have learned working with the millions of small business owners and consumers who buy and sell on its family of sites. Having PayPal, eBay's online payment service, on its side has further helped the MicroPlace to thrive. PayPal will process the loans free of charge, thus giving the added value for the investor to invest all his money to the downtrodden. Going forward, the company is focusing on improving its user interface, which will provide investors with more search criteria by which they can choose their investment, such as which institutions offer the highest rate of return and which offers loans primarily to women and/or the “poorest-of-the-poor.”
MicroPlace has invested heavily in the development of software that helps microfinance institutions (MFIs) collect and organize data. "Microlending is just a good fit for eBay," says eBay spokeswoman Catherine England. "It really leverages eBay's areas of expertise to address what we see as an emerging market.
MicroPlace faces many
diverse challenges in its business but it has been able to handle most
of it
with EBay on its side.
Regulatory
Clearance: In order
to offer
investments on the website, MicroPlace must be registered as a
broker-dealer
with the Securities and Exchange Commission (SEC), a government agency
that
sets rules for the securities industry. As a registered broker,
MicroPlace must
also join the Financial Industry Regulatory Authority (FINRA), the
organization
that provides compliance oversight for the SEC. Getting the compliance
is not a
easy hurdle, as seen with KIVA.org which settled as a non-profit
organization
for this reason. By considering being part of EBay, it has immensely
helped
MicroPlace in terms of EBay doing the work to get the regulatory
clearance.
Also, MicroPlace as a broker-dealer would need to hold $1 on hand for every $6 invested. Obviously, EBay hasn’t been in this field and needed a partner to handle this. Turner (MicroPlace founder)’s previous employer Calvert foundation agreed to take this mantle and it got support from several other foundations to chip in, all due to the high profile EBay in the picture. Calvert is also the issuer of several securities offered on MicroPlace.
Microfinance Institutions (MFIs): MFIs are the means for MicroPlace to reach the borrowers. MicroPlace has made partnerships with existing MFIs and also setup its own MFIs to reach these poor. There are challenges with these MFIs. MFIs are harmed by various factors like financial crisis, natural disasters, political instability, reaching the right people and mismanagement of funds. Also, more MFIs are needed to address the ambitious target of MicroPlace to reach the billion people.
Execution: MicroPlace, with its current strength of 26, is really small for the scale it aspires to achieve. It has to grow to reach its target and as we have seen with many organizations, execution will be a challenge. Being under the hood of EBay, MicroPlace is well placed to face this challenge.
The MicroPlace initiative is a classic example of business meeting social development and leverages technology that can reach a wide audience.
Technology:
Technology is the most important component of MicroPlace that allows the investors to contribute to this social cause. MicroPlace target is to capture the day-to-day investors with investments starting as low as $20. Providing the accurate and enough information for the investor on its website is critical for MicroPlace. It is important to gather on how the money invested is helping the poor, while also capturing the information about the potential borrower so the investor can make his/her choice. MFIs will be the major source for providing this information, but using the technology to gather it from MFIs is crucial. Also by making it easy and secure for the investor to make an investment using the easy-to-use PayPal interface is another important part of the business.
Social Impact:
At its core, microfinance is about human dignity. It is based on the old adage: "Give a man a fish, you have fed him for today. Teach a man to fish, and you have fed him for a lifetime." Microfinance borrowers take great pride in their ability to lift themselves out of poverty through their own initiative. They work hard to survive from day to day and a loan provides a way for them to create a sustainable solution to their economic lot in life. A loan is attractive because microfinance borrowers know that successful repayment can result in the opportunity to take out more and bigger loans in the future. While a charitable donation can be helpful in the short-run, it may not represent an ongoing source of financial support.

There are millions of poor people who live in the direst of conditions for whom donations are critical for survival. Microfinance does not target these people. It addresses a segment of the poor that are looking for a hand up, not a hand out. MicroPlace is targeting a billion of these people to pull them out of poverty once and for all.
Tracey Pettengill Turner is the founder of the MicroPlace. Tracey is a well-known social entrepreneur committed to finding market-based solutions to global poverty. She is a seasoned business executive who has been involved in international development, social investing and philanthropy for more than 15 years. Prior to founding MicroPlace, Tracey was CFO of KickStart, an organization that designs and sells products focused on poverty alleviation. In 1998, she started her first company, 4charity, a web-based marketplace for charitable giving, and served as its CEO.
Earlier in her career, Tracey held a variety of positions with socially responsible firms including the Grameen Bank in Bangladesh (working with the noble prize winner Muhammad Yunus), Calvert Ventures and the World Bank. Working for the Grameen Bank of Bangladesh in the 1990s, Tracey Pettengill Turner saw first hand how microfinance works to lift people out of poverty. What she also learned was how microfinance can be a profitable investment. In October 2007, Turner and eBay launch the first of its kind MicroPlace, a website where investors can chose to invest in microfinance institutions (MFIs) in specific areas of the world.
MicroPlace is the first microfinance site to allow everyday folks to earn interest on their investment. MicroPlace is a registered broker-dealer, and is a for profit business. MicroPlace's business model is actually comparable to online traders like E-trade and Ameritrade. Investors can simply click on the area of the world they would like their microfinance investments to support. They are then presented with a list of MFIs operating in the area, their missions, and the terms of investments, including interest rates, maturity, and security issuer. Each MFI also features recent microfinance borrowers and their businesses. The interest rates charged by MFIs to the borrowers are significantly less than the rates charged by the local moneylenders, while with the high volume of this lending; the availability of the loans is also much higher. The repayment rates for microfinance borrowers are high, averaging 97 percent historically much higher than American consumer lending repayment rates of around 85 percent, proving this as a good bet for investors while making a positive impact on the world.
The expensive infrastructure that MicroPlace has built to facilitate the investing is in itself would be an entry barrier for a new entrant. MicroPlace currently charges a fee to the organizations that offer investments through the MicroPlace website, to make itself sustainable. This fee covers MicroPlace’s costs to support the website, provide customer service and be compliant with security regulations. MicroPlace does not charge any fees to the investor. Any profits generated by MicroPlace will be used to fund eBay’s socially beneficial activities like the eBay Foundation.
Deutsche Bank estimates that we need $250 billion to help the billion people out there living on less than $1 a day to work their way out of poverty. So far, the world has raised $25 billion. In 2007, Americans gave $300 billion to charity but invested $2.7 trillion in socially responsible investments. Poverty is a big problem and we need a big lever. MicroPlace believes that socially responsible investing is the only lever big enough to address this problem. It is generally believed that institutions and individuals are motivated to make themselves as well off as possible and that microfinance has been successful because it is based on this principle. Because borrowers, lenders, and investors alike are all motivated to make themselves better off, their incentives to maximize profit are aligned and self-supporting. MicroPlace and its partners, being for-profit organizations are no different in this aspect. With the costly infrastructure in place already, MicroPlace is poised to scale and is in there for a long haul.
Microfinance is a proven and successful concept. MicroPlace having built a sustainable business model around this concept is scalable and well placed to succeed. It does have its challenges, but most of the challenge was to setup its expensive infrastructure, which is already in place, and it is sure to take off from here to bring many more investors into its grove to help the people in poverty around the world.
Having spent considerable amount of my childhood in India, I have seen the significant population living in poverty and how hard they struggle to make the ends meet. I can hence, truly appreciate the difference MicroPlace is making in alleviating the poverty around the world.
動作確認などのちょっとしたレポートで構いません。ぜひメーリングリストに1通メールを出して参加賞をゲットしてください ^o^
Who would've thunk it that the dumb-phones are driving Mobile Web traffic today? Consumers that don't have an iPhone, but have a dumber non-smartphone instead, seem to still want to do all the things that iPhone users like to do, like surf the Web.
See: Dumb Phones Driving Mobile Web Here's a quote: Opera Software's Opera Mini browser is one of the few usable solutions for standard "feature phones." The Java-based browser actually uses proxy servers to compress and handle much of the rendering of websites using the same rendering engine as Opera's desktop browser, which is then pushed to the phone and displayed on-screen. This arrangement makes it possible to view even complex pages on meager hardwareNow, where is all the credit for Mobile Web advancement going? It should go to Java ME technology, since there are more non-smartphones than smartphones. Oooh... sorry. Meant to say "CPU-challenged" cell phones, not non-smartphones. :-) |
Last fall, I ran the Wide Finder Project. The results were interesting, but incomplete; it was a real shoestring operation. I think this line of work is interesting, so I’m restarting it. I’ve got a new computer and a new dataset, and anyone who’s interested can play.
I’ll use this entry as a table-of-contents for the series as it grows.
The problem is that lots of simple basic data-processing operations, in my case a simple Ruby script, run like crap on modern many-core processors. Since the whole world is heading in the slower/many-core direction, this is an unsatisfactory situation.
If you look at the results from last time, it’s obvious that there are solutions, but the ones we’ve seen so far impose an awful complexity cost on the programmer. The holy grail would be something that maximizes ratio of performance increase per core over programmer effort. My view: Anything that requires more than twice as much source code to take advantage of many-core is highly suspect.
There were a few problems last time. First, the disk wasn’t big enough and the sample data was too small (much smaller than the computer’s memory). Second, I could never get big Java programs to run properly on that system, something locked up and went weird. Finally, when I had trouble compiling other people’s code, I eventually ran out of patience and gave up. One consequence is that no C or C++ candidates ever ran successfully.
This time, we have sample data that’s larger than main memory and we have our own computer, and I’ll be willing to give anyone who’s seriously interested their own account to get on and fine-tune their own code.
This time, the computer is a T2000, with 8 cores and 32 threads. It’s actually slower (well, fewer cores) than the semi-pre-production T5120 I was working with last time, but it’s got over 250G of pretty fast disks, which I’ve built a ZFS pool and one filesystem on.
I’ve also staged all the ongoing logfiles from February 2003 to April 2008 there, 45G of data in 218 million lines.
It’s Internet-facing, with ssh access and port 80 open (not that I’m running a Web server yet).
I’ve set up a WideFinder Project Wiki. The details of how to get started are there. For now, anyone with a wikis.sun.com account can write to it, which I’m hoping will be an adequate vandalism filter.
Before we start coding, we need to agree on
the
Benchmark; the 13-line Ruby program was an instructive target for Wide
Finder 1, but several people pointed out that this could be done with an
awk/sort one-liner, so something a little more
ambitious might be appropriate. I’ve made a couple of initial suggestions on
the wiki.
Are there any computer programs that you wish were faster? Time was, you could solve that problem just by waiting; next year’s system would run them faster. No longer; Next year’s system will do more computing all right, but by giving you more CPUs, running at this year’s speed, to work with. So the only way to make your program faster is to work with more CPUs. Bad news: this is hard. Good news: we have some really promising technologies to help make it less hard. Bad news: none of them are mainstream. But I’m betting that will change.
On my recent excursion to Japan, I had the chance for a few conversations with Bruce Tate. He advanced a line of thinking that I found compelling: Right now is the time when the concurrent-programming winners will emerge. He sees an analogy to Object-Orientation in the early nineties: Several O-O languages were in play (most notably C++ and Smalltalk), but it hadn’t penetrated the application-development mainstream. Then Java came along, and turned out to have just the right characteristics to push O-O into the middle of the road.
Thus the analogy. Right at the moment, we have a bunch of candidate technologies to fill in the concurrent-programming void; obvious examples include Erlang, Scala, Clojure, and Haskell. While there are common threads, they differ from each other in many essential ways. Between the lot of them, there are a whole lot of different characteristics. The fact is, we don’t know at this moment which laundry-list of features is going to turn some candidate into The Java Of Concurrency.
I think that right now is a good time to have a run at this problem. I’ve been scanning back and forth around the Internet, information-gathering, contrasting, and comparing. As I work through this, I’ll publish my research notes here on the blog as I go along.
Here’s what I have so far:
Java — The factors that led to Java’s success.
The Laundry List — Ingredients that might go into the winning formula that brings concurrent programming to the mainstream.
Crosstalk — High-quality feedback, yours truly accused of bias, and deltas to the laundry list.
My Take — Exposing my own experiences and bias.
C vs. P - “Concurrency” vs. “Parallelism”, and where does the distinction lead?
Messaging — First impressions of messaging in Clojure as opposed to Erlang.
References — Using Clojure refs.
Parallel I/O — More Clojure concurrency tools, with generally pleasing results.
More Clojure I/O — Refactoring and retuning, based mostly on your feedback. Kind of discouraging.
No Free Lunch — In which the compute costs of concurrency seem anomalously high.
Tab Sweep — Concurrency miscellany, including node.js, optimism, Joe Armstrong, and an Intel voice.
Idiomatic Clojure — Code from those who, unlike me, natively inhabit this space.
Eleven Theses on Clojure — Summing up my perceptions so far.
Tuning Concurrent Clojure — Making the code run faster (and slower).
The developers, actually; they have a direct incentive in that by doing concurrency well, their apps will run faster, and their employers do too in that the same performance level will require less iron.
In fact, I suspect the most likely candidates to get behind this are the chip builders; it’s traditionally been seen as their role to push the development tools that make their products shine. So I suspect that Intel, AMD, IBM, and the Sun part of Oracle are the most likely candidates to go all activist. In particular, the Sun SPARC processors have been leading the more-cores-and-damn-the-gigahertz charge for the last few years, so we ought to be the ones who care the most.
I’ve started working on a Late-2009 Concurrency Linkography page over at Project Kenai; it seems something that fits more comfortably on a wiki than a blog. If there’s anyone else out there that wants to contribute, I’m open-minded. I’m leaning toward things that are contemporary rather than historic in value.
I think the concurrency problem is pretty well solved for one class of application: the Web server and most of what runs in it. If you know what you’re doing, whether you’re working in an Apache module or Java EE or Rails or Django or PHP or .NET, given enough load you can usually arrange to saturate as many cores as you can get your hands on.
That’s a big chunk of the application space, but not all of it. And even in web apps, it’s not uncommon to have pure application code that needs to wrestle the concurrency dragon.
I’m taking the following as an axiom: Exposing real pre-emptive threading with shared mutable data structures to application programmers is wrong. Once you get past Doug Lea, Brian Goetz, and a few people who write operating systems and database kernels for a living, it gets very hard to find humans who can actually reason about threads well enough to be usefully productive.
When I give talks about this stuff, I assert that threads are a recipe for deadlocks, race conditions, horrible non-reproducible bugs that take endless pain to find, and hard-to-diagnose performance problems. Nobody ever pushes back.
We are living a drastic change, something close to a revolution with the new Sun Oracle Database machine. Why ? With the critical use of enterprise flash memory, this architecture is not anymore reserved to data warehouses but very well suited to Online Transaction Processing. We are preparing benchmark results on this platform and actively shipping systems to customers. In the meantime, and in a suite of short entries, I will describe the key innovations at the heart of this environment.
Let's start with the Sun Flash Accelerator F20 PCIe Cards.
Each Exadata cell (or Sun Oracle Exadata Storage Server) include 384 GB total of flash storage producing up to 75,000 IOPS [8k block]. This capacity is obtained via four 96GB F20 PCIe cards detailed below. A full rack configuration comes equipped with 5.3TB of Flash storage and can produce an amazing 1 million IOPS [8k block]. This huge cache is not only used smartly and automatically by the Database machine but can also be user-managed via the ALTER TABLE STORAGE command and the CELL_FLASH_CACHE argument.
Here is the detailed architecture of the F20 PCIe card :

As you can see, we obtain the total 96GB capacity via four Disk on Module (DOM). Each DOM contains four 4GB SLC NAND component on the front side and four on the back side. It gives us a 32GB capacity of which 24GB is addressable. To even accelerate flash performance, 64MB of DDR-400 DRAM per DOM provide a local buffer cache.
Finally, the DOM need to manage all of its components, track faulty blocks, handle load balancing and communicate with the outside world using standard SATA protocols. This is achieved with a Marvell SATA2 Flash Memory Controller.
Outside of the four DOMS, a Supercapacitor module provides enough backup power to flush data from DRAM to non-volatile flash devices, therefore maintaining data integrity during a power outage. With a 5 years lifespan in a well-cooled chassis, this modules are superior to classic batteries.Finally, a LSI eight-port SAS controller connect the four DOMS to a 12-port SAS expander for external connectivity.
We measured in Sun labs a 16.5W power consumption per F20 card. We were able to produce 1GB/s in sequential read (1MB I/O) and 100,110 IOPS (4k random read) for each card. In addition, we can replace about two hundred 15k HDDs latest generation for a power consumption of 0.165 milliwatts per 4K I/O and an estimated MTBF of 227 years. Amazing !
See you next time in the wonderful world of benchmarking.
I can't think of a better reason to take the train up to San Francisco than the Monk's Kettle's Beer Pairing dinner. My second (or was it third?) beer dinner there was the November 4th event hosted by Firestone Walker Brewing Company. We all got comfortable and finished our happy hour beers (note to self: happy hour beer not necessary when dinner comes with 6 beers) in our seats along the kitchen. It took me awhile to write this up, as I left my notes there and had to return again to retrieve them (for December's dinner). :)
Our host welcomed us and quickly told us, "No driving. The training wheels are off. These are real beers," and beer service began! All of these beers were barrel aged and got their primary fermentation in oak barrels, and they got stronger as the night went on.
We started with a nice English style pale ale poured from the cask, Double Barrel Ale. It was light and fruity, coming in at a nice 5%. This was paired with a delightful crostini with white bean puree and olive tapenade. YUM! This small amuse-bouche was delicious and a great way to start.
The salad course was served with a saison, Lil' Opal. We learned that this beer was actually an accident when it was created when a batch of Big Opal ended up too much sugar. I love happy little surprises like this! We all loved this beer, for its lemony and sweet flavor, with just a touch of hoppiness. My friend Lucas said, "It tastes like when doves cry". An unexpected and apt 80s references. but... then the salad came. The salad itself (red Belgian endives, baby letuces, shaved red onion, pomegranate seeds and feta) was delicious, but the "Lil' Opal Vinaigrette" did not pair well with the beer, changing the flavor to a distinctly PBR taste. Not terrible, but nowhere near as good as the beer tasted without the food. In the future, I hope that Chef Kevin stays away from vinegar in these dinners.
My favorite course was the house-cured bacon stuffed dates drizzled with a balsamic reduction and topped with pickled shallots, served with house made cheddar bread. They came with Walker's Reserve, a very robust porter. Four pounds of oatmeal go into each barrel, along with chocolate malt and cascade hops. The beer I could've repeated this course several times - delicious!
(Yes, I know Balsamic is a vinegar, but in this reduction, it was sweet and not acidic.)
The main course was "A Drunken Lamb, A Rare Bird" - the lamb leg had been marinated in the beer that was paired with the course, Black Xantus, and came out very tender and the match was made in heaven. The Black Xantus was a Russian Imperial Stout, made with Mexican coffee which made for a slightly bitter, but very nice, flavor. This is a beer that can really get you in trouble, coming in at 11% ABV!
For dessert, the scrumptious chocolate fondant cake was served hot with a side of Chantilly cream and mint. There were also some "drunken Fuyu persimmons", but they had been left in the "cheap" bourbon a bit too long and we couldn't really eat them.
The bonus? Dessert came with two beers! Yay! Abucus, which was an American Barleywine coming in at 12% ABV, paired wonderfully with the chocolate cake, with its own dark cherry and chocolate flavors soaring when enjoyed together with the cake. I also enjoyed the Firestone Twelve (which had been cellared for one year), another 12% ABV. The Twelve had been aged in bourbon and brandy barrels, and then blended.
I really enjoy these dinners, as there is no rush, service is outstanding, and you get to hear directly from the brewers so you fall in love with the beer as much as they have. And while the event is not rushed, the staff is aware that we've all come via public transport and we always finish with time to pay the bill and get to the Caltrain station. :)
Twitter will have to go down as the internet craze of 2009. However is Twitter more than a means for celebrities to let us know what they get up to a daily basis and a way in which I can tell the word what I had for breakfast and guess what I just had a coffee. Can Twitter be a useful tool for business to drive traffic and sales? This will be the key to the ultimate success of Twitter and its value.
Dell computer is leading the way in using Twitter as a sales driver. Dell has recently announced that it has generated more than US$ 6.5 million in sales via Twitter microbogs and has more than one million followers on its Twitter account and has tripled revenues coming in from Tweeted offers for Dell PCs in the past year and is doing business in dozens of countries in this way. All Dell is doing is offering good deals such as "get a free mouse with any laptop purchase" through Twitter tweets with links to a Dell outlet on line. This is example of the business harnessing the power of Twitter and this will only add to the potential value of Twitter.

I'm back blogging! It has been a busy time over recent months.. however I am back in the blogosphere! Look out for some interesting blogs on my Sun Blog!
Watch the brief Introduction to Shared Shell Video to learn more about this useful collaborative service tool.
The Hybrid Storage Pool integrates flash into the storage hierarchy in two specific ways: as a massive read cache and as fast log devices. For read cache devices, Readzillas, there's no need for redundant configurations; it's a clean cache so the data necessarily also resides on disk. For log devices, Logzillas, redundancy is essential, but how that translates to their configuration can be complicated. How to decide whether to stripe or mirror?
Logzillas are used as ZFS intent log devices (slogs in ZFS jargon). For certain synchronous write operations, data is written to the Logzilla so the operation can be acknowledged to the client quickly before the data is later streamed out to disk. Rather than the milliseconds of latency for disks, Logzillas respond in about 100μs. If there's a power failure or system crash before the data can be written to disk, the log will be replayed when the system comes back up, the only scenario in which Logzillas are read. Under normal operation they are effectively write-only. Unlike Readzillas, Logzillas are integral to data integrity and they are relied upon for data integrity in the case of a system failure.
A common misconception is that a non-redundant Logzilla configuration introduces a single point of failure into the system, however this is not the case since the data contained on the log devices is also held in system memory. Though that memory is indeed volatile, data loss could only occur if both the Logzilla failed and the system failed within a fairly small time window.
While a Logzilla doesn't represent a single point of failure, redundant configurations are still desirable in many situations. The Sun Storage 7000 series implements the Hybrid Storage Pool, and offers several different redundant disk configurations. Some of those configurations add a single level of redundancy: mirroring and single-parity RAID. Others provide additional redundancy: triple-mirroring, double-parity RAID and triple-parity RAID. For disk configurations that provide double disk redundancy of better, the best practice is to mirror Logzillas to achieve a similar level of reliability. For singly redundant disk configurations, non-redundant Logzillas might suffice, but there are conditions such as a critically damaged JBOD that could affect both Logzilla and controller more or less simultaneously. Mirrored Logzillas add additional protection against such scenarios.
Note that the Logzilla configuration screen (pictured) includes a column for No Single Point of Failure (NSPF). Logzillas are never truly a single point of failure as previous discussed; instead, this column refers to the arrangement of Logzillas in JBODs. A value of true indicates that the configuration is resilient against JBOD failure.
The most important factors to consider when deciding between mirrored or striped Logzillas are the consequences of potential data loss. In a failure of Logzillas and controller, data will not be corrupted, but the last 5-30 seconds worth of transactions could be lost. For example, while it typically makes sense to mirror Logzillas for triple-parity RAID configurations, it may be that the data stored is less important and the implications for data loss not worthy of the cost of another Logzilla device. Conversely, while a mirrored or single-parity RAID disk configuration provides only a single level of redundancy, the implications of data loss might be such that the redundancy of volatile system memory is insufficient. Just as it's important to choose the appropriate disk configuration for the right balance of performance, capacity, and reliability, it's at least as important to take care and gather data to make an informed decision about Logzilla configurations.
Projects hosted on Kenai.com can have three different kinds of source code repositories: git, mercurial, and subversion. With git and mercurial, developers often use ssh for access. However, this requires at least one public key to be uploaded to the site. If you are having problems accessing a repository using ssh, you can test to see if your uploaded key is correct by invoking ssh from the command line on the host with the corresponding private key. Substitute your own Kenai.com username in the examples below. My username is edwingo and the following means a successful public key upload:
$ ssh [email protected] Hi, edwingo! You have successfully authenticated, but we do not provide shell access. Connection to kenai.com closed.
If you receive some other kind of error, such as:
Permission denied (publickey,keyboard-interactive)
please check that your public key has been uploaded correctly to the SSH keys tab of your profile.
This entry was updated on 2009-12-09 to reflect the improved SSH keys tab user interface. (Soon subversion will also be accessible via ssh.)