<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-89287579799971239</id><updated>2011-10-23T22:24:26.979-07:00</updated><category term='J2ME'/><category term='pure lazy'/><category term='tuples by example'/><category term='Lamda'/><category term='JSObject'/><category term='tuples'/><category term='OpenSolaris libc'/><category term='salesforce.com'/><category term='Java ME'/><category term='Java JavaScript'/><category term='.NET CF'/><category term='upgrade'/><category term='for comprehensions'/><category term='URE'/><category term='objective-c'/><category term='Web stack'/><category term='POX'/><category term='bfs'/><category term='SCJP 5.0'/><category term='Solaris'/><category term='Java EE 6'/><category term='Flex'/><category term='singlet'/><category term='Apache'/><category term='Load balancer loadbalancer'/><category term='BigInt'/><category term='hg'/><category term='SJSWS'/><category term='BIOS'/><category term='.NET 3.5'/><category term='Cloud computing'/><category term='chillipower'/><category term='sort'/><category term='Curried functions'/><category term='Java EE'/><category term='Netbeans 6.1'/><category term='azure'/><category term='example'/><category term='WCF3.5'/><category term='OpenOffice'/><category term='DotNet'/><category term='Adobe LiveCycle'/><category term='streams'/><category term='Compression'/><category term='LiveCycle'/><category term='OpenSolaris'/><category term='interface builder'/><category term='iPhone'/><category term='Large LBA'/><category term='implicit conversion'/><category term='b60e'/><category term='build'/><category term='scala for comprehesions'/><category term='Diffie-Hellman'/><category term='Blog'/><category term='LISP'/><category term='.NET'/><category term='vmware server 2.0'/><category term='partial application'/><category term='Microsoft'/><category term='REST Describe'/><category term='Zones'/><category term='crt'/><category term='iPhone dev'/><category term='UNO'/><category term='Euclid&apos;s Algorithm'/><category term='lazy'/><category term='Scala'/><category term='Http'/><category term='Compact framework'/><category term='Connection pooling'/><category term='JSR-311'/><category term='Certificates'/><category term='NWAM'/><category term='project euler problem 12'/><category term='SSL'/><category term='GZIP'/><category term='JSON'/><category term='mod_jk'/><category term='Scheme'/><category term='Modular exponentiation'/><category term='Scala-lang'/><category term='signed'/><category term='main'/><category term='Actors'/><category term='Scala concurrency'/><category term='image-update'/><category term='Google'/><category term='JDBC'/><category term='X509'/><category term='partial functions'/><category term='Scala ant'/><category term='placeholders'/><category term='task'/><category term='Quantum entanglement'/><category term='WADL'/><category term='GlashFish v3'/><category term='bootstrap'/><category term='Java ME JSR 216'/><category term='library problems'/><category term='Ant'/><category term='Applet'/><category term='mobile'/><category term='connector'/><category term='Blastwave'/><category term='Metro'/><category term='DNS'/><category term='SQL'/><category term='Service model'/><category term='SICP'/><category term='HTTPS'/><category term='Solaris networking'/><category term='singleton'/><category term='REST Compile'/><category term='SELinux'/><category term='Fon'/><category term='Flash'/><category term='GlassFish 2.1'/><category term='XMing'/><category term='XNest'/><category term='bootstrapconnector'/><category term='selfsigned'/><category term='Scala Servlet'/><category term='insertion sorting'/><category term='X11'/><category term='Jersey'/><category term='force.com'/><category term='Security context'/><category term='Open Solaris'/><category term='MySQL'/><category term='dfs'/><category term='httpd'/><category term='vmware'/><category term='CentOS'/><category term='object'/><category term='Apache HTTPD 2.2.x'/><category term='if expression'/><category term='XML'/><category term='compile'/><category term='zipWithIndex'/><category term='Binary Tree'/><category term='mercurial hg'/><category term='Haskell'/><category term='xcode'/><category term='integration'/><category term='Tree'/><category term='CSharp'/><category term='iPhone JSON client'/><category term='traits and mixins'/><category term='JavaScript'/><category term='Wireless'/><category term='case class'/><category term='certs'/><category term='triangle numbers'/><category term='Glassfish 3'/><category term='SCJP'/><category term='Sieve of Eratosthenes'/><category term='Louis'/><category term='LBA'/><category term='JNDI'/><category term='GlassFish AS'/><category term='anonymous class'/><category term='Function'/><category term='functional'/><category term='b93'/><category term='Currying'/><category term='class'/><category term='blank screen'/><category term='LBA-48'/><category term='REST code gen'/><category term='DD-WRT'/><category term='scala for'/><category term='ZFS'/><category term='OpenOffice 3.0'/><category term='JVM'/><category term='Glassfish Portfolio'/><category term='REST'/><category term='stream'/><category term='sorting'/><category term='Java'/><category term='Air'/><category term='Prime factorization'/><category term='Google App Engine'/><category term='Delegates'/><category term='constructor'/><category term='partially applied functions'/><category term='C#'/><category term='pattern matching'/><category term='primes'/><category term='Quantum mechanics'/><category term='implicit'/><category term='appengine'/><category term='WCF'/><category term='2008.11'/><category term='functional programming'/><category term='cloudforce'/><category term='Stunnel'/><category term='Glassfish'/><category term='code gen'/><category term='mercurial'/><category term='vmware tools'/><category term='Xephyr'/><title type='text'>Louis Botterill's mostly software and techy Blog</title><subtitle type='html'>My mostly technical blog. An on-line journal of my activity in the IT industry and any other technical interests or techy things that happen to catch my attention.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>66</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-6321891946615994938</id><published>2010-02-03T10:34:00.000-08:00</published><updated>2010-02-03T10:59:49.197-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GlashFish v3'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='Java EE'/><category scheme='http://www.blogger.com/atom/ns#' term='Glassfish'/><category scheme='http://www.blogger.com/atom/ns#' term='Java EE 6'/><title type='text'>GlassFish v3 and Java EE 6 Sun-Oracle roadshow - key notes</title><content type='html'>&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;GlassFish Roadshow 2010 - London 03-02-2010&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The following is some notes I took down during the above event.&lt;br /&gt;&lt;br /&gt;In brief summary of GlassFish v3 and Java EE 6, here are some of the key takeaways:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;GlassFish v3 continues to be developed and supported, as the Java EE 5 &amp;amp; 6 RI app server&lt;/li&gt;&lt;li&gt;GlassFish v3 currently has no clustering, but offers OSGi modularization and extensibility&lt;/li&gt;&lt;li&gt;Supports and takes advantage of new Java EE 6 specifications&lt;/li&gt;&lt;li&gt;Big push on modularity and flexibility in both GlassFish and Java EE 6&lt;/li&gt;&lt;li&gt;Java EE 6 supports annotation based EJBs, RESTful web services&lt;/li&gt;&lt;li&gt;Java EE 6 greatly simplified configuration, optional web-inf.xml etc&lt;/li&gt;&lt;li&gt;Java EE 6 simplied simple class EJBs and improved JPA specification&lt;/li&gt;&lt;li&gt;Ongoing road-map for GlassFish, details TBA later this year&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Java EE 6 (Roberto&lt;/span&gt;&lt;span style="visibility: visible; font-weight: bold;" id="main"&gt;&lt;span style="visibility: visible;" id="search"&gt; Chinnici&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Released Dec 10 2009&lt;br /&gt;&lt;br /&gt;Key new features: New API, Web profiles, Pluggabiliy, dependancy injection&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;New technologies:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Jax-RS 1.1&lt;/li&gt;&lt;li&gt;Bean validation 1.0&lt;/li&gt;&lt;li&gt;DI 1.0&lt;/li&gt;&lt;li&gt;CDI 1.0&lt;/li&gt;&lt;li&gt;Managed beans 1.0&lt;/li&gt;&lt;/ul&gt;Closed down gap between EJB and POJO with unification and annotations&lt;br /&gt;&lt;br /&gt;CDI works with POJO and EJB classes&lt;br /&gt;&lt;br /&gt;Unification of platform types, more uniform programming model&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;EJB 3.1&lt;/li&gt;&lt;li&gt;JPA 2.0&lt;/li&gt;&lt;li&gt;Servlet 3.0&lt;/li&gt;&lt;li&gt;JSF 2.0&lt;/li&gt;&lt;li&gt;Connectors 1.6&lt;/li&gt;&lt;li&gt;Interceptors 1.1&lt;/li&gt;&lt;li&gt;JAX-WS 2.2&lt;/li&gt;&lt;li&gt;JSR-109 1.3&lt;/li&gt;&lt;li&gt;JSP 2.2&lt;/li&gt;&lt;li&gt;JSR-250 1.1&lt;/li&gt;&lt;li&gt;JACC 1.4&lt;/li&gt;&lt;li&gt;JASPIC 1.1&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Key goal in Java EE 6 - flexibility, pruning, extensibility and web profiles&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Profiles:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  Bundles of technologies targeting specific classes of applications&lt;br /&gt;  Decoupled from each other and the platform&lt;br /&gt;  Guarantees compatibility of required technologies, individually and in combination - must satisfy all joint requirements&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Web Profile:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Modern Java web application stack&lt;br /&gt;First profile to be definite&lt;br /&gt;Mid sized, fully functional (expected 80% web-app coverage), add additional components via extensibility (such as web services API, 3rd party frameworks)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Web profile contents:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Servlet, JSP/EL, JSTL, JSF, Bean Validation, EJB Lite, JPA, JTA, Di, CDI, Managed beans, Interceptors, JSR-250&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Pruning:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Goal - to address bloat concerns&lt;br /&gt;&lt;br /&gt;2 step process:&lt;br /&gt;  Declare components as "Proposed optional"&lt;br /&gt;  The make fully optional for the next release&lt;br /&gt;&lt;br /&gt;Proposed optional technologies:&lt;br /&gt;&lt;br /&gt;  JAX-RPC (JAX-WS)&lt;br /&gt;  EJB 2.x Entity beans (JPA entity classes)&lt;br /&gt;  JAXR (little use)&lt;br /&gt;  JSR-88 (deployment, tools API - not used)&lt;br /&gt;&lt;br /&gt;* Don't use - use replacements / alternatives&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Pluggability / extensibility:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Focus on web tier&lt;br /&gt;Level playing field for 3-rd party libraries and frameworks&lt;br /&gt;Two major extensibility points: Servlets and CDI&lt;br /&gt;Simplify packaging of web-apps&lt;br /&gt;  Zero-configuration!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Modular Web applications:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Libraries can contain web-fragment.xml descriptor&lt;br /&gt;web.xml is now optional&lt;br /&gt;Can server resources out of jars with: /META-INF/resources&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;/WEB-INF/lib/catalog.jar&lt;br /&gt;    /META-INF/resources/catalog/books.html&lt;br /&gt;&lt;br /&gt;e.g. Dojo jar in resources&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Web fragments in servlet 3.0:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;META-INF.web-fragment.xml&lt;br /&gt;&lt;br /&gt;same structure as web.xml, can override in web.xml&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Servlet container pluggability:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ServletContainerInitializer interface implements by extensions&lt;br /&gt;&lt;br /&gt;@HandlesTypes to declare interest in on or more annotation types&lt;br /&gt;&lt;br /&gt;ServletContext now contains method to dynamically register servlets and filters&lt;br /&gt;  i.e. ServletContext API has been extended&lt;br /&gt;&lt;br /&gt;Registered using META-INF/services&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;onStartup method gets called with a Set of classes available&lt;br /&gt;&lt;br /&gt;** Can only add services at startup, not dynamically once running&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Asynchronous HTTP processing:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;New programming model for async request processing&lt;br /&gt;e.g. Comet, char, push apps&lt;br /&gt;Opt-in model&lt;br /&gt;Threads are managed by the container&lt;br /&gt;&lt;br /&gt;@WebServlet(asyncSupported=true)&lt;br /&gt;public class MyServlet extends HTTPServlet {&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Goal - Decouple requests from threads&lt;br /&gt;&lt;br /&gt;* Changes to the way filters work - thread not attached to the socket, response not written. Filters modified to make safe - option than can be turned on to identify asyncSupported=true&lt;br /&gt;  - do this on servlet and any filter involved in the chain&lt;br /&gt;&lt;br /&gt;Ideal when waiting for some external resource etc.&lt;br /&gt;  Low level API - not very elegant&lt;br /&gt;  Idea is that frameworks will use this - see for example Atmosphere framework which is based on annotations - under the hood this async API is used.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;JSF 2.0:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Facelet as a standard view declaration language&lt;br /&gt;Composite components&lt;br /&gt;Ajax (declarative and programmatic) e.g. f:ajax tag&lt;br /&gt;Partial state saving (track deltas and sends changes in response, previously all would have been sent even if not changed!)&lt;br /&gt;System events e.g. f:event tag&lt;br /&gt;Resources&lt;br /&gt;Validation e.g. new f:validateBean tag (better integration, validation API. can handle multiple errors, not first one at a time!)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;EJB 3.1:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;@Singleton beans&lt;br /&gt;@Startup beans (invoked at app startup, works well with Singleton pattern)&lt;br /&gt;@Asynchronous invocations (biggest change, allows non-blocking sync EJB invocations as first class call. Method must be either void or return a Future object)&lt;br /&gt;No interface view  (bean impl does not need an interface anymore, now 1 class = 1 EJB!)&lt;br /&gt;Define EJBs directly inside a web app, inside a war file&lt;br /&gt;New API - EJBContainer API works on Java SE, can bootstrap an EJB container in a Java SE application (ideal for testing/development, could be useful in client applications)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Simplified packaging:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;EJB class directly into the war file&lt;br /&gt;Previously must built an EJB jar to be included&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;EJB 3.1 lite:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A subset of EJB 3.1&lt;br /&gt;All types of session beans (stageful, stateless, singleton) - other bean types not supported (timer, entity etc)&lt;br /&gt;Declarative transactions and security&lt;br /&gt;Interceptors&lt;br /&gt;ejb-jar.xml descriptor allows (is optional, probably not useful)&lt;br /&gt;&lt;br /&gt;* Class loading, new visibility rules in Java EE spec&lt;br /&gt;&lt;br /&gt;Slight differences in class loading rules - if in doubt check the specs&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;New JNDI Namespaces:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Until now - only java:comp&lt;br /&gt;Now added:&lt;br /&gt;  java:module - a module (war, ejb, jar)&lt;br /&gt;  java:app - an application&lt;br /&gt;  java:global  the whole server / cluster&lt;br /&gt;&lt;br /&gt;e.g. @Resource(lookup="java:app/CustomerDB") DataSource db;&lt;br /&gt;&lt;br /&gt;EJB components have global names now:&lt;br /&gt;&lt;br /&gt;e.g. java:global/app1/module2/SomeBeanIcom.acme.Foo&lt;br /&gt;&lt;br /&gt;Helps solve problem of remote EJB communication in same app server&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Dependency injection (DI):&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Combination of DI 1.0 / CDI 1.0&lt;br /&gt;New @Inject annotation&lt;br /&gt;@Inject @LoggedIn User user; (@LoggedIn = "Which one", User  = "What")&lt;br /&gt;Beans auto-discovered at start-up&lt;br /&gt;Extensible&lt;br /&gt;  Injection metamodel (BeanManager API)&lt;br /&gt;@Resource still available for container resources&lt;br /&gt;&lt;br /&gt;* Identified by type and qualifiers (no longer just a string name alone)&lt;br /&gt;&lt;br /&gt;* No bean declaration as per Spring declaration, bean discovery at startup&lt;br /&gt;* Injection errors all reported at startup, rather than on use at runtime&lt;br /&gt;&lt;br /&gt;Beans can be associated with session - i.e. loggedIn&lt;br /&gt;Beans can be more ephemeral, i.e. for request&lt;br /&gt;Beans can be more long lived, i.e. shopping cart conversation flows&lt;br /&gt;Can add class for beans on the fly, via APIs at runtime&lt;br /&gt;&lt;br /&gt;Example of DI annotation:&lt;br /&gt;&lt;br /&gt;@Inject&lt;br /&gt;CheckoutHandler(&lt;br /&gt;  @LoggedIn User user,&lt;br /&gt;  @Reliable @PayBy(CREDIT_CARD)&lt;br /&gt;  PaymentProcessor processor,&lt;br /&gt;  @Default Cart cart)&lt;br /&gt;&lt;br /&gt;* Note that constructor injection is possible&lt;br /&gt;* Note different scopes, PaymentProcessor is probably conversation scope, LoggedIn is session, PaymentProcessor is probably application scope singleton&lt;br /&gt;&lt;br /&gt;* Instance and state management handled "for free" by framework/APIs&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;JAX-RS 1.1:&lt;/span&gt;&lt;br /&gt;  Already widely adoped&lt;br /&gt;Really a high level HTTP API&lt;br /&gt;Annotation-based programming model&lt;br /&gt;Programmatic API when needed&lt;br /&gt;&lt;br /&gt;* think of it as the new HTTP level API (higher level than HTTPServlets, remove low level detail and tedium)&lt;br /&gt;&lt;br /&gt;Jax-RS resource class, example:&lt;br /&gt;&lt;br /&gt;Identified by the @Path annotation&lt;br /&gt;&lt;br /&gt;@Path("widgets./{id}")&lt;br /&gt;@Produces("application/widgets+xml")&lt;br /&gt;public class WidgetResource {&lt;br /&gt;  pubic WidgetResource(@PathParam("id") String id { … }&lt;br /&gt; &lt;br /&gt;  @GET&lt;br /&gt;  Widget getWidget() { … }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Provides higher level HTTP handling, more declarative, better match with conceptual needs of developer&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Bean Validation 1.0:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Integrated with JSF, JPA&lt;br /&gt;Constraints represented by annotations&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;&lt;br /&gt;  @NotNull&lt;br /&gt;  @Size(max=40)&lt;br /&gt;  String address;&lt;br /&gt;&lt;br /&gt;Fully extensible&lt;br /&gt;  @Email&lt;br /&gt;  String recipient;&lt;br /&gt;&lt;br /&gt;Validation API's for validation directly, create a new validation object etc&lt;br /&gt;Validation of trees of objects is possible (including loops)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;JPA 2.0:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Supported for collections of basic types and embeddable objects&lt;br /&gt;JPQL enhancements e.g. CASE WHEN, NULLIF&lt;br /&gt;Pessimistic locking added (annotations added)&lt;br /&gt;Criteria API for dynamic query construction&lt;br /&gt;&lt;br /&gt;Criteria API: Uses the canonical metamodel classes&lt;br /&gt;&lt;br /&gt;CriteriaBuilder, create criteria&lt;br /&gt;CriterialQuery, typed criteria&lt;br /&gt;&lt;br /&gt;Strongly types checking, type parasitised equals checking, compiler errors generated if query does not have the right types etc, so robust and safe query (rather than say String SQL construction directly).&lt;br /&gt;&lt;br /&gt;Connectors 1.6 added too (not covered in any detail)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Summary overview:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Improved, more powerful, more flexible, more extensible, easier to use&lt;br /&gt;&lt;br /&gt;&lt;a href="http://java.sun.com/javaee"&gt;http://java.sun.com/javaee&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;GlassFish V3 (Alexis Moussine-Pouchkine):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Java EE 6 Reference Implementation (RI)&lt;br /&gt;&lt;br /&gt;Geographic download map:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://maps.glassfish.org/server"&gt;http://maps.glassfish.org/server&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Healthy increase in downloads and usage over time&lt;br /&gt;&lt;br /&gt;GlassFish V1 first shipped 2006, reusing much from Tomcat&lt;br /&gt;&lt;br /&gt;V2.1.1 Nov 2009, V3 (Java EE 6) Dec 10th 2009&lt;br /&gt;&lt;br /&gt;GlassFish V3 Open Source CDDL, GPL (with 'classpath exception') licensing&lt;br /&gt;&lt;br /&gt;Java EE 5 &amp;amp; 6, enterprise quality - full support is available.&lt;br /&gt;&lt;br /&gt;Sub projects:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;  Jersey (JAX-RS)&lt;/li&gt;&lt;li&gt;  Metro (JAX-WS)&lt;/li&gt;&lt;li&gt;  Grizzly (NIO)&lt;/li&gt;&lt;li&gt;  Atmosphere (Comet)&lt;/li&gt;&lt;li&gt;  OpenMQ (JMS)&lt;/li&gt;&lt;li&gt;  and scripting jRoR Grails and now Django (python)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Main difference from Tomcat - Grizzly core (rewritten)&lt;br /&gt;&lt;br /&gt;Netbeans 6.8 tooling&lt;br /&gt;Support available in Eclipse too&lt;br /&gt;&lt;br /&gt;GlassFish development continues&lt;br /&gt;Support contracts through to 2017+ unlimited&lt;br /&gt;Remains the Java EE reference implementation&lt;br /&gt;Now also sold with WebLogic and standalone&lt;br /&gt;&lt;br /&gt;Roadmap -&gt; expected soon for remaining year&lt;br /&gt;&lt;br /&gt;Don't have to deliver as much standard runtime / frameworks jars as part of the application jar&lt;br /&gt;&lt;br /&gt;Netbeans in-place edit of classes, incremental compilation, deploy on save, GF v3 preserves session across redeployments(!)&lt;br /&gt;&lt;br /&gt;Session retention:&lt;br /&gt;  Deployment option to maintain statefull sessions across re-deployments!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;GlassFish v3 key goals:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Modular and dynamic&lt;br /&gt;  Modular: Apache Felix (OSGi)&lt;br /&gt;  Extensible: HK2 (100k kernel)&lt;br /&gt;  Still very fast!&lt;br /&gt;&lt;br /&gt;Centralized configuration, modules configured through centralised control&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Key Features:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;No ejbjar.xml needed, no web.xml, annotation driven, EJB's as single classes&lt;br /&gt;&lt;br /&gt;Declarative annotations:&lt;br /&gt;&lt;br /&gt;@Stateless annotation for class stateless bean&lt;br /&gt;@Schedule annotation for timers&lt;br /&gt;&lt;br /&gt;Eclipse - GlassFish tool bundle for eclipse (contains everything!)&lt;br /&gt;&lt;br /&gt;Ultra fast auto-deploy of all Java EE and static artefacts&lt;br /&gt;&lt;br /&gt;Maven support: mvn gf:run gf:start gf-deploy&lt;br /&gt;&lt;br /&gt;Containers can be added / removed dynamically&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;New API for EJB testing (EJBContainer):&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;br /&gt;EJBContainer c = EJBContainer.createEJBContainer();&lt;br /&gt;Context ice = c.getContext();&lt;br /&gt;SimpleEjb ejb (SImpleEjb)ic.lookup("java:global/sample/SimpleEjb");&lt;br /&gt;ejb.sayHello();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;GlassFish "Embedded" - allows all features of GlassFish to be automated&lt;br /&gt;&lt;br /&gt;org.glassfish.api.embedded.Server server;&lt;br /&gt;Server.Build builder = new Server.Builder();&lt;br /&gt;server = builder.build();&lt;br /&gt;ContainerBuilder b = server.createConfig(ContainerBuilder.Type.web);&lt;br /&gt;server.addContainer(b);&lt;br /&gt;&lt;br /&gt;File archive = new File("hello.war");&lt;br /&gt;server.getDeployer().deply(archive);&lt;br /&gt;&lt;br /&gt;i.e. Ship app server inside an application!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;OSGi:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;GlassFish runs on top of OSGi (Felix by default)&lt;br /&gt;  Also runs unmodified on Knopflerfish and Equinox&lt;br /&gt;  GlassFish ships with 200+ bundles&lt;br /&gt;  Can run without OSGi (static mode based on HK2)&lt;br /&gt;  Can use OSGi management tools (CLI or Web)&lt;br /&gt;&lt;br /&gt;Any OSGi bundles will run in GlassFish v3&lt;br /&gt;  Drop it in glassfish/modules&lt;br /&gt;&lt;br /&gt;Servlets can get hold of OSGi bundles (using @Resource DI)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update centre:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Graphical tool (GlassFish does not need to be started), available in web admin console&lt;br /&gt;CLI version available&lt;br /&gt;Was in v2.x but not from admin console&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;RESTful admin API:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;JAX-RS/Jersey + Grizzly to provide REST interfaces to&lt;br /&gt;  Configure runtime (via GET, POST, DELETE)&lt;br /&gt;  Invoke commands (restart, stop, deploy, etc)&lt;br /&gt;  Monitoring (GET only)&lt;br /&gt;  Log rotation etc&lt;br /&gt; &lt;br /&gt;e.g. Available from:&lt;br /&gt;  localhost:4848/management/domain&lt;br /&gt;  localhost:4848/monitoring/domain&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Further advantages:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Dynamic language support via modules:&lt;br /&gt;  Rails, Grails, Django, Scala/Lift&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Comet:&lt;/span&gt;&lt;br /&gt;  Cometd/Bayeux&lt;br /&gt;  Atmosphere&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Full support for:&lt;/span&gt;&lt;br /&gt;  mod_jk&lt;br /&gt;  WebDAV, CGI, SSI&lt;br /&gt;&lt;br /&gt;OpenMQ 4.4&lt;br /&gt;&lt;br /&gt;Web Services Metro 1.4&lt;br /&gt;  .NET 3.5 interoperability&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;v3 Clustering:&lt;/span&gt;&lt;br /&gt;  Lower priority after Java EE 6 and modularity, so not yet...&lt;br /&gt;  Clustering is not built in as per v2&lt;br /&gt;  More similar to v1, single instance&lt;br /&gt;  Have to take on own clustering (load balancing, deployment)&lt;br /&gt;  See roadmap for details...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Doing More with GlassFish (Steve Elliott):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;GlassFish v3 - Management and monitoring&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Management:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;User Friendly, pluggable and extensible for administration&lt;br /&gt;Feature rich Admin console (GUI)&lt;br /&gt;Easy to use Command Line Interface (CLI)&lt;br /&gt;RESTful management and monitoring API&lt;br /&gt;Fully documented AMX API (app server management API)&lt;br /&gt;All management features built on AMX API&lt;br /&gt;&lt;br /&gt;OSGi, load on demand = fast initial start up&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;v3 AdminConsole:&lt;/span&gt;&lt;br /&gt;  Frame-set removed, now Ajax based pages&lt;br /&gt;  Pluggable console (admin panes, trees etc loaded on demand)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Monitoring:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Lightweight prode architecture&lt;br /&gt;Ad hoc monitoring in Production&lt;br /&gt;Client-scripting (JavaScript)&lt;br /&gt;DTrace integration on Solaris (similar to OS probes, uniform tracing experience with MySQL etc)&lt;br /&gt;Extensibility / Pluggability&lt;br /&gt;&lt;br /&gt;No overhead when there is no monitoring&lt;br /&gt;Allows Monitoring to be turned on in a production environment with minimal impact&lt;br /&gt;Generate and listen to only interested&lt;br /&gt;Turn on monitoring when needed&lt;br /&gt;BTrace integration&lt;br /&gt;  Portable and dynamic&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Instrumentation:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Modules expose probes&lt;br /&gt;  POJO with annotations&lt;br /&gt;  XML&lt;br /&gt;&lt;br /&gt;Modules register probe listeners&lt;br /&gt;&lt;br /&gt;In code, POJO annotations can be used&lt;br /&gt;&lt;br /&gt;@ProbeProvider(providername="glassfish", modulename="web")&lt;br /&gt;&lt;br /&gt;ProbeProvider XML configuration also possible&lt;br /&gt;&lt;br /&gt;ProbeListeners&lt;br /&gt;JMX exposed&lt;br /&gt;&lt;br /&gt;@ManagedAttribute(id="jspcount")&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;OSGi:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;big move to OSGi technology&lt;br /&gt;Big move to more modular development approach&lt;br /&gt;&lt;br /&gt;Demands and enforces stronger modularity&lt;br /&gt;&lt;br /&gt;OSGi is largely under the covers&lt;br /&gt;  Visible to GlassFish developers, but not to GlassFish users&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Service based architecture&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;  Core modules loaded on app startup&lt;br /&gt;  Rest loaded on demand&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Module Management:&lt;/span&gt;&lt;br /&gt;  add, remove, update installed modules&lt;br /&gt;&lt;br /&gt;OSGi as a container&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Web services - Metro : JAX-WS / Jersey : JAX-RS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Metro - SOAP-based web services stack&lt;br /&gt;  Built into GlassFish&lt;br /&gt;Works with any servlet 2.5 compliant web container&lt;br /&gt;  WebLogic, WebSphere, JBoss, Tomcat&lt;br /&gt;  Also standalone&lt;br /&gt;Advances interoperability with .NET 3.x/4.0&lt;br /&gt;&lt;br /&gt;Project Tango - focused on interoperability with .NET&lt;br /&gt;&lt;br /&gt;JAXB based XML Data Binding (XSD, XPATH)&lt;br /&gt;&lt;br /&gt;SOAP Messaging MTOM etc&lt;br /&gt;&lt;br /&gt;Bi-directional interoperability with .NET (Java or .NET as client or server)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Standards:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;JCP: JAX-WS 2.2 &amp;amp; JAXB 2.2&lt;br /&gt;W3C SPAP 1.1/1.2 WSDL 1.1, WS-Addressing&lt;br /&gt;… etc&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;JAX-RS&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;JAX-RS 1.1 is final and part of EE6&lt;br /&gt;&lt;br /&gt;Not a web profile&lt;br /&gt;  but included with GlassFish v3 web profile&lt;br /&gt;JCP 311&lt;br /&gt;Spec - JSR 311&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.oracle.com/java"&gt;http://www.oracle.com/java&lt;/a&gt;&lt;br /&gt;Contains links to GlassFish etc&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-6321891946615994938?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/6321891946615994938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=6321891946615994938' title='40 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6321891946615994938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6321891946615994938'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2010/02/glassfish-v3-and-java-ee-6-sun-oracle.html' title='GlassFish v3 and Java EE 6 Sun-Oracle roadshow - key notes'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>40</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-5506442292700211349</id><published>2009-11-01T11:52:00.001-08:00</published><updated>2009-11-01T12:59:14.445-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='project euler problem 12'/><category scheme='http://www.blogger.com/atom/ns#' term='triangle numbers'/><category scheme='http://www.blogger.com/atom/ns#' term='streams'/><category scheme='http://www.blogger.com/atom/ns#' term='stream'/><title type='text'>Project Euler 12 - Scala Streams, creating triangle numbers</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Just a short blog today on Scala Streams and generating numeric progressions, such as a simple arithmetic series&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is a solution to project Euler problem 12: &lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=12" style="text-decoration: none;" title="Click to view problem"&gt;"What is the value of the first triangle number to have over five hundred divisors?"&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is actually a fairly easy problem to solve, providing you use a sufficiently efficient function to count the divisors!&lt;br /&gt;&lt;br /&gt;The method I've adopted for this is particularly simple, but performs sufficiently well to solve this problem as stated within a few seconds.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Triangle Numbers:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Just a quick refresher, the triangle numbers are the sum of integers from 1 to n.&lt;br /&gt;&lt;br /&gt;An Arithmetic series is a number series of the form:&lt;br /&gt;&lt;br /&gt;a + (a + b) + (a + 2b) + ....&lt;br /&gt;&lt;br /&gt;and using this form the Triangle numbers can be written as:&lt;br /&gt;&lt;br /&gt; 1 + (1 + 1) + (1 + 2) + (1 + 3) + ...&lt;br /&gt;&lt;br /&gt;so they clearly are of the form of an Arithmetic series.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The more interesting aspect of this problem was the generation of the Triangle number sequence. Naturally, wanting to use Scala to solve this problem, the idea of using a Stream to evaluate the triangle number sequence lazily on demand is a natural approach.&lt;br /&gt;&lt;br /&gt;The implementation I settled on to produce the Stream of triangle numbers was the iterative version as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;val trianglesI = Stream.iterate((1L,0L)){&lt;br /&gt;            case (n, sum) =&amp;gt; (n + 1L, sum + n) }.map(_._2)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;       &lt;br /&gt;Which is a fairly natural way to solve via the additive definition of the triangle numbers.&lt;br /&gt;&lt;br /&gt;What's perhaps more interesting is finding some alternative ways to achieve the same thing, here are some alternatives to the iterative additive stream definition:&lt;br /&gt;&lt;br /&gt;Using the multiplicative definition of the Triangle numbers and the map function:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// use a stream map and the multiplicative solution for triangle numbers&lt;br /&gt;val trianglesM = Stream.from(1).map(n =&amp;gt; n * (n + 1) / 2)&lt;br /&gt;       &lt;br /&gt;println("trianglesM take(5)")&lt;br /&gt;trianglesM.take(5).foreach(println)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;Using "inits" - inits are a concept that can be found in languages such as Haskell:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// using inits (not efficient)&lt;br /&gt;// inits -&amp;gt; inits(Stream.from(1)) is Stream(Stream(), Stream(1), Stream(1, 2), Stream(1, 2, 3), ...)&lt;br /&gt;// and tails -&amp;gt; tails(Stream(1)) = Stream(Stream(1,2,3,...), Stream(2,3,4,...), Stream(3,4,5,...), ...)&lt;br /&gt;def inits[T](xs: Stream[T]) = Stream.from(0).map(xs.take(_))&lt;br /&gt;      &lt;br /&gt;val trianglesInits = inits(Stream.from(1)).tail.map(_.sum)&lt;br /&gt;&lt;br /&gt;println("trianglesInits take(5)")&lt;br /&gt;trianglesInits.take(5).foreach(println)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Using Stream.cons and a helper function zipWith that can zip tuples:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// using zipWith&lt;br /&gt;def zipWith[T1,T2,T3](s1: Stream[T1], s2: Stream[T2])(fn: (T1,T2) =&amp;gt; T3) = &lt;br /&gt;  s1.zip(s2).map(Function.tupled(fn))&lt;br /&gt;       &lt;br /&gt;lazy val trianglesZ: Stream[Int] = Stream.cons(1, zipWith(trianglesZ, &lt;br /&gt;  Stream.from(2))(_ + _))&lt;br /&gt;       &lt;br /&gt;println("trianglesZ take(5)")&lt;br /&gt;trianglesZ.take(5).foreach(println)&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So, whilst problem 12 is not too hard, the production of triangle numbers as lazy lists is quite interesting, being that there are several approaches that can be taken!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The whole program solution to problem 12 (and the alternative triangle number streams)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package projecteuler&lt;br /&gt;&lt;br /&gt;object Problem12 {&lt;br /&gt;&lt;br /&gt; def main(args : Array[String]) {&lt;br /&gt; &lt;br /&gt;  println("result = " + problem12(500))&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; def problem12(target : Int) {&lt;br /&gt; &lt;br /&gt;  // using Stream.iterate to create a lazy stream of triangle numbers&lt;br /&gt;  val trianglesI = Stream.iterate((1L,0L)){ &lt;br /&gt;   case (n, sum) =&gt; (n + 1L, sum + n) }.map(_._2)&lt;br /&gt;  &lt;br /&gt;  // test it&lt;br /&gt;  //println("trianglesI take(5)")&lt;br /&gt;  //trianglesI.take(5).foreach(println)&lt;br /&gt;  &lt;br /&gt;  // count the divisors (not massively efficient, but sufficient)&lt;br /&gt;  def numDivisors(n : Long) = {&lt;br /&gt;   &lt;br /&gt;   var count = 0&lt;br /&gt;   &lt;br /&gt;   for (i &lt;- 1L to Math.sqrt(n).toInt) {&lt;br /&gt;    if (n % i == 0) {&lt;br /&gt;     count = count + 2&lt;br /&gt;    } &lt;br /&gt;   }&lt;br /&gt;   count&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  trianglesI.find(p =&gt; numDivisors(p) &gt; target)&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  def otherTriangleStreams {&lt;br /&gt;   &lt;br /&gt;    // use a stream map and the multiplicative solution for triangle numbers&lt;br /&gt;  val trianglesM = Stream.from(1).map(n =&gt; n * (n + 1) / 2)&lt;br /&gt;  &lt;br /&gt;  println("trianglesM take(5)")&lt;br /&gt;  trianglesM.take(5).foreach(println)&lt;br /&gt;  &lt;br /&gt;  // using inits (not efficient)&lt;br /&gt;  // inits -&gt; inits(Stream.from(1)) is Stream(Stream(), Stream(1), Stream(1, 2), Stream(1, 2, 3), ...)&lt;br /&gt;  // tails -&gt; tails(Stream(1)) = Stream(Stream(1,2,3,...), Stream(2,3,4,...), Stream(3,4,5,...), ...)&lt;br /&gt;  def inits[T](xs: Stream[T]) = Stream.from(0).map(xs.take(_))&lt;br /&gt;  &lt;br /&gt;  val trianglesInits = inits(Stream.from(1)).tail.map(_.sum)&lt;br /&gt;  &lt;br /&gt;  println("trianglesInits take(5)")&lt;br /&gt;  trianglesInits.take(5).foreach(println)&lt;br /&gt;  &lt;br /&gt;  // using zipWith&lt;br /&gt;  def zipWith[T1,T2,T3](s1: Stream[T1], s2: Stream[T2])(fn: (T1,T2) =&gt; T3) = s1.zip(s2).map(Function.tupled(fn))&lt;br /&gt;  &lt;br /&gt;  lazy val trianglesZ: Stream[Int] = Stream.cons(1, zipWith(trianglesZ, Stream.from(2))(_ + _))&lt;br /&gt;  &lt;br /&gt;  println("trianglesZ take(5)")&lt;br /&gt;  trianglesZ.take(5).foreach(println)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-5506442292700211349?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/5506442292700211349/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=5506442292700211349' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/5506442292700211349'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/5506442292700211349'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/11/project-euler-12-scala-streams-creating.html' title='Project Euler 12 - Scala Streams, creating triangle numbers'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-1074793110665060072</id><published>2009-09-27T09:31:00.000-07:00</published><updated>2009-09-27T10:00:27.529-07:00</updated><title type='text'>Scala &amp; GUIs, a simple maze generator and solver applet</title><content type='html'>In this blog we will touch on using &lt;span style="font-weight: bold;"&gt;Scala&lt;/span&gt; for a simple &lt;span style="font-weight: bold;"&gt;GUI&lt;/span&gt;, in the form of a simple &lt;span style="font-weight: bold;"&gt;2D Maze Applet&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;An example of this applet can be viewed running from here &lt;a href="http://www.chillipower.com/examples/maze/maze1.html"&gt;http://www.chillipower.com/examples/maze/maze1.html&lt;/a&gt; to give an illustration of what it does. This uses a maze space of 100x100 cells on a regular grid.&lt;br /&gt;&lt;br /&gt;The applet illustrates 2 aspects of GUI programming in Scala, the first is how to interact with basic javax.swing APIs directly and the second is how to go one step further and achieve the same effect using the scala.swing wrapper API instead.&lt;br /&gt;&lt;br /&gt;The function of the Applet can be broken down into 3 simple steps:&lt;br /&gt;&lt;br /&gt;Step 1: Produce a random maze. This uses a modified version of Prim's algorithm, running backwards from the exit until all of the available space has been covered. This will produce a simple path from the source to the exit, which is the path we seek when we try to solve the maze by starting at the start. The standard Prim's algorithm is used to produce a minimum spanning tree from a directed acyclic graph by recursively adding safe edges to the current minimum spanning tree recursively, starting at a source node.&lt;br /&gt;&lt;br /&gt;Step 2: Use a regular (recursive) DFS algorithm to search the maze, stopping only when the exit is reached (or all paths are explored fully if there were no reachable exit).&lt;br /&gt;&lt;br /&gt;Step 3: Remove all backtrack paths and show the single simple path from start to exit as the solution to the maze.&lt;br /&gt;&lt;br /&gt;During maze exploration, the parts of the maze explored are marked with coloured breadcrumbs, red indicates a forward search path and blue a backtracking path (which happens when a path reaches a dead-end).&lt;br /&gt;&lt;br /&gt;In step 2, in order to stop immediately when the exit is found (rather than conclude all other possible search branches) the recursive maze solving function throws an exception to escape out of the call stack immediately.&lt;br /&gt;&lt;br /&gt;The code given is compatible with the very latest Scala 2.8.x trunk development builds, and with 2.7.6 the latest stable release (some 2.7.6 only versions of functions such as shuffle are commented out in preference to the newer and better 2.8 versions). Note that there are currently some issues with Arrays in 2.8.x causing run time errors with trying to create a multidimensional array. The solution that still works with current 2.8 builds is to use the Array.tabulate function.&lt;br /&gt;&lt;br /&gt;i.e. the following works in 2.7.6 but not currently in 2.8:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;var cells : Array[Array[Cell]] = new Array[Array[Cell]](WIDTH, HEIGHT)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and there are similar problems with the new Array.ofDims function too. These issues should be resolved in 2.8 final release but recently arrays in scala have been undergoing some re-factoring and so stability in this area has not been too strong.&lt;br /&gt;&lt;br /&gt;One interesting thing to note is the use of the new Scala 2.8+ Stream.iterate function to avoid undesirable vars instead of vals, here is an example of that extracted from the code.&lt;br /&gt;&lt;br /&gt;A typical iterative piece of code, the while loops is used to iterate over some code block whilst a particular condition is met for a given variable. For this to work the variable n needs to be updated in the loop, hence it can't be a val and has to be a var instead. This is somewhat paradigmatic of iterative imperative programming, but doesn't sit well with the strive for a more functional style.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var n = cells(exit.x)(exit.y)&lt;br /&gt;&lt;br /&gt;while (n != null) {&lt;br /&gt;&lt;br /&gt; n.trail = Forward&lt;br /&gt; n = n.pi&lt;br /&gt; update&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What we can do here is make use of the Stream.iterate function to avoid the unsightly var n, as follows:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Stream.iterate(cells(exit.x)(exit.y))(_.pi).takeWhile(_ != null).foreach{&lt;br /&gt; n =&amp;gt; {&lt;br /&gt;   n.trail = Forward&lt;br /&gt;   update&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Given that this is new in Scala 2.8 and 2.8 isn't released yet, you can augment existing 2.7.6 code with a helper function to aid the transition and improve 2.7 based code in readiness for 2.8. Here is an example of a util class that defines iterate so the same idea can be used in 2.7 based code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def iterate[T](x:T)(f : T =&amp;gt; T) : Stream[T] =&lt;br /&gt;   Stream.cons(x, iterate(f(x))(f))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Another interesting thing to note in the code is the use of a permutation on a list (to create random directions when generating or exploring the maze), here is the code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def shuffle[T](xs: List[T], r: scala.util.Random) = {&lt;br /&gt;   xs.toStream.zip(Stream.const(r.nextDouble _).map(_())).toList.sort(_._2 &amp;lt; _._2).map(_._1)&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;The code maps the elements with a stream of random real numbers and then permutes by sorting the list, extracting the sorted items to create the random permutation (neat huh!)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;The above code is 2.7.x &amp;amp; 2.8+ compatible, but perhaps even better is the following 2.8+ code that makes use of the new Stream.continually function:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def shuffle[T](xs: List[T])(implicit r: scala.util.Random) = {&lt;br /&gt; xs.zip(Stream.continually(r.nextDouble)).sortWith(_._2 &amp;lt; _._2).map(_._1)&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;In terms of the GUI aspects, the application is an applet, and the example code shows 2 ways of achieving this in Scala. The first, using the swing API directly is as follows:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class MazeApplet2 extends JApplet {&lt;br /&gt;&lt;br /&gt; override def init() {&lt;br /&gt;   ...&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; override def start() {&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Which is familiar to any Java programmer, but the more interesting approach is using the scala.swing API instead, whereby we have:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class MazeApplet extends Applet {&lt;br /&gt;&lt;br /&gt; object ui extends UI with Reactor {&lt;br /&gt;&lt;br /&gt;   def init() = {&lt;br /&gt;     ...&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   override def start() = {&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Where the abstract ui attribute (of type UI) is implemented using the Reactor &lt;/span&gt;&lt;span style="font-style: italic;font-family:arial;" &gt;mixin&lt;/span&gt;&lt;span style="font-family:arial;"&gt; &lt;/span&gt;&lt;span style="font-style: italic;font-family:arial;" &gt;trait&lt;/span&gt;&lt;span style="font-family:arial;"&gt; (&lt;/span&gt;&lt;a href="http://www.scala-lang.org/docu/files/api/scala/swing/Reactor.html"&gt;&lt;span style="font-family:courier new;"&gt;http://www.scala-lang.org/docu/files/api/scala/swing/Reactor.html&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:arial;"&gt;), to provide the framework for event handling.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;One thing that's quite clear is the obviously similarity between the function to generate and the function to solve the maze. Using the DSL-like features of Scala it should be possible to extract the common control structure / algorithm and create a new utility function to provide built-in like support for this, passing in a body function to provide the difference implementation of maze generate vs. solve.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;Full code example:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/**&lt;br /&gt;* Scala 2.8+ Maze Applet v0.1 20-09-2009 Louis Botterill&lt;br /&gt;*/&lt;br /&gt;package maze&lt;br /&gt;&lt;br /&gt;import scala.swing.Applet&lt;br /&gt;import scala.swing.Panel&lt;br /&gt;import scala.swing.Reactor&lt;br /&gt;&lt;br /&gt;import javax.swing._;&lt;br /&gt;import java.awt.Graphics;&lt;br /&gt;import java.awt.Color;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;object Direction extends Enumeration {&lt;br /&gt; type Direction = Value&lt;br /&gt;   val North, South, East, West = Value&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;object Breadcrumb extends Enumeration {&lt;br /&gt; type Breadcrumb = Value&lt;br /&gt;   val Forward, Backward, Clear = Value&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;import Direction._&lt;br /&gt;import Breadcrumb._&lt;br /&gt;&lt;br /&gt;class MazeModel {&lt;br /&gt; val HEIGHT = 100&lt;br /&gt; val WIDTH = 100&lt;br /&gt;&lt;br /&gt; // instantiate and initialise the 2d array - there is a direct 2d version but not working currently in scala 2.8.x&lt;br /&gt; var cells = Array.tabulate(WIDTH)(i =&gt; Array.tabulate(HEIGHT)(j =&gt; Cell(i, j)))&lt;br /&gt;&lt;br /&gt; // set everything as not visited and with no trail&lt;br /&gt; def clearVisited() = {&lt;br /&gt;&lt;br /&gt;   cells.foreach(_.foreach(c =&gt; {&lt;br /&gt;         c.visited = false;&lt;br /&gt;         c.trail = Clear&lt;br /&gt;     }))&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; // generate maze&lt;br /&gt; def generateMaze(update :  =&gt; Unit) {&lt;br /&gt;&lt;br /&gt;   val exit = new Point(WIDTH - 1, HEIGHT - 1)&lt;br /&gt;   val start = new Point(0, 0)&lt;br /&gt;&lt;br /&gt;   // 1. Start at a particular cell, call it the "exit"&lt;br /&gt;   // 2. Mark the current cell as visited, and get a list of all its neighbors.&lt;br /&gt;   //      For each neighbor, starting with a randomly selected neighbor:&lt;br /&gt;   //   1. If that neighbor hasn't been visited,&lt;br /&gt;   //        remove the wall between this cell and that neighbor,&lt;br /&gt;   //        and then recurse with that neighbor as the current cell.&lt;br /&gt;&lt;br /&gt;   // cell 0,0 is the start, open the north wall to highlight this&lt;br /&gt;   var s = cells(0)(0)&lt;br /&gt;   s.clear(North);&lt;br /&gt;&lt;br /&gt;   // cell width-1,height-1 is the exit, open the south wall to highlight this&lt;br /&gt;   val c = cells(exit.x)(exit.y)&lt;br /&gt;   c.clear(South);&lt;br /&gt;&lt;br /&gt;   // recursively process the next cell&lt;br /&gt;   def doNextCell(c : Cell) {&lt;br /&gt;&lt;br /&gt;     c.visited = true&lt;br /&gt;     c.trail = Forward&lt;br /&gt;&lt;br /&gt;     var dirs = c.getRndDirections()&lt;br /&gt;&lt;br /&gt;     while (!(dirs isEmpty)) {&lt;br /&gt;       val dir = dirs.head&lt;br /&gt;       val x = getCell(c, dir)&lt;br /&gt;&lt;br /&gt;       x match {&lt;br /&gt;         case Some(n) =&gt;&lt;br /&gt;          &lt;br /&gt;           if (n.visited != true) {&lt;br /&gt;             n.visited = true&lt;br /&gt;             c.clear(dir)&lt;br /&gt;             n.clear(getInv(dir))&lt;br /&gt;             n.trail = Forward&lt;br /&gt;             update&lt;br /&gt;             doNextCell(n)&lt;br /&gt;             n.trail = Clear&lt;br /&gt;             update&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;         case None =&gt;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       dirs = dirs.tail&lt;br /&gt;&lt;br /&gt;       //Thread.sleep(1)&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   doNextCell(c)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; // find the maze solution using dfs from the start node until the end&lt;br /&gt; // node is located&lt;br /&gt; def solveMaze(update :  =&gt; Unit) {&lt;br /&gt;  &lt;br /&gt;   val start = new Point(0, 0)&lt;br /&gt;   val exit = new Point(WIDTH - 1, HEIGHT - 1)&lt;br /&gt;&lt;br /&gt;   val s = cells(0)(0)&lt;br /&gt;   s.clear(North);&lt;br /&gt;&lt;br /&gt;   def doNextCell(c : Cell) {&lt;br /&gt;&lt;br /&gt;     c.visited = true&lt;br /&gt;     c.trail = Forward&lt;br /&gt;&lt;br /&gt;     var dirs = c.getDirections()&lt;br /&gt;    &lt;br /&gt;     while (!(dirs isEmpty)) {&lt;br /&gt;       val dir = dirs.head&lt;br /&gt;       val x = getCell(c, dir)&lt;br /&gt;&lt;br /&gt;       x match {&lt;br /&gt;         case Some(n) =&gt;&lt;br /&gt;&lt;br /&gt;           if (n.visited != true) {&lt;br /&gt;             n.visited = true&lt;br /&gt;             n.pi = c  // set predecessor node&lt;br /&gt;             n.trail = Forward&lt;br /&gt;             update&lt;br /&gt;             if (n.i == exit.x &amp;amp;&amp;amp; n.j == exit.y) throw new Exception("Done")&lt;br /&gt;             doNextCell(n)&lt;br /&gt;             n.trail = Backward&lt;br /&gt;             update&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;         case _ =&gt;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       // take the top item off and use the rest of the list&lt;br /&gt;       dirs = dirs.tail&lt;br /&gt;      &lt;br /&gt;       Thread.sleep(1) // add a little delay so we can watch the dfs explore and find the solution&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   doNextCell(s)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; // from the exit recurse over the trail of predecessors,&lt;br /&gt; // marking with a forward trail&lt;br /&gt; def showSolution(update :  =&gt; Unit) {&lt;br /&gt;&lt;br /&gt;   val exit = new Point(WIDTH - 1, HEIGHT - 1)&lt;br /&gt;&lt;br /&gt;   // 2.8 avoid var using Stream&lt;br /&gt;   // Stream.iterate(cells(exit.x)(exit.y))(_.pi).takeWhile(_ != null)&lt;br /&gt;   Stream.iterate(cells(exit.x)(exit.y))(_.pi).takeWhile(_ != null).foreach{&lt;br /&gt;     n =&gt; {&lt;br /&gt;       n.trail = Forward&lt;br /&gt;       update&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // the following works fine but replaced with the above to avoid unnecessary var&lt;br /&gt;   /*&lt;br /&gt;   var n = cells(exit.x)(exit.y)&lt;br /&gt;&lt;br /&gt;   while (n != null) {&lt;br /&gt;&lt;br /&gt;     n.trail = Forward&lt;br /&gt;     n = n.pi&lt;br /&gt;     update&lt;br /&gt;   }&lt;br /&gt;   */&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; // get the cell if possible based on current cell and the given direction&lt;br /&gt; def getCell(c : Cell, dir : Direction) : Option[Cell] = dir match {&lt;br /&gt;&lt;br /&gt;   case North  =&gt; if (c.j &gt; 0) Some(cells(c.i)(c.j-1)) else None&lt;br /&gt;   case South  =&gt; if (c.j &lt; east   =""&gt; if (c.i &lt; west   =""&gt; if (c.i &gt; 0) Some(cells(c.i-1)(c.j)) else None&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; // find the inverse direction for a given direction&lt;br /&gt; def getInv(dir : Direction) = dir match {&lt;br /&gt;&lt;br /&gt;   case North =&gt; Direction.South&lt;br /&gt;   case South =&gt; Direction.North&lt;br /&gt;   case East =&gt; Direction.West&lt;br /&gt;   case West =&gt; Direction.East&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// a scala.swing.Panel, override paint(Graphics2D) to paint each of the cells&lt;br /&gt;class MazePanel(m : MazeModel) extends Panel {&lt;br /&gt;&lt;br /&gt; override def paint(g : java.awt.Graphics2D) {&lt;br /&gt;&lt;br /&gt;   m.cells.foreach(_.foreach(_.draw(g)))&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// a javax.swing.JPanel, override paint(Graphics) to paint each of the cells&lt;br /&gt;class MazePanel2(m : MazeModel) extends JPanel {&lt;br /&gt;&lt;br /&gt; override def paint(g : Graphics) {&lt;br /&gt;&lt;br /&gt;   m.cells.foreach(_.foreach(_.draw(g)))&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// a scala.swing.Applet based applet using scala swing wrappers&lt;br /&gt;class MazeApplet extends Applet {&lt;br /&gt; val m = new MazeModel()&lt;br /&gt; lazy val mp = new MazePanel(m)&lt;br /&gt;&lt;br /&gt; object ui extends UI with Reactor {&lt;br /&gt;&lt;br /&gt;   def init() = {&lt;br /&gt;     contents = mp&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   override def start() = {&lt;br /&gt;     def update = {&lt;br /&gt;       this.repaint()&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     m.generateMaze(update)&lt;br /&gt;&lt;br /&gt;     Thread.sleep(2000)&lt;br /&gt;&lt;br /&gt;     m.clearVisited&lt;br /&gt;&lt;br /&gt;     try {&lt;br /&gt;       m.solveMaze(update);&lt;br /&gt;     }&lt;br /&gt;     catch {&lt;br /&gt;       case e : Exception =&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     Thread.sleep(2000)&lt;br /&gt;&lt;br /&gt;     m.clearVisited&lt;br /&gt;&lt;br /&gt;     m.showSolution(update)&lt;br /&gt;&lt;br /&gt;     mp.repaint()&lt;br /&gt;     this.repaint()&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// standard javax.swing.JApplet of the maze&lt;br /&gt;class MazeApplet2 extends JApplet {&lt;br /&gt;&lt;br /&gt; val m = new MazeModel()&lt;br /&gt; lazy val mp = new MazePanel2(m)&lt;br /&gt;&lt;br /&gt; def MazeApplet2 = {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; override def init() {&lt;br /&gt;&lt;br /&gt;   this.add(mp)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; override def start() {&lt;br /&gt;   def update = {&lt;br /&gt;     this.repaint()&lt;br /&gt;   }&lt;br /&gt;  &lt;br /&gt;   m.generateMaze(update)&lt;br /&gt;&lt;br /&gt;   Thread.sleep(2000)&lt;br /&gt;&lt;br /&gt;   m.clearVisited&lt;br /&gt;&lt;br /&gt;   try {&lt;br /&gt;     m.solveMaze(update);&lt;br /&gt;   }&lt;br /&gt;   catch {&lt;br /&gt;     case e : Exception =&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   Thread.sleep(2000)&lt;br /&gt;&lt;br /&gt;   m.clearVisited&lt;br /&gt;&lt;br /&gt;   m.showSolution(update)&lt;br /&gt;&lt;br /&gt;   mp.repaint()&lt;br /&gt;   this.invalidate()&lt;br /&gt;   this.repaint()&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; override def stop() {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; override def destroy() {&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// standard Java app of the maze using JFrame&lt;br /&gt;object Maze {&lt;br /&gt;&lt;br /&gt; def main(args: Array[String]) {&lt;br /&gt;&lt;br /&gt;   val mazeApplet = new MazeApplet()&lt;br /&gt;   val frame = new JFrame()&lt;br /&gt;   frame.setBounds(50, 50, 750, 750)&lt;br /&gt;   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);&lt;br /&gt;&lt;br /&gt;   frame.add(mazeApplet)&lt;br /&gt;&lt;br /&gt;   frame.setVisible(true)&lt;br /&gt;   mazeApplet.init&lt;br /&gt;   mazeApplet.start&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// represent a Cell of the maze&lt;br /&gt;case class Cell(i: Int, j : Int) {&lt;br /&gt;&lt;br /&gt; val size = 7; // each cell is 7px by 7px&lt;br /&gt; var north : Boolean = true&lt;br /&gt; var south : Boolean = true&lt;br /&gt; var east : Boolean = true&lt;br /&gt; var west : Boolean = true&lt;br /&gt; var visited : Boolean = false&lt;br /&gt; var pi : Cell = null  // predecessor cell&lt;br /&gt; var trail : Breadcrumb = Clear;&lt;br /&gt;&lt;br /&gt; def draw(g : Graphics) {&lt;br /&gt;&lt;br /&gt;   val x = i * size&lt;br /&gt;   val y = j * size&lt;br /&gt;&lt;br /&gt;   trail match {&lt;br /&gt;     case Forward =&gt; {&lt;br /&gt;       g.setColor(Color.RED);&lt;br /&gt;       g.fillRect(x + 2, y + 2, size - 4, size - 4)&lt;br /&gt;     }&lt;br /&gt;     case Backward =&gt; {&lt;br /&gt;       g.setColor(Color.BLUE);&lt;br /&gt;       g.fillRect(x + 2, y + 2, size - 4, size - 4)&lt;br /&gt;     }&lt;br /&gt;     case _ =&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   g.setColor(Color.BLACK);&lt;br /&gt;   if (north) {&lt;br /&gt;     g.drawLine(x, y, x + size, y);&lt;br /&gt;   }&lt;br /&gt;   if (south) {&lt;br /&gt;     g.drawLine(x, y + size, x + size, y + size);&lt;br /&gt;   }&lt;br /&gt;   if (east) {&lt;br /&gt;     g.drawLine(x + size, y, x + size, y + size);&lt;br /&gt;   }&lt;br /&gt;   if (west) {&lt;br /&gt;     g.drawLine(x, y, x, y + size);&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def clear(dir : Direction) = dir match {&lt;br /&gt;&lt;br /&gt;   case North =&gt; north = false&lt;br /&gt;   case South =&gt; south = false&lt;br /&gt;   case East =&gt; east = false&lt;br /&gt;   case West =&gt; west = false&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def getDirections() : scala.List[Direction] = {&lt;br /&gt;&lt;br /&gt;   var d = scala.List[Direction]()&lt;br /&gt;&lt;br /&gt;   if (!north) d = North :: d&lt;br /&gt;   if (!south) d = South :: d&lt;br /&gt;   if (!east) d = East :: d&lt;br /&gt;   if (!west) d = West :: d&lt;br /&gt;&lt;br /&gt;   d&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def getRndDirections() : scala.List[Direction] = {&lt;br /&gt;&lt;br /&gt;   val directions = North :: South :: East :: West :: Nil&lt;br /&gt;   implicit val r = Rand.rand&lt;br /&gt;   Utils.shuffle(directions) //, Rand.rand)&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// represent a 2d point&lt;br /&gt;case class Point(x : Int, y : Int)&lt;br /&gt;&lt;br /&gt;// init a random generator singleton&lt;br /&gt;object Rand {&lt;br /&gt; val rand : scala.util.Random = new scala.util.Random();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;object Utils {&lt;br /&gt;&lt;br /&gt; // ref: http://okmij.org/ftp/Haskell/perfect-shuffle.txt&lt;br /&gt; // scala 2.7+ here's an O(n log n) solution:&lt;br /&gt; /*&lt;br /&gt; def shuffle[T](xs: List[T], r: scala.util.Random) = {&lt;br /&gt;   xs.toStream.zip(Stream.const(r.nextDouble _).map(_())).toList.sort(_._2 &lt; nil =""&gt; scala.List(Nil)&lt;br /&gt;   case _ =&gt; xs.flatMap(x =&gt; permute(xs.filter(_ != x)).map(x :: _))&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; // make a stream of x, f(x), f(f(x)), etc.&lt;br /&gt; // in Haskell this is called "iterate".  it ought to be in the standard library&lt;br /&gt; // as Stream.iterate.  "unfold" should be more general, but nonetheless I'm&lt;br /&gt; // going to call this unfold for the moment...&lt;br /&gt; def unfold[T](x:T)(f:T=&gt;T):Stream[T] =&lt;br /&gt;   Stream.cons(x,unfold(f(x))(f))&lt;br /&gt;&lt;br /&gt; def iterate[T](x:T)(f:T=&gt;T):Stream[T] =&lt;br /&gt;   Stream.cons(x,iterate(f(x))(f))&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-1074793110665060072?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/1074793110665060072/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=1074793110665060072' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/1074793110665060072'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/1074793110665060072'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/09/scala-guis-simple-maze-generator-and.html' title='Scala &amp; GUIs, a simple maze generator and solver applet'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-2851172686488509291</id><published>2009-08-31T11:31:00.000-07:00</published><updated>2009-08-31T12:24:27.922-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='Tree'/><category scheme='http://www.blogger.com/atom/ns#' term='dfs'/><category scheme='http://www.blogger.com/atom/ns#' term='pattern matching'/><category scheme='http://www.blogger.com/atom/ns#' term='case class'/><category scheme='http://www.blogger.com/atom/ns#' term='Binary Tree'/><category scheme='http://www.blogger.com/atom/ns#' term='bfs'/><title type='text'>Scala, trees, pattern matching and tree recursion</title><content type='html'>Hi! Long time no see...&lt;br /&gt;&lt;br /&gt;Well after some outage due to Holiday (road trip around Europe and down to the Swiss Alps!), work commitments and some personal things to deal with, I'm back again.&lt;br /&gt;&lt;br /&gt;I thought I'd start with some stuff on Tree structures, whilst continuing on with Scala too. The following code illustrates some good examples of case classes and pattern matching, along with extensive use of Some, None and Option (Scala's improved way of dealing with optional types, rather than relying on null everywhere).&lt;br /&gt;&lt;br /&gt;The following code defines a simple recursive binary tree definition as a case class, using option to define the left and right children.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;case class Tree[+T](value: T, left: Option[Tree[T]], right: Option[Tree[T]])&lt;br /&gt;&lt;/pre&gt;The above definition defines a tree recursively, exactly as a tree is defined as a data structure in computer science. Each tree node has a value of type T and an Optional left and right child node (bin tree). The +T makes the Tree type covarient about T, which is a generally useful property of a Tree.&lt;br /&gt;&lt;br /&gt;A few helper functions are used that make life a little easier when working with Option types, by extracting the value or providing a safe default when no value exists. These help keep the code a little tidy and manageable.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; /**&lt;br /&gt;  * Helper function: For o return f: A =&gt; Int if Some or 0 if None&lt;br /&gt;  *   also could try opt map f getOrElse 0&lt;br /&gt;  */&lt;br /&gt; def zeroIfNone[A](o: Option[A], f: A =&gt; Int): Int = o match {&lt;br /&gt;   case None =&gt; 0&lt;br /&gt;   case Some(x) =&gt; f(x)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Helper function: Return value of function provided if Some, or 0 otherwise&lt;br /&gt;  */&lt;br /&gt; def zeroIfNoneVal[A](o: Option[A], n: =&gt; Int) = zeroIfNone[A](o, _ =&gt; n)&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Helper function: Default to provided value if option is None&lt;br /&gt;  */&lt;br /&gt; def defaultIfNone[A](o: Option[A], f: A =&gt; Int, d : Int): Int = o match {&lt;br /&gt;   case None =&gt; d&lt;br /&gt;   case Some(x) =&gt; f(x)&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The example code demonstrates preorder, inorder and postorder recursive tree traversal (which are all simple permutations of a basic depth first search), applying the provided unit function to each node as it is visited.&lt;br /&gt;&lt;br /&gt;Recall that the preorder, inorder and postorder functions are defined as follows:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;PreOrder - visit parent node, left and then right child node&lt;/li&gt;&lt;li&gt;InOrder - visit left, parent and then right nodes&lt;/li&gt;&lt;li&gt;PostOrder - visit left, right and then parent node&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Using recursion and the call stack, depth first search based tree traversal is very simple and concise. The basic DFS inorder traversal looks like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; /**&lt;br /&gt;  * Perform an inorder tree traversal using the provided Tree[A] =&gt; Unit function&lt;br /&gt;  */&lt;br /&gt; def inOrder[A](t: Option[Tree[A]], f: Tree[A] =&gt; Unit) : Unit = t match {&lt;br /&gt;&lt;br /&gt;   case None =&gt;&lt;br /&gt;   case Some(x) =&gt;&lt;br /&gt;     if (x.left != None) inOrder(x.left, f)&lt;br /&gt;     f(x)&lt;br /&gt;     if (x.right != None) inOrder(x.right, f)&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The breadth first search algorithm is perhaps more interesting. This uses a List as a basic FIFO queue to provide the breadth first search tree traversal:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; /**&lt;br /&gt;  * Breadth first search on a tree, a list is used as a basic fifo queue to&lt;br /&gt;  *   give the bfs traversal&lt;br /&gt;  */&lt;br /&gt; def breadthFirstSearch[A](t: Tree[A], f: Tree[A] =&gt; Unit): Unit = {&lt;br /&gt;   def bfs(ts: List[Tree[A]]): Unit = ts match {&lt;br /&gt;     case Nil =&gt; // ignore&lt;br /&gt;     case _ =&gt;&lt;br /&gt;       val children = for{tree &lt;- ts         &lt;br /&gt;         Some(child) &lt;- List(tree.left, tree.right)}         &lt;br /&gt;         yield child      &lt;br /&gt;     ts map f     &lt;br /&gt;     bfs(children)   &lt;br /&gt;   }     &lt;br /&gt;   bfs(List(t))  &lt;br /&gt; } &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The example also shows a treeFold function. Whether this is a useful function as-is is perhaps debatable, but it makes for an interesting example. The code traverses the tree in a DFS inorder traversal and applies the mapping function f : A -&gt; B and then it applies the join function j : B, B -&gt; B to combine the results of the tree map. In this way the function is similar to say flatMap where a list is mapped and then flattened into a single list, or perhaps more closely to foldLeft/foldRight where items in a list a joined into a single resulting value.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; /**&lt;br /&gt;  * Fold up a tree into a single value, using provided map and join functions&lt;br /&gt;  */&lt;br /&gt; def treeFold[A, B](t: Option[Tree[A]],&lt;br /&gt;                    f: Option[Tree[A]] =&gt; Option[B],&lt;br /&gt;                    j: (Option[B], Option[B]) =&gt; Option[B]) : Option[B] = t match {&lt;br /&gt;&lt;br /&gt;   case None =&gt; None&lt;br /&gt;   case Some(x) =&gt; j(j(f(t), treeFold(x.left, f, j)), treeFold(x.right, f, j))&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Some utility functions are also defined, to return the size and depth of the tree for illustration of how this can be achieved.&lt;br /&gt;&lt;br /&gt;In summary Scala can quite elegantly represent Tree data structures, using case classes and operate over them using pattern matching and higher order functions to provide powerful and concise support for trees and the operations that can be performed on them.&lt;br /&gt;&lt;br /&gt;Some additional things that could be done here would be to provide an example of a binary search and perhaps insertion, update and delete too. A job for another followup blog perhaps...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The full example code (is complete and self contained) is as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package trees&lt;br /&gt;&lt;br /&gt;// Define a recursive Bin Tree structure&lt;br /&gt;case class Tree[+T](value: T, left: Option[Tree[T]], right: Option[Tree[T]])&lt;br /&gt;&lt;br /&gt;object TreeObj {&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Helper function: For o return f: A =&gt; Int if Some or 0 if None&lt;br /&gt;  *   also could try opt map f getOrElse 0&lt;br /&gt;  */&lt;br /&gt; def zeroIfNone[A](o: Option[A], f: A =&gt; Int): Int = o match {&lt;br /&gt;   case None =&gt; 0&lt;br /&gt;   case Some(x) =&gt; f(x)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Helper function: Return value of function provided if Some, or 0 otherwise&lt;br /&gt;  */&lt;br /&gt; def zeroIfNoneVal[A](o: Option[A], n: =&gt; Int) = zeroIfNone[A](o, _ =&gt; n)&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Helper function: Default to provided value if option is None&lt;br /&gt;  */&lt;br /&gt; def defaultIfNone[A](o: Option[A], f: A =&gt; Int, d : Int): Int = o match {&lt;br /&gt;   case None =&gt; d&lt;br /&gt;   case Some(x) =&gt; f(x)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Return the size of the tree&lt;br /&gt;  */&lt;br /&gt; def size[A](t : Option[Tree[A]]) : Int = t match {&lt;br /&gt;&lt;br /&gt;   case None =&gt; 0&lt;br /&gt;   case Some(x) =&gt;&lt;br /&gt;     zeroIfNoneVal(x.left, size(x.left)) + zeroIfNoneVal(x.right, size(x.right)) + 1&lt;br /&gt;     //zeroIfNone(x.left, (_:Tree[Any]) =&gt; (size(x.left))) +&lt;br /&gt;     //zeroIfNone(x.right, (_:Tree[Any]) =&gt; (size(x.right))) + 1&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Alternative size using nested function&lt;br /&gt;  */&lt;br /&gt; def size2[A](t : Option[Tree[A]]) : Int = {&lt;br /&gt;&lt;br /&gt;   def sizeB(b : Option[Tree[A]]) : Int = b match {&lt;br /&gt;     case None =&gt; 0&lt;br /&gt;     case Some(x) =&gt; size(b);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   t match {&lt;br /&gt;     case None =&gt; 0&lt;br /&gt;     case Some(x) =&gt;&lt;br /&gt;       sizeB(x.left) + sizeB(x.right) + 1&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Return the max depth of the tree&lt;br /&gt;  */&lt;br /&gt; def depth[A](t : Option[Tree[A]]) : Int = t match {&lt;br /&gt;&lt;br /&gt;   case None =&gt; 0&lt;br /&gt;   case Some(x) =&gt;&lt;br /&gt;     Math.max(zeroIfNoneVal(x.left, depth(x.left)), zeroIfNoneVal(x.right, depth(x.right))) + 1&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Alternative deptch, return the max depth of the tree using nested function&lt;br /&gt;  */&lt;br /&gt; def depth2[A](t : Option[Tree[A]]) : Int = {&lt;br /&gt;&lt;br /&gt;   def depthB(b : Option[Tree[A]]) : Int = b match {&lt;br /&gt;     case None =&gt; 0&lt;br /&gt;     case Some(x) =&gt; depth(b);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   t match {&lt;br /&gt;&lt;br /&gt;     case None =&gt; 0&lt;br /&gt;     case Some(x) =&gt;&lt;br /&gt;       Math.max(depthB(x.left), depthB(x.right)) + 1&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Breadth first search on a tree, a list is used as a basic fifo queue to&lt;br /&gt;  *   give the bfs traversal&lt;br /&gt;  */&lt;br /&gt; def breadthFirstSearch[A](t: Tree[A], f: Tree[A] =&gt; Unit): Unit = {&lt;br /&gt;   def bfs(ts: List[Tree[A]]): Unit = ts match {&lt;br /&gt;     case Nil =&gt; // ignore&lt;br /&gt;     case _ =&gt;&lt;br /&gt;       val children = for{tree &lt;- ts           Some(child) &lt;- List(tree.left, tree.right)}           yield child       ts map f       bfs(children)     }      bfs(List(t))   }    /**    * Sum up the elements of a numeric tree    */   def sumTree[A &lt;: Int](t: Option[Tree[A]]) : Int = t match {      case None =&gt; 0&lt;br /&gt;   case Some(x) =&gt;&lt;br /&gt;     sumTree(x.left) + sumTree(x.right) + x.value&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Fold up a tree into a single value, using provided map and join functions&lt;br /&gt;  */&lt;br /&gt; def treeFold[A, B](t: Option[Tree[A]],&lt;br /&gt;                    f: Option[Tree[A]] =&gt; Option[B],&lt;br /&gt;                    j: (Option[B], Option[B]) =&gt; Option[B]) : Option[B] = t match {&lt;br /&gt;&lt;br /&gt;   case None =&gt; None&lt;br /&gt;   case Some(x) =&gt; j(j(f(t), treeFold(x.left, f, j)), treeFold(x.right, f, j))&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Perform an inorder tree traversal using the provided Tree[A] =&gt; Unit function&lt;br /&gt;  */&lt;br /&gt; def inOrder[A](t: Option[Tree[A]], f: Tree[A] =&gt; Unit) : Unit = t match {&lt;br /&gt;&lt;br /&gt;   case None =&gt;&lt;br /&gt;   case Some(x) =&gt;&lt;br /&gt;     if (x.left != None) inOrder(x.left, f)&lt;br /&gt;     f(x)&lt;br /&gt;     if (x.right != None) inOrder(x.right, f)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Perform a preorder tree traversal using the provided Tree[A] =&gt; Unit functio&lt;br /&gt;  */&lt;br /&gt; def preOrder[A](t: Option[Tree[A]], f: Tree[A] =&gt; Unit) : Unit = t match {&lt;br /&gt;&lt;br /&gt;   case None =&gt;&lt;br /&gt;   case Some(x) =&gt;&lt;br /&gt;     f(x)&lt;br /&gt;     if (x.left != None) inOrder(x.left, f)&lt;br /&gt;     if (x.right != None) inOrder(x.right, f)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Perform a postorder tree traversal using the provided Tree[A] =&gt; Unit functio&lt;br /&gt;  */&lt;br /&gt; def postOrder[A](t: Option[Tree[A]], f: Tree[A] =&gt; Unit) : Unit = t match {&lt;br /&gt;&lt;br /&gt;   case None =&gt;&lt;br /&gt;   case Some(x) =&gt;&lt;br /&gt;     if (x.left != None) inOrder(x.left, f)&lt;br /&gt;     if (x.right != None) inOrder(x.right, f)&lt;br /&gt;     f(x)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * build tree and run tree functions on it&lt;br /&gt;  */&lt;br /&gt; def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;   /* Test Tree structure&lt;br /&gt;&lt;br /&gt;               1&lt;br /&gt;              / \&lt;br /&gt;             2   3&lt;br /&gt;            / \ / \&lt;br /&gt;           4  x 5  6&lt;br /&gt;         &lt;br /&gt;   */&lt;br /&gt;&lt;br /&gt;   // build a tree&lt;br /&gt;   val myTree = Tree(1,&lt;br /&gt;     Some(Tree(2,&lt;br /&gt;       Some(Tree(4, None, None)),&lt;br /&gt;         None&lt;br /&gt;       )&lt;br /&gt;     ),&lt;br /&gt;     Some(Tree(3,&lt;br /&gt;       Some(Tree(5, None, None)),&lt;br /&gt;         Some(Tree(6, None, None))&lt;br /&gt;       )&lt;br /&gt;     )&lt;br /&gt;   )&lt;br /&gt;&lt;br /&gt;   printBfsTree(myTree)&lt;br /&gt;&lt;br /&gt;   println("Size = " + size(Some(myTree)))&lt;br /&gt;&lt;br /&gt;   println("Depth = " + depth(Some(myTree)))&lt;br /&gt;&lt;br /&gt;   println("Sum = " + sumTree(Some(myTree)))&lt;br /&gt;  &lt;br /&gt;   var sum = treeFold[Int, Int](&lt;br /&gt;               Some(myTree),&lt;br /&gt;               (t: Option[Tree[Int]]) =&gt; t match { case None =&gt; Some(0); case Some(x) =&gt; Some(x.value) },&lt;br /&gt;               (x: Option[Int], y: Option[Int]) =&gt;&lt;br /&gt;                 Some(zeroIfNone[Int](x, (x:Int) =&gt; x) + zeroIfNone[Int](y, y =&gt; y))&lt;br /&gt;             )&lt;br /&gt;&lt;br /&gt;   var mult = treeFold[Int, Int](&lt;br /&gt;               Some(myTree),&lt;br /&gt;               (t: Option[Tree[Int]]) =&gt; t match { case None =&gt; Some(0); case Some(x) =&gt; Some(x.value) },&lt;br /&gt;               (x: Option[Int], y: Option[Int]) =&gt;&lt;br /&gt;                 Some(defaultIfNone[Int](x, (x:Int) =&gt; x, 1) * defaultIfNone[Int](y, y =&gt; y, 1))&lt;br /&gt;              )&lt;br /&gt;&lt;br /&gt;   println("Sum Result = " + sum)&lt;br /&gt;   println("Mult Result = " + mult)&lt;br /&gt;&lt;br /&gt;   println("InOrder = ")&lt;br /&gt;   inOrder(Some(myTree), (t: Tree[Any]) =&gt; println(t.value))&lt;br /&gt;&lt;br /&gt;   println("PreOrder = ")&lt;br /&gt;   preOrder(Some(myTree), (t: Tree[Any]) =&gt; println(t.value))&lt;br /&gt;&lt;br /&gt;   println("PostOrder = ")&lt;br /&gt;   postOrder(Some(myTree), (t: Tree[Any]) =&gt; println(t.value))&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Print a tree using BFS, passing in print unit function&lt;br /&gt;  */&lt;br /&gt; def printBfsTree[A](tree: Tree[A]) {&lt;br /&gt;&lt;br /&gt;   breadthFirstSearch(tree, (t: Tree[A]) =&gt; println(t.value))&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-2851172686488509291?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/2851172686488509291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=2851172686488509291' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2851172686488509291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2851172686488509291'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/08/scala-trees-pattern-matching-and-tree.html' title='Scala, trees, pattern matching and tree recursion'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-7988032601257770675</id><published>2009-07-09T11:01:00.000-07:00</published><updated>2009-10-16T13:45:51.961-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Air'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe LiveCycle'/><category scheme='http://www.blogger.com/atom/ns#' term='LiveCycle'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Notes on Adobe LiveCycle, Flash, Flex and Air</title><content type='html'>Having recently attended &lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;Adobe LiveCycle&lt;/span&gt;&lt;/span&gt; training at Adobe Uxbridge, here are a few notes and links from it.&lt;br /&gt;&lt;br /&gt;Adobe LiveCycle is an integrated Java based SOA and document management server framework. LiveCycle can be hosted on a JEE application server, including JBoss, WebSphere and WebLogic. LiveCycle requires a Database, mySql, Oracle and MS SQL are supported.&lt;br /&gt;&lt;br /&gt;LiveCycle is offers best performance on Microsoft/MS SQLServer platforms - currently.&lt;br /&gt;&lt;br /&gt;LiveCycle is compatible with Windows, Solaris, AIX and Linux&lt;br /&gt;&lt;br /&gt;LiveCycle is designed to integrate with RIA technologies, such as Flash, Flex and Air.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Key LiveCycle features include:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Forms builder - a PDF based form generation engine for PDF/HTML and Flash presentation&lt;/li&gt;&lt;li&gt;Form Guides - based on PDF but with wizard style Flash presentation&lt;/li&gt;&lt;li&gt;Reader/Reader extensions - Acrobat/Reader document management including digital signatures, revocation, permissions etc&lt;/li&gt;&lt;li&gt;Process Management&lt;/li&gt;&lt;li&gt;Data Services - Web Services, support for RESTful webservices in the next version&lt;/li&gt;&lt;li&gt;Output - print/production services&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Flash is the original rich embedded content for multimedia, video, graphics and sound - flash runs as a plugin in the browser (although stand alone players are available too).&lt;/li&gt;&lt;li&gt;Flex builds on Flash and adds a rich component model.&lt;/li&gt;&lt;li&gt;Air is Flex technology that can be run in the browser or as desktop applications transparently.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;LiveCycle and Flex based technologies can use ActionScript, a form of ECMA (JavaScript), Flex itself uses an XML format called mxml to define applications and component layout.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Key Tools:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;FlexBuilder&lt;/span&gt; - IDE for Flex/Air development&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;LiveCycle Workbench&lt;/span&gt; - for LiveCycle development including forms and process management&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Main Development WebSite: &lt;a href="http://www.adobe.com/devnet/"&gt;http://www.adobe.com/devnet/&lt;/a&gt;&lt;br /&gt;Main Download home: &lt;a href="http://www.adobe.com/downloads/"&gt;http://www.adobe.com/downloads/&lt;/a&gt;&lt;br /&gt;Flex Downloads: &lt;a href="http://www.adobe.com/products/flex/flexdownloads/"&gt;http://www.adobe.com/products/flex/flexdownloads/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Flex Development center: &lt;a href="http://www.adobe.com/devnet/flex/?view=home"&gt;http://www.adobe.com/devnet/flex/?view=home&lt;/a&gt;&lt;br /&gt;TourDeFlex: &lt;a href="http://www.adobe.com/devnet/flex/tourdeflex/"&gt;http://www.adobe.com/devnet/flex/tourdeflex/&lt;/a&gt;&lt;br /&gt;TourDeLiveLycle: &lt;a href="http://www.adobe.com/devnet/livecycle/tourdelivecycle/"&gt;http://www.adobe.com/devnet/livecycle/tourdelivecycle/&lt;/a&gt;&lt;br /&gt;LiveCycle Cafe: &lt;a href="http://www.adobe.com/devnet/livecycle/cafe/"&gt;http://www.adobe.com/devnet/livecycle/cafe/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;LiveDocs (online documentation): &lt;a href="http://livedocs.adobe.com/"&gt;http://livedocs.adobe.com/&lt;/a&gt;&lt;br /&gt;ActionScript 3: &lt;a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/"&gt;http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/&lt;/a&gt;&lt;br /&gt;Flex 3 LiveDocs: &lt;a href="http://livedocs.adobe.com/flex/3/"&gt;http://livedocs.adobe.com/flex/3/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Adobe Partners: &lt;a href="https://www.adobe.com/cfusion/partnerportal/index.cfm"&gt;https://www.adobe.com/cfusion/partnerportal/index.cfm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;FlashDevelop: Getting started &lt;a href="http://nuigroup.com/forums/viewthread/1689/"&gt;http://nuigroup.com/forums/viewthread/1689/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-7988032601257770675?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/7988032601257770675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=7988032601257770675' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/7988032601257770675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/7988032601257770675'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/07/notes-on-adobe-livecycle-flash-flex-and.html' title='Notes on Adobe LiveCycle, Flash, Flex and Air'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-4885769043474634487</id><published>2009-07-05T12:35:00.000-07:00</published><updated>2009-07-09T13:03:18.813-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='JSON'/><category scheme='http://www.blogger.com/atom/ns#' term='Google App Engine'/><category scheme='http://www.blogger.com/atom/ns#' term='Scala Servlet'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone JSON client'/><title type='text'>Scala, the Google App Engine and an iPhone client...</title><content type='html'>In this Blog I wanted to explore &lt;span style="font-weight: bold; font-style: italic;"&gt;Scala&lt;/span&gt; on the &lt;span style="font-weight: bold; font-style: italic;"&gt;Google App Engine&lt;/span&gt;. The Google App Engine has supported Java (as well as Python) for a little while now. There have been a few blogs about running Scala on the App engine and I wanted to further demonstrate this by taking a simple Java Servlet and converting it to a Scala based web application suitable for the App Engine.&lt;br /&gt;&lt;br /&gt;The Google App Engine home is here &lt;a href="http://code.google.com/appengine/"&gt;http://code.google.com/appengine/&lt;/a&gt; and contains excellent documentation on how to get stated. I don't want to repeat the documentation, so I'll just point out the essentials relevant to this blog.&lt;br /&gt;&lt;br /&gt;The Getting Started guide can be found here: &lt;a href="http://code.google.com/appengine/docs/java/gettingstarted/"&gt;http://code.google.com/appengine/docs/java/gettingstarted/&lt;/a&gt; for Java, and a Python equivalent is available too.&lt;br /&gt;&lt;br /&gt;This example is based on the previous blog, the Sieve of Eratosthenes as a simple prime number generator. The request accepts one parameter n whose integer value is the upper limit to generate all the primes until (from 2). The response output is &lt;span style="font-weight: bold;"&gt;JSON&lt;/span&gt; encoded to create a simple web service.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Starting with the very basics, the recommended project directory structure is of the form:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;|-src&lt;br /&gt;|---META-INF&lt;br /&gt;|---primes&lt;br /&gt;|-war&lt;br /&gt;|---WEB-INF&lt;br /&gt;|-----classes&lt;br /&gt;|-------META-INF&lt;br /&gt;|-------primes&lt;br /&gt;|-----lib&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;For any Web App for the Google App Engine, one additional GAE specific file is required alongside the standard &lt;span style="font-style: italic; font-weight: bold;"&gt;web.xml &lt;/span&gt;deployment descriptor. This file is called &lt;span style="font-weight: bold; font-style: italic;"&gt;appengine-web.xml&lt;/span&gt; and contains the name of the Application, for example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;appengine-web-app xmlns="http://appengine.google.com/ns/1.0"&amp;gt;&lt;br /&gt;  &amp;lt;application&amp;gt;primes-chillipower-com&amp;lt;/application&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;1&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/appengine-web-app&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this simple GAE deployment descriptor the main thing is that the name of the application is specified, in this example the application was called 'primes-chillipower-com'.&lt;br /&gt;&lt;br /&gt;Applications must be created on the App Engine, this can be done here: &lt;a href="http://appengine.google.com/"&gt;http://appengine.google.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note that there are some limitations currently, you are allowed up to a maximum of 10 applications and applications can not be deleted once created!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The simple Java version:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the simple Java version we can place a simple Servlet in the src directory and build using ant.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example Java servlet:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package primes;&lt;br /&gt;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import javax.servlet.http.*;&lt;br /&gt;&lt;br /&gt;public class PrimesServletJ extends HttpServlet {&lt;br /&gt;public void doGet(HttpServletRequest req, HttpServletResponse resp)&lt;br /&gt;       throws IOException {&lt;br /&gt;    resp.setContentType("text/plain");&lt;br /&gt;&lt;br /&gt;int n = 100;&lt;br /&gt;&lt;br /&gt;String nStr = req.getParameter("n");&lt;br /&gt;&lt;br /&gt;try {&lt;br /&gt;&lt;br /&gt;   n = Integer.parseInt(nStr);&lt;br /&gt;}&lt;br /&gt;catch (Exception e) {}&lt;br /&gt;&lt;br /&gt;int[] primes = primes(n);&lt;br /&gt;&lt;br /&gt;resp.getWriter().println("{ \"n\" : \"" + n + "\",");&lt;br /&gt;resp.getWriter().println("  \"primes\" : [ ");&lt;br /&gt;&lt;br /&gt;for (int i = 0; i &amp;lt; primes.length; i++) {&lt;br /&gt;   String sep = (i &amp;lt; primes.length - 1) ? ", " : "";&lt;br /&gt;       resp.getWriter().println(" { \"" + i + "\" : \"" + primes[i] + "\" }" + sep);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;resp.getWriter().println(" ] }");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static int[] primes(int n) {&lt;br /&gt;&lt;br /&gt;   // initially assume all integers are prime&lt;br /&gt;   boolean[] isPrime = new boolean[n + 1];&lt;br /&gt;&lt;br /&gt;   for (int i = 2; i &amp;lt;= n; i++) {&lt;br /&gt;       isPrime[i] = true;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // mark non-primes &amp;lt;= N using Sieve of Eratosthenes&lt;br /&gt;   for (int i = 2; i*i &amp;lt;= n; i++) {&lt;br /&gt;&lt;br /&gt;       // if i is prime, then mark multiples of i as nonprime&lt;br /&gt;       // suffices to consider mutiples i, i+1, ..., N/i&lt;br /&gt;       if (isPrime[i]) {&lt;br /&gt;           for (int j = i; i * j &amp;lt;= n; j++) {&lt;br /&gt;               isPrime[i * j] = false;&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // count primes&lt;br /&gt;   int primeCount = 0;&lt;br /&gt;   for (int i = 2; i &amp;lt;= n; i++) {&lt;br /&gt;       if (isPrime[i]) primeCount++;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   System.out.println("The number of primes &amp;lt;= " + n + " is " + primeCount);&lt;br /&gt;&lt;br /&gt;   int[] primes = new int[primeCount];&lt;br /&gt;   int idx = 0;&lt;br /&gt;   for (int i = 0; i &amp;lt;= n; i++) {&lt;br /&gt;       if (isPrime[i] == true) {&lt;br /&gt;&lt;br /&gt;           primes[idx] = i;&lt;br /&gt;           idx++;&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return primes;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static void main(String[] args) {&lt;br /&gt;&lt;br /&gt;   int n = 100;&lt;br /&gt;&lt;br /&gt;   if (args.length &amp;gt; 0 &amp;amp;&amp;amp; args[0] != null) {&lt;br /&gt;       n = Integer.parseInt(args[0]);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   int[] primes = primes(n);&lt;br /&gt;&lt;br /&gt;   for (int p : primes) {&lt;br /&gt;       System.out.println("Prime: " + p);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The ant build script goes in the root of the project, to start with I based mine on the example on the Google App Engine documentation here &lt;a href="http://code.google.com/appengine/docs/java/tools/ant.html#Uploading_and_Other_AppCfg_Tasks"&gt;http://code.google.com/appengine/docs/java/tools/ant.html#Uploading_and_Other_AppCfg_Tasks&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Using the standard ant script the project can be compiled and even run locally using the SDK.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ant compile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ant runserver&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you start the dev app server locally, it will be accessibly using a URL of the form:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://localhost:8080/yourappcontextpath"&gt;&lt;span style="font-family:courier new;"&gt;http://localhost:8080/yourappcontextpath&lt;/span&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Where the port 8080 is the default and can be changed in the script.&lt;br /&gt;&lt;br /&gt;The App Engine SDK comes with &lt;span style="font-weight: bold; font-style: italic;"&gt;appcfg.sh&lt;/span&gt; script in the bin directory, which can be used to perform operations such as uploading your app to the App Engine.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;../../../../tools/appengine-java-sdk-1.2.1/bin/appcfg.sh update war&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Scala version:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The main tasks in converting this conventional Java Servlet based web app to a Scala based one is to:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Rewrite the Java Servlet in Scala.&lt;/li&gt;&lt;li&gt;Reconfigure the ant build.xml to modify the classpath to include the Scala libraries and to run the Scala scalac compiler to create the Java .class files from the .scala source files.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Since the Servlet API is a Java based API, there will of course be some reference to Java based classes in the Scala Servlet.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example Scala based Servlet:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package primes&lt;br /&gt;&lt;br /&gt;import javax.servlet.http._&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class PrimesServlet extends HttpServlet {&lt;br /&gt;override def doGet(request: HttpServletRequest, response: HttpServletResponse) = {&lt;br /&gt;&lt;br /&gt;  var n = 100&lt;br /&gt;&lt;br /&gt;  try {&lt;br /&gt;    val nStr = request.getParameter("n"); &lt;br /&gt;    n = Integer.parseInt(nStr);&lt;br /&gt;  } catch {&lt;br /&gt;    case e : Exception =&amp;gt; {&lt;br /&gt;      println("Exception e " + e.getMessage())&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  val ps = primes take n&lt;br /&gt;  val out = response.getWriter()&lt;br /&gt;&lt;br /&gt;  out.println("{ \"n\" : \"" + n + "\", \"primes\" : [")&lt;br /&gt;&lt;br /&gt;  var i = 0&lt;br /&gt;  for (p &amp;lt;- ps) {&lt;br /&gt;    val sep = if (i &amp;lt; ps.length - 1) ", " else ""&lt;br /&gt;    out.println(" { \"" + i + "\" : \"" + p + "\" }" + sep)&lt;br /&gt;    i = i + 1&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  out.println(" ] } ")&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def primes = {&lt;br /&gt; def sieve(is: Stream[Int]): Stream[Int] = {&lt;br /&gt;   val h = is.head&lt;br /&gt;   Stream.cons(h, sieve(is filter (_ % h &amp;gt; 0)))&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; sieve(Stream.from(2))&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example modified and build.xml file:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;project&amp;gt;&lt;br /&gt;&amp;lt;property name="scala.home" location="/Users/chillipower_uk/dev/tools/scala/scala-2.7.5.final/" /&amp;gt;&lt;br /&gt;&amp;lt;property name="sdk.dir" location="/Users/chillipower_uk/dev/tools/appengine-java-sdk-1.2.1/" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;import file="${sdk.dir}/config/user/ant-macros.xml" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;path id="project.classpath"&amp;gt;&lt;br /&gt;&amp;lt;pathelement path="war/WEB-INF/classes" /&amp;gt;&lt;br /&gt;&amp;lt;fileset dir="war/WEB-INF/lib"&amp;gt;&lt;br /&gt; &amp;lt;include name="**/*.jar" /&amp;gt;&lt;br /&gt;&amp;lt;/fileset&amp;gt;&lt;br /&gt;&amp;lt;fileset dir="${sdk.dir}/lib"&amp;gt;&lt;br /&gt; &amp;lt;include name="shared/**/*.jar" /&amp;gt;&lt;br /&gt;&amp;lt;/fileset&amp;gt;&lt;br /&gt;&amp;lt;/path&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- Copy over Scala jars --&amp;gt;&lt;br /&gt;&amp;lt;target name="init"&amp;gt;&lt;br /&gt;&amp;lt;property&lt;br /&gt; name="scala-library.jar"&lt;br /&gt; value="${scala.home}/lib/scala-library.jar"&lt;br /&gt;  /&amp;gt;&lt;br /&gt;&amp;lt;path id="build.classpath"&amp;gt;&lt;br /&gt; &amp;lt;pathelement location="${scala-library.jar}"   /&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;pathelement location="${build.dir}"   /&amp;gt;&lt;br /&gt;&amp;lt;/path&amp;gt;&lt;br /&gt;&amp;lt;taskdef resource="scala/tools/ant/antlib.xml"&amp;gt;&lt;br /&gt; &amp;lt;classpath&amp;gt;&lt;br /&gt;   &amp;lt;pathelement location="${scala.home}/lib/scala-compiler.jar"   /&amp;gt;&lt;br /&gt;   &amp;lt;pathelement location="${scala-library.jar}"   /&amp;gt;&lt;br /&gt; &amp;lt;/classpath&amp;gt;&lt;br /&gt;&amp;lt;/taskdef&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- Copy Scala JARs --&amp;gt;&lt;br /&gt;&amp;lt;target name="copyscala"&lt;br /&gt; description="Copies the Scala JARs to the WAR."&amp;gt;&lt;br /&gt;&amp;lt;copy&lt;br /&gt;   todir="war/WEB-INF/lib"&lt;br /&gt;   flatten="true"&amp;gt;&lt;br /&gt; &amp;lt;fileset dir="${scala.home}/lib"&amp;gt;&lt;br /&gt;   &amp;lt;include name="**/scala-library.jar" /&amp;gt;&lt;br /&gt; &amp;lt;/fileset&amp;gt;&lt;br /&gt;&amp;lt;/copy&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- Copy App engine jars --&amp;gt;&lt;br /&gt;&amp;lt;target name="copyjars"&lt;br /&gt; description="Copies the App Engine JARs to the WAR."&amp;gt;&lt;br /&gt;&amp;lt;copy&lt;br /&gt;   todir="war/WEB-INF/lib"&lt;br /&gt;   flatten="true"&amp;gt;&lt;br /&gt; &amp;lt;fileset dir="${sdk.dir}/lib/user"&amp;gt;&lt;br /&gt;   &amp;lt;include name="**/*.jar" /&amp;gt;&lt;br /&gt; &amp;lt;/fileset&amp;gt;&lt;br /&gt;&amp;lt;/copy&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="compile" depends="copyscala, copyjars, init"&lt;br /&gt; description="Compiles Java source and copies other source files to the WAR."&amp;gt;&lt;br /&gt;&amp;lt;mkdir dir="war/WEB-INF/classes" /&amp;gt;&lt;br /&gt;&amp;lt;copy todir="war/WEB-INF/classes"&amp;gt;&lt;br /&gt; &amp;lt;fileset dir="src"&amp;gt;&lt;br /&gt;   &amp;lt;exclude name="**/*.scala" /&amp;gt;&lt;br /&gt;&amp;lt;exclude name="**/*.java" /&amp;gt;&lt;br /&gt; &amp;lt;/fileset&amp;gt;&lt;br /&gt;&amp;lt;/copy&amp;gt;&lt;br /&gt;&amp;lt;scalac&lt;br /&gt;   srcdir="src"&lt;br /&gt;   destdir="war/WEB-INF/classes"&lt;br /&gt;   classpathref="project.classpath"&lt;br /&gt;    /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--&lt;br /&gt;&amp;lt;copy todir="war/WEB-INF/classes"&amp;gt;&lt;br /&gt;  &amp;lt;fileset dir="src"&amp;gt;&lt;br /&gt;    &amp;lt;exclude name="**/*.scala" /&amp;gt;&lt;br /&gt;    &amp;lt;exclude name="**/*.java" /&amp;gt;&lt;br /&gt;  &amp;lt;/fileset&amp;gt;&lt;br /&gt;&amp;lt;/copy&amp;gt; --&amp;gt;&lt;br /&gt;&amp;lt;javac&lt;br /&gt;   srcdir="src"&lt;br /&gt;   destdir="war/WEB-INF/classes"&lt;br /&gt;   classpathref="project.classpath"&lt;br /&gt;   debug="on" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="datanucleusenhance" depends="compile"&lt;br /&gt; description="Performs JDO enhancement on compiled data classes."&amp;gt;&lt;br /&gt;&amp;lt;enhance_war war="war" /&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="runserver" depends="datanucleusenhance"&lt;br /&gt; description="Starts the development server."&amp;gt;&lt;br /&gt;&amp;lt;dev_appserver war="war" /&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="update" depends="datanucleusenhance"&lt;br /&gt; description="Uploads the application to App Engine."&amp;gt;&lt;br /&gt;&amp;lt;appcfg action="update" war="war" /&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="update_indexes" depends="datanucleusenhance"&lt;br /&gt; description="Uploads just the datastore index configuration to App Engine."&amp;gt;&lt;br /&gt;&amp;lt;appcfg action="update_indexes" war="war" /&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="rollback" depends="datanucleusenhance"&lt;br /&gt; description="Rolls back an interrupted application update."&amp;gt;&lt;br /&gt;&amp;lt;appcfg action="rollback" war="war" /&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="request_logs"&lt;br /&gt; description="Downloads log data from App Engine for the application."&amp;gt;&lt;br /&gt;&amp;lt;appcfg action="request_logs" war="war"&amp;gt;&lt;br /&gt; &amp;lt;options&amp;gt;&lt;br /&gt;   &amp;lt;arg value="--num_days=5"/&amp;gt;&lt;br /&gt; &amp;lt;/options&amp;gt;&lt;br /&gt; &amp;lt;args&amp;gt;&lt;br /&gt;   &amp;lt;arg value="logs.txt"/&amp;gt;&lt;br /&gt; &amp;lt;/args&amp;gt;&lt;br /&gt;&amp;lt;/appcfg&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example request and output:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Request: &lt;a href="http://primes-chillipower-com.appspot.com/primes?n=50"&gt;http://primes-chillipower-com.appspot.com/primes?n=50&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;{ "n" : "50", "primes" : [ { "0" : "2" }, { "1" : "3" }, { "2" : "5" }, { "3" : "7" }, { "4" : "11" }, { "5" : "13" }, { "6" : "17" }, { "7" : "19" }, { "8" : "23" }, { "9" : "29" }, { "10" : "31" }, { "11" : "37" }, { "12" : "41" }, { "13" : "43" }, { "14" : "47" }, { "15" : "53" }, { "16" : "59" }, { "17" : "61" }, { "18" : "67" }, { "19" : "71" }, { "20" : "73" }, { "21" : "79" }, { "22" : "83" }, { "23" : "89" }, { "24" : "97" }, { "25" : "101" }, { "26" : "103" }, { "27" : "107" }, { "28" : "109" }, { "29" : "113" }, { "30" : "127" }, { "31" : "131" }, { "32" : "137" }, { "33" : "139" }, { "34" : "149" }, { "35" : "151" }, { "36" : "157" }, { "37" : "163" }, { "38" : "167" }, { "39" : "173" }, { "40" : "179" }, { "41" : "181" }, { "42" : "191" }, { "43" : "193" }, { "44" : "197" }, { "45" : "199" }, { "46" : "211" }, { "47" : "223" }, { "48" : "227" }, { "49" : "229" } ] }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The iPhone client:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'm currently developing using the iPhone 3.1 beta SDK. I'm not going to post all the source code the the simple client, but rather give some essential snippets relevant to the invocation of the simple JSON web service once deployed on the Google App Engine.&lt;br /&gt;&lt;br /&gt;To Consume this JSON in an iPhone app, we can use the JSON Objective-C library, which is available on Google code here &lt;a href="http://code.google.com/p/json-framework/wiki/FAQ"&gt;http://code.google.com/p/json-framework/wiki/FAQ&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;- (void)loadData {&lt;br /&gt;[super viewDidLoad];&lt;br /&gt;&lt;br /&gt;NSString *urlString = [NSString stringWithFormat:@"http://primes-chillipower-com.appspot.com/primes?n=1000"];&lt;br /&gt;NSURL *url = [NSURL URLWithString:urlString];&lt;br /&gt;&lt;br /&gt;NSDictionary *primesResponse = (NSDictionary *)[JsonClientHelper fetchJSONValueForURL:url];&lt;br /&gt;&lt;br /&gt;if (primesResponse != nil) {&lt;br /&gt;&lt;br /&gt;NSArray *primeEntries = [primesResponse objectForKey:@"primes"];&lt;br /&gt;&lt;br /&gt;NSMutableArray *primesTemp = [[NSMutableArray alloc] init];&lt;br /&gt;[primesTemp retain];&lt;br /&gt;&lt;br /&gt;for (int i = 0; i &amp;lt; [primeEntries count]; i++) {&lt;br /&gt;&lt;br /&gt; NSDictionary *primeEntry = (NSDictionary*)[primeEntries objectAtIndex:i];&lt;br /&gt;&lt;br /&gt; NSString *key = [NSString stringWithFormat:@"%d", i];&lt;br /&gt;&lt;br /&gt; NSString *p = [primeEntry objectForKey:key];&lt;br /&gt;&lt;br /&gt; NSString *msg = [NSString stringWithFormat:@"Prime %d = %@", i, p];&lt;br /&gt;&lt;br /&gt; NSLog(msg);&lt;br /&gt;&lt;br /&gt; [primesTemp addObject:p];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;primes = [primesTemp copy];&lt;br /&gt;&lt;br /&gt;[primesTemp release];&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The above code makes a request to the JSON web service on the App Engine and decodes the response, which once decoded using the JSON library is contained in Dictionaries (NSDictionary) and Arrays (NSArray).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Where JsonClientHelper contains a basic class helper method fetchJSONValueForURL to fetch and decode a JSON response from the supplied URL.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;+ (id)fetchJSONValueForURL:(NSURL *)url&lt;br /&gt;{&lt;br /&gt;NSString *jsonString = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];&lt;br /&gt;&lt;br /&gt;id jsonValue = [jsonString JSONValue];&lt;br /&gt;&lt;br /&gt;[jsonString release];&lt;br /&gt;&lt;br /&gt;return jsonValue;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I hope this Blog has helped give some insight into creating a Scala based Web Application for the Google App Engine, as well as the consumption of JSON in an iPhone Objective-C client.&lt;br /&gt;&lt;br /&gt;(I appologise for the formatting of the code in this blog, finding it awkward to get the code into the blog without it being mangled in some way!).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Resources:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Handy JSON Lint tool: &lt;a href="http://www.jsonlint.com/"&gt;http://www.jsonlint.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Scala Servlet development: &lt;a href="http://blogs.oracle.com/aseembajaj/2008/08/scala_servlet_development.html"&gt;http://blogs.oracle.com/aseembajaj/2008/08/scala_servlet_development.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Scala on the Google App Engine: &lt;a href="http://froth-and-java.blogspot.com/2009/04/scala-on-google-appengine.html"&gt;http://froth-and-java.blogspot.com/2009/04/scala-on-google-appengine.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The Google App Engine provides support for JPA and JDO based persistence - a comparison of the two can be found here: &lt;a href="http://www.jpox.org/docs/persistence_technology.html"&gt;http://www.jpox.org/docs/persistence_technology.html&lt;/a&gt; Further details of the JDO specification can be found here: &lt;a href="http://java.sun.com/jdo/index.jsp"&gt;http://java.sun.com/jdo/index.jsp&lt;/a&gt; and the JDO specification here: &lt;a href="http://java.sun.com/javaee/technologies/persistence.jsp"&gt;http://java.sun.com/javaee/technologies/persistence.jsp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Support for the Google App Engine in Netbeans: &lt;a href="http://kenai.com/projects/nbappengine/pages/Home"&gt;http://kenai.com/projects/nbappengine/pages/Home&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-4885769043474634487?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/4885769043474634487/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=4885769043474634487' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4885769043474634487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4885769043474634487'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/07/scala-google-app-engine-and-iphone.html' title='Scala, the Google App Engine and an iPhone client...'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-3361930394969818999</id><published>2009-07-03T10:52:00.000-07:00</published><updated>2009-10-16T13:34:44.376-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Sieve of Eratosthenes'/><category scheme='http://www.blogger.com/atom/ns#' term='pure lazy'/><category scheme='http://www.blogger.com/atom/ns#' term='lazy'/><title type='text'>Scala, lazy evaluation and the Sieve of Eratosthenes</title><content type='html'>This blog posting is primarily concerned with looking at &lt;span style="font-style: italic; font-weight: bold;"&gt;lazy evaluation&lt;/span&gt; in functional programing, what it means and how it can be put to use.&lt;br /&gt;&lt;br /&gt;Lazy evaluation can be described as an expression that has a value, but that is not evaluated until it's actually needed. Conversely strict refers to the opposite property where all expressions are evaluated up front when declared.&lt;br /&gt;&lt;br /&gt;Some functional languages are described as Pure Lazy (no, this is not a derogatory term!), to reflect the fact that all evaluation is performed on demand. Haskell is on such language. Scala has both aspects of strict evaluation and lazy evaluation, as such it couldn't be referred to as 'pure' in either sense.&lt;br /&gt;&lt;br /&gt;By means of the simplest example I can think of to illustrate Lazy evaluation, consider the following interaction with the Scala CLI:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;scala&amp;gt; lazy val a = b + 1; lazy val b = 1;&lt;br /&gt;a: Int = &amp;lt;lazy&amp;gt;&lt;br /&gt;b: Int = &amp;lt;lazy&amp;gt;&lt;br /&gt;&lt;br /&gt;scala&amp;gt; a&lt;br /&gt;res9: Int = 2&lt;br /&gt;&lt;br /&gt;scala&amp;gt; b&lt;br /&gt;res10: Int = 1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I think this illustrates lazy evaluation, without defining the 'vals' as lazy the statement lazy val a = b + 1; lazy val b = 1;  as val a = b + 1; val b = 1; couldn't be evaluated because b would be undefined when evaluating a!&lt;br /&gt;&lt;br /&gt;The examples are based on the &lt;span style="font-weight: bold;"&gt;Sieve of Eratosthenes&lt;/span&gt;. Eratosthenes was an ancient Greek Mathmetician from 276 BC&lt;sup id="cite_ref-0" class="reference"&gt;&lt;a href="http://en.wikipedia.org/wiki/Eratosthenes#cite_note-0"&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/sup&gt; – c. 195 BC.&lt;span style="text-decoration: underline;"&gt; &lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Eratosthenes#cite_note-1"&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;The Sieve of Eratosthenes is a ancient algorithm for finding prime numbers from 2 .. n. Stated simply, this algorithm can be expressed as:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create a list of all the numbers from 2 .. n.&lt;/li&gt;&lt;li&gt;Starting at p = 2&lt;/li&gt;&lt;li&gt;Strike out all multiples of p up until n from the list&lt;/li&gt;&lt;li&gt;Let p now be the first (lowest) number that has not been struck-off the list&lt;/li&gt;&lt;li&gt;Repeat the last two steps until p^2 &gt; n&lt;/li&gt;&lt;li&gt;All remaining numbers not struck from the list are prime&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In Haskell this can be expressed very elegantly and succinctly, as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;primes = sieve [2..]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;sieve (p : xs) = p : sieve [x | x &lt;− xs, x `mod` p &gt; 0]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Note that [2..] creates an infinite steam of all the integers from 2 to infinity. You might think this is impossible and would create an out of memory error on the machine it ran on, but this is perfectly valid in a pure lazy language because none of the numbers are actually generated until they are requested!&lt;br /&gt;&lt;br /&gt;In Scala there's not really a way to represent this quite so succinctly, but it is possibly to create a Lazy stream of numbers using:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;var is = Stream from 2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;which is essentially equivalent to Haskell's:&lt;br /&gt;&lt;br /&gt;[2..]&lt;br /&gt;&lt;br /&gt;Syntax.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Another important thing to note and be aware of is that Scala's List class is not a lazy list. Therefore, trying to make the equivalent of the Haskell algorithm in Scala using a List is not going to work.&lt;br /&gt;&lt;br /&gt;Scala's Stream class however is Lazy, and so it can form the basic of the equivalent algorithm in Scala. To be specific, Scala's Stream class is strict about head and lazy about tail - which is ok since head contains a finite set of 0|1 elements.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The following Scala code shows two ways to implement the Sieve using Scala Lazy streams.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example 1:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package primes;&lt;br /&gt;&lt;br /&gt;/* Haskell...&lt;br /&gt;&lt;br /&gt;primes = sieve [2..]&lt;br /&gt;sieve (p : xs) = p : sieve [x | x &lt;− xs, x `mod` p &gt; 0]&lt;br /&gt;*/&lt;br /&gt;object Primes1 {&lt;br /&gt;&lt;br /&gt;def primes : Stream[Int] = {&lt;br /&gt;&lt;br /&gt; var is = Stream from 2&lt;br /&gt;&lt;br /&gt; def sieve(numbers: Stream[Int]): Stream[Int] = {&lt;br /&gt;   Stream.cons(&lt;br /&gt;     numbers.head,&lt;br /&gt;     sieve(for (x &lt;- numbers.tail if x % numbers.head &gt; 0) yield x))&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; sieve(is)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def main(args : Array[String]) = {&lt;br /&gt;&lt;br /&gt; primes take 100 foreach println&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;object Primes2 {&lt;br /&gt;def primes = {&lt;br /&gt; def sieve(is: Stream[Int]): Stream[Int] = {&lt;br /&gt;   val h = is.head&lt;br /&gt;   Stream.cons(h, sieve(is filter (_ % h &gt; 0)))&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; sieve(Stream.from(2))&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def main(args: Array[String]) {&lt;br /&gt; println(primes take 100 toList)&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note the use of the 'take' method to extract the first 100 primes from the stream (so the program terminates!).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This second example shows how we can define a Lazy list like trait and then use it to implement the same, equivalent behavior:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example 2:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package primes&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;object PrimesLazyTrait {&lt;br /&gt;&lt;br /&gt;sealed trait Lazy[+A] {&lt;br /&gt; def head: A = this match {&lt;br /&gt;   case Nil =&gt; error("head called on empty")&lt;br /&gt;   case Cons(h, _) =&gt; h()&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def tail: Lazy[A] = this match {&lt;br /&gt;   case Nil =&gt; error("tail on empty")&lt;br /&gt;   case Cons(_, t) =&gt; t()&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def filter(p: A =&gt; Boolean): Lazy[A] = this match {&lt;br /&gt;   case Nil =&gt; Nil&lt;br /&gt;   case Cons(h, t) =&gt; if(p(h())) Cons(h, () =&gt; t() filter p) else t() filter p&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def foreach(f: A =&gt; Unit) {&lt;br /&gt;   this match {&lt;br /&gt;     case Nil =&gt;&lt;br /&gt;     case Cons(h, t) =&gt; {&lt;br /&gt;       f(h())&lt;br /&gt;       t() foreach f&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def toList: List[A] = this match {&lt;br /&gt;   case Nil =&gt; scala.Nil&lt;br /&gt;   case Cons(h, t) =&gt; h() :: t().toList&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;final case class Cons[+A](h: () =&gt; A, t: () =&gt; Lazy[A]) extends Lazy[A]&lt;br /&gt;case object Nil extends Lazy[Nothing]&lt;br /&gt;&lt;br /&gt;def from(n: Int): Lazy[Int] = Cons(() =&gt; n, () =&gt; from(n + 1))&lt;br /&gt;&lt;br /&gt;def primes = {&lt;br /&gt; def sieve(is: =&gt; Lazy[Int]): Lazy[Int] = {&lt;br /&gt;   lazy val h = is.head&lt;br /&gt;   Cons(() =&gt; h, () =&gt; sieve(is filter (_ % h &gt; 0)))&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; sieve(from(2))&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def main(args: Array[String]) {&lt;br /&gt; primes foreach println&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In this version we see the Lazy trait provides the necessary methods head, tail, filter, foreach and toList.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;These little examples help demonstrate some of the power, elegance and conciseness of lazy functional programming - as well as the beauty of this Ancient Greek algorithm for finding primes.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The basic algorithms complexity is:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;O((nlogn)(loglogn)) &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;And has a memory requirement of:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;O(n).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Without any optimization.&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Additional example - e (Euler's number): &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Calculating e, a list of converging numbers in the sequence of e&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;e&lt;/span&gt; can be defined as &lt;span style="font-weight: bold;"&gt;lim n-&gt;inf ( 1 + 1/n)^n &lt;/span&gt;and therefore expressed directly as a function e of n as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;def e(n : Int) = { Math.pow((1.0 + (1.0/n)), n)  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So, how can we turn this into a stream? If we create a stream of numbers from 1 that are mapped using the e function, which can be defined as an anon lambda argument to map:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;val es = Stream.from(1).map((n  =&gt; { Math.pow((1.0 + (1.0/n)), n)  }))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Example usage of the e stream:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;es take 5 toList&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-3361930394969818999?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/3361930394969818999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=3361930394969818999' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/3361930394969818999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/3361930394969818999'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/07/scala-lazy-evaluation-and-sieve-of.html' title='Scala, lazy evaluation and the Sieve of Eratosthenes'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-6359782405805290789</id><published>2009-06-15T14:10:00.000-07:00</published><updated>2009-06-17T14:12:48.729-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='Actors'/><category scheme='http://www.blogger.com/atom/ns#' term='Scala concurrency'/><title type='text'>Scala actors, an introduction with some simple examples</title><content type='html'>The Scala programming language provides an Actor based framework for handling concurrency.&lt;br /&gt;&lt;br /&gt;Scala's Actor model for concurrent programming was originally inspired by the Erlang programming language.&lt;br /&gt;&lt;br /&gt;The actor model is a system of asynchronous message passing for concurrent programming, rather than the typical shared data and locks model. The shared data and locks model has some inherent difficulties that make programming in this way difficult and error prone. Major problems with shared data and locks include the well known dead-lock problem, as well as live locks and the general problem of locking shared mutable data without affecting program scalability and performance. Whilst Scala's actor messaging framework is build around asynchronous messaging, synchronous messaging is provided on top of this for convenience.&lt;br /&gt;&lt;br /&gt;The Scala's actor model is based around an actor library and the Actor trait, along with some simple syntactical constructs for sending and receiving messages.&lt;br /&gt;&lt;br /&gt;The actor library can be included into a project using:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;import scala.actors.Actor._&lt;/pre&gt;&lt;br /&gt;The simplest way to start an actor is to declare an object/class that extends the class Actor and in the body of the actor declare an act() {} method to do the work. The actor x can then be started much like a thread, using x.start(). The act() method is much like the Java Thread's run() method.&lt;br /&gt;&lt;br /&gt;A more succinct method is to declare a variable val x = actor {} and put the action definition directly between the braces (no act method required). What happens here is that actor is a helper method on Actor that creates and starts the actor - so there is no need to call x.start() explicitly when using this approach.&lt;br /&gt;&lt;br /&gt;Actors can receive messages using the receive {} method. The  receive message is passed a partial function to receive the messages. Typically the body of the receive method uses case pattern matching to determine what to do with the message.&lt;br /&gt;&lt;br /&gt;A message can be sent to an actor using the ! operation. For example, an Int can be sent to actor x using: x ! 3&lt;br /&gt;&lt;br /&gt;All actors get their own thread to call the receive function - this causes scalability problems when there are many actors with receive functions. The way to overcome this in Scala is to use the react() {} method instead. React is similar to receive except it doesn't not need a native thread to run and but must call itself when done to receive more messages  - apart from this both are the same in that they both take a partial function.&lt;br /&gt;&lt;br /&gt;Scala provides a convenience to avoid having to call act/react within a react method, this is the loop construct. This ends up looking as simple as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;loop {&lt;br /&gt; react {&lt;br /&gt;   // message handling body goes here&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that react itself does not end end by returning up the call stack in the normal way, all calls to react result in an exception.&lt;br /&gt;&lt;br /&gt;Within a receive or react method, an actor can reply to the sender of the received message by messaging the special identifier "sender", which represents the source of the message.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example 1:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This simple example shows the most basic way to create an actor, by extending Actor, creating an instance and calling start on it.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package scalaactors1&lt;br /&gt;&lt;br /&gt;import scala.actors._&lt;br /&gt;&lt;br /&gt;class Actor1 extends Actor {&lt;br /&gt;&lt;br /&gt; def act {&lt;br /&gt;   var x = 1&lt;br /&gt;   while (true) {&lt;br /&gt;     println("actor1! " + x)&lt;br /&gt;     x = x + 1&lt;br /&gt;     Thread.sleep(500)&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;object TestActors1 {&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * @param args the command line arguments&lt;br /&gt;  */&lt;br /&gt; def main(args: Array[String]) = {&lt;br /&gt;&lt;br /&gt;   println("&amp;gt;&amp;gt;main() - starting")&lt;br /&gt;&lt;br /&gt;   val actor1 = new Actor1()&lt;br /&gt;&lt;br /&gt;   actor1.start()&lt;br /&gt;&lt;br /&gt;   println("&amp;lt;&amp;lt;main() - ending")&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example 2:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This example creates a couple of actors using the val x = actor {} constructs. Each actor will automatically start and run concurrently, outputting a message and sleeping in an infinite loop. If you run this you can observe that the main thread starts and ends, the messages from the two actors are interleaved and run even after the main method has ended.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package scalaactors1&lt;br /&gt;&lt;br /&gt;import scala.actors.Actor._&lt;br /&gt;&lt;br /&gt;object TestActors2 {&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * @param args the command line arguments&lt;br /&gt;  */&lt;br /&gt; def main(args: Array[String]) = {&lt;br /&gt;&lt;br /&gt;   println("&amp;gt;&amp;gt;main() - starting")&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;   val actor1 = actor {&lt;br /&gt;&lt;br /&gt;     var x = 1&lt;br /&gt;     while (true) {&lt;br /&gt;       println("actor1! " + x)&lt;br /&gt;       x = x + 1&lt;br /&gt;       Thread.sleep(500)&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   val actor2 = actor {&lt;br /&gt;&lt;br /&gt;     var x = 1&lt;br /&gt;     while (true) {&lt;br /&gt;       println("actor2! " + x)&lt;br /&gt;       x = x + 1&lt;br /&gt;       Thread.sleep(1000)&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   println("&amp;lt;&amp;lt;main() - ending")&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example 3:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This example is slightly more complex.&lt;br /&gt;&lt;br /&gt;Actor kbReaderActor takes input from the keyboard (as Chars) and passes them one by one to the actor kbProcessorActor which prints out the received character and then uses a 3rd actor called sleep to sleep for the specified amount of time before then waking up the kbProcessorActor (to simulate some "work" that takes a finite amount of time to complete). Note that sleep signals the "sender" using a simple case class to represent the message type (with no arguments).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package scalaactors1&lt;br /&gt;&lt;br /&gt;import scala.actors.Actor._&lt;br /&gt;&lt;br /&gt;case class Wakeup // simple signalling case class&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// simple actor example&lt;br /&gt;object TestActors3 {&lt;br /&gt;&lt;br /&gt; def main(args: Array[String]) = {&lt;br /&gt;&lt;br /&gt;   println("&amp;gt;&amp;gt;Starting")&lt;br /&gt;&lt;br /&gt;   val sleep = actor {&lt;br /&gt;&lt;br /&gt;     loop {&lt;br /&gt;       react {&lt;br /&gt;         case x : int =&amp;gt; {&lt;br /&gt;           println("sleeping for " + x)&lt;br /&gt;          &lt;br /&gt;           java.lang.Thread.sleep(x)&lt;br /&gt;&lt;br /&gt;           println("waking up sender...")&lt;br /&gt;&lt;br /&gt;           sender ! Wakeup&lt;br /&gt;         }&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   val keyProcessorActor = actor {&lt;br /&gt;&lt;br /&gt;     println("&amp;gt;&amp;gt;keyProcessorActor starting")&lt;br /&gt;&lt;br /&gt;     var key : Option[Char] = null&lt;br /&gt;&lt;br /&gt;     loop {&lt;br /&gt;&lt;br /&gt;       react {&lt;br /&gt;         case 'q' =&amp;gt; exit() // 'q' signifies quit app!&lt;br /&gt;         case x : Char =&amp;gt; println("keyProcessorActor received '" + x + "'")&lt;br /&gt;&lt;br /&gt;           sleep ! 1000  // ask the sleep actor to sleep, we will get a Wakeup call when done&lt;br /&gt;&lt;br /&gt;           // now wait for our wakeup&lt;br /&gt;           var r = false&lt;br /&gt;&lt;br /&gt;           do {&lt;br /&gt;             receive {&lt;br /&gt;               case Wakeup =&amp;gt; r = true&lt;br /&gt;             }&lt;br /&gt;           } while (!r)&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     println("&amp;lt;&amp;lt;keyProcessorActor ending")&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   val kbReaderActor = actor {&lt;br /&gt;&lt;br /&gt;     println("&amp;gt;&amp;gt;kbReaderActor starting")&lt;br /&gt;&lt;br /&gt;     var key : Char = ' '&lt;br /&gt;&lt;br /&gt;     do {&lt;br /&gt;&lt;br /&gt;       println("kbReaderActor waiting for input")&lt;br /&gt;       val i = System.in.read()&lt;br /&gt;          &lt;br /&gt;       key = i.asInstanceOf[Char]&lt;br /&gt;&lt;br /&gt;       println("Received input " + key)&lt;br /&gt;&lt;br /&gt;       // message actor1 with the key read from the console&lt;br /&gt;       keyProcessorActor ! key&lt;br /&gt;          &lt;br /&gt;     } while (key != 'q')&lt;br /&gt;&lt;br /&gt;     println("&amp;lt;&amp;lt;kbReaderActor ending")&lt;br /&gt;   }&lt;br /&gt;  &lt;br /&gt;   println("&amp;lt;&amp;lt;Application Ending")&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-6359782405805290789?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/6359782405805290789/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=6359782405805290789' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6359782405805290789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6359782405805290789'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/06/scala-actors-introduction-with-some.html' title='Scala actors, an introduction with some simple examples'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-6665130379425885751</id><published>2009-06-06T08:50:00.000-07:00</published><updated>2009-06-06T09:31:10.350-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Quantum mechanics'/><category scheme='http://www.blogger.com/atom/ns#' term='singlet'/><category scheme='http://www.blogger.com/atom/ns#' term='Quantum entanglement'/><title type='text'>Quantum Entanglement, entanglement with 2 electron singlet</title><content type='html'>(and now for something completely different... Quantum mechanics and quantum entanglement)&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Quantum Entanglement:&lt;/span&gt; Entanglement with 2 element quantum singlet.&lt;br /&gt;&lt;br /&gt;Having recently emailed &lt;span style="font-weight: bold;"&gt;Leonard Susskind&lt;/span&gt; (Stanford CA) with a question regarding entanglement of a 3rd element with a 2 element system in the quantum singlet state (an entangled pair).&lt;br /&gt;&lt;br /&gt;Leonard Susskind is the Felix Bloch professor of theoretical physics at &lt;a href="http://en.wikipedia.org/wiki/Stanford_University" title="Stanford University"&gt;Stanford University&lt;/a&gt; in the field of &lt;a href="http://en.wikipedia.org/wiki/String_theory" title="String theory"&gt;string theory&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Quantum_field_theory" title="Quantum field theory"&gt;quantum field theory&lt;/a&gt;  &lt;a href="http://en.wikipedia.org/wiki/Leonard_Susskind"&gt;http://en.wikipedia.org/wiki/Leonard_Susskind&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Susskind is widely regarded as one of the fathers of String Theory.&lt;br /&gt;&lt;br /&gt;So naturally, I was somewhat surprised when I actually got a detailed response, and the answer is very interesting and informative too! Like most things in Quantum mechanics, the result is not something that could be guest or anticipated, it's not something that could be expected using classical intuition or experience.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Here is the reply:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;div id="doc-contents"&gt;&lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;Let’s begin with the initial state consisting of two electrons in a singlet state  |ud-du&gt; .( I should include a factor of one-over-square-root-of-2 to normalize the state but it’s too hard to type in Word so I will leave it to you.)  Now add another electron in the up state— |u). Also, in order to keep track of photons, lets indicate that there are no photons present with the notation |0}. The initial state is,&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;[&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |ud-du&gt; |u) &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;]&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |0} &lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;Now let’s rearrange the symbols so as to group electrons 2 and 3 together. This is just a notational device. The initial state is&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt; [&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |u&gt; |du) - |d&gt;|uu) &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;] &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;|0}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;Now use the trivial identity&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;|du) = ½   |du-ud) + ½   |du+ud)&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;to rewrite it &lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;=½  &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;[&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |u&gt; |du-ud) &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;]&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |0} + ½  &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;[&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |u&gt; |du+ud) &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;]&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |0}&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;      -&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;[&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |d&gt;|uu) &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;] &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;|0}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;Now think of electron 2 and 3 as close one another, while electron 1 is off in the distance. In the first term 2-3 are in a singlet state. Nothing happens to it. In the other two terms the 2-3 system is orthogonal to the singlet. The 2-3 system  will interact to emit a photon, and decay to the singlet in those cases, although the photons will be in different states in the two terms. Denoting the presence of the photon by |γ} and |γ’}, the final state will be&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;=½ &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;[&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |u&gt; |du-ud) &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;]&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |0} + ½ &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;[&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |u&gt; |du-ud) &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;]&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |γ}&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;      -&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;[&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |d&gt;|du-ud)&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;] &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;|γ’}  (note, there is missing sqrt2)&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="color: rgb(51, 0, 153);"&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;So what do we have in the end? A superposition of states in which the 2-3 system is in the singlet and&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;ol style="color: rgb(51, 0, 153);" type="a"&gt;&lt;li&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;electron 1 is up with no photon&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="color: rgb(51, 0, 153);"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;ol style="color: rgb(51, 0, 153);" start="2" type="a"&gt;&lt;li&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; electron 1 is up with a  photon in state |γ}&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="color: rgb(51, 0, 153);"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;ol style="color: rgb(51, 0, 153);" start="3" type="a"&gt;&lt;li&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;electron 1 is down with a photon in state  &lt;/span&gt; &lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;|γ’}. &lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="color: rgb(51, 0, 153);"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 0, 153);font-family:Times New Roman;font-size:100%;"  &gt;If there is no photon or a photon in state |γ}   then we know that electron 1 is up. If there is a photon in state |γ’} then e-1 must be down.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;Having such a brilliantly and concise response was fantastic!&lt;br /&gt;&lt;br /&gt;I've gone on to calculate the trivial equations to determine the probability in each state, as follows:&lt;br /&gt;&lt;br /&gt;Given the probabilities of the 3 possibilities must add up to 1, taking the coefficients as lambda, the probability is given by lambda.lambda* which for real numbers is just lambda^2, so:&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;=½  &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;[&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |u&gt; |du-ud) &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;]&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |0} + ½  &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;[&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |u&gt; |du-ud) &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;]&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt; |γ}&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;       -&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;[&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;  |d&gt;|du-ud)&lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:6;"  &gt;] &lt;/span&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;|γ’}  (note, there is missing  sqrt2)&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;a.&lt;/span&gt; electron 1 is up    with no photon&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;|      1      | 2&lt;br /&gt;| ------------|      = 1/4 = p1 = &lt;span style="font-weight: bold;"&gt;0.25&lt;/span&gt;&lt;br /&gt;|  2 sqrt(2)  |&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;  &lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;b.&lt;/span&gt; elect&lt;/span&gt;ron 1 is up with a  photon in state |γ}&lt;br /&gt;&lt;br /&gt;    p2 = &lt;span style="font-weight: bold;"&gt;0.25&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="font-weight: bold;"&gt;c.&lt;/span&gt; electron 1 is down with a photon in state  |γ’}.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;|      1      | 2&lt;br /&gt;| ------------|      = 1/2 = p3 = &lt;span style="font-weight: bold;"&gt;0.5&lt;/span&gt;&lt;br /&gt;|  sqrt(2)    |&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-weight: bold;"&gt;Google document:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a id="publishedDocumentUrl" class="tabcontent" target="_blank" href="http://docs.google.com/View?id=df4zskcg_25d8xtc9hp"&gt;http://docs.google.com/View?id=df4zskcg_25d8xtc9hp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The Stanford course "Modern Theoretical Physics - Fall 2006" by Leonard Susskind is available on iTunes-U (highly recommended!).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-6665130379425885751?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/6665130379425885751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=6665130379425885751' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6665130379425885751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6665130379425885751'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/06/quantum-entanglement-entenglement-with.html' title='Quantum Entanglement, entanglement with 2 electron singlet'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-2642358946892620331</id><published>2009-06-06T08:02:00.000-07:00</published><updated>2009-06-06T08:12:35.583-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mercurial hg'/><category scheme='http://www.blogger.com/atom/ns#' term='mercurial'/><category scheme='http://www.blogger.com/atom/ns#' term='hg'/><title type='text'>Basic Crib sheet for Mercurial hg</title><content type='html'>Mercurial (hg) is a distributed version control system, with many similarities to Subversion (svn). Being distributed, means people can work offline and still keep their version history local, merging changes with each other by exporting and importing the repository changes periodically.&lt;br /&gt;&lt;br /&gt;Generally speaking mercurial is very simple and easy to use, but here are a few commands for quick reference:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Basic crib for Mecurial HG&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Clone a repository from a web URL:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg clone http://www.selenic.com/repo/hello my-hello&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Clone from another local repository:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg clone existing-repos clone-repos&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Make a new repository:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg init&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Add files:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg add&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Committing changes:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg commit (hg ci)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Pull changes from one repository to another:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg pull &lt;repository&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Note: this doesn't update the working directory, to do this update the working directory:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg update (hg up)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Exporting and import:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg export -o filename tip&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg import -o filename &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Other common commands:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg log&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg status (hg st)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg diff&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg revert&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;hg (-q) tip&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;HG Editor&lt;/span&gt;, the editor for HG comments is determined in the following order:&lt;br /&gt;&lt;br /&gt;HGEDITOR environment variable&lt;br /&gt;&lt;br /&gt;editor configuration option in [ui] section (in hgrc or passed with --config ui.editor command-line option).&lt;br /&gt;&lt;br /&gt;VISUAL environment variable&lt;br /&gt;&lt;br /&gt;EDITOR environment variable&lt;br /&gt;&lt;br /&gt;vi, if none of the above is set&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;References:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Mercurial home:&lt;br /&gt;&lt;a href="http://www.selenic.com/mercurial/wiki/Mercurial"&gt;&lt;br /&gt;http://www.selenic.com/mercurial/wiki/Mercurial&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Mecurial tutorial:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.selenic.com/mercurial/wiki/Tutorial"&gt;http://www.selenic.com/mercurial/wiki/Tutorial&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Quick reference and cheat sheets:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.selenic.com/mercurial/wiki/QuickReferenceCardsAndCheatSheets"&gt;http://www.selenic.com/mercurial/wiki/QuickReferenceCardsAndCheatSheets&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-2642358946892620331?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/2642358946892620331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=2642358946892620331' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2642358946892620331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2642358946892620331'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/06/basic-crib-sheet-for-mercurial-hg.html' title='Basic Crib sheet for Mercurial hg'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-8561612171528015572</id><published>2009-06-04T11:51:00.000-07:00</published><updated>2009-06-04T14:11:01.010-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GlassFish AS'/><category scheme='http://www.blogger.com/atom/ns#' term='b60e'/><category scheme='http://www.blogger.com/atom/ns#' term='Glassfish'/><category scheme='http://www.blogger.com/atom/ns#' term='GlassFish 2.1'/><title type='text'>GlassFish v2.1 b60e crib sheet / installation notes</title><content type='html'>&lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Recently, having been working on a project that's migrated from JBoss 4.2.2 to GlassFish v2.1, I needed to hand over a crib sheet / quick guide to people supporting the live system, so as it might be useful in general. Only really covering the basics, but here it is anyway:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-weight: bold;" lang="EN-GB"&gt;GlassFish AS Basic Crib / notes:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Prerequisites:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;ul style="margin-top: 0cm;" type="disc"&gt;&lt;li&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Java JDK      6.x latest&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;GlassFish AS version V2.1 b60e Final Release&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Download jar here &lt;a href="http://java.net/download/javaee5/v2.1_branch/promoted/Linux/glassfish-installer-v2.1-b60e-linux.jar" target="_blank"&gt;http://java.net/download/&lt;wbr&gt;javaee5/v2.1_branch/promoted/&lt;wbr&gt;Linux/glassfish-installer-v2.&lt;wbr&gt;1-b60e-linux.jar&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;        &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;For RHEL derived CentOS, recommended installation would be something like &lt;span style="font-family: courier new;"&gt;/usr/local/projectname/&lt;/span&gt;&lt;wbr style="font-family: courier new;"&gt;&lt;span style="font-family: courier new;"&gt;glassfish&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-weight: bold;" lang="EN-GB"&gt;Installation:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Courier New;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; font-family: &amp;quot;Courier New&amp;quot;;" lang="EN-GB"&gt;java -Xmx256m -jar glassfish-installer-v2.1-b60e-&lt;wbr&gt;linux.jar&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Courier New;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-family: &amp;quot;Courier New&amp;quot;;" lang="EN-GB"&gt;cd glassfish&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Courier New;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-family: &amp;quot;Courier New&amp;quot;;" lang="EN-GB"&gt;chmod -R +x lib/ant/bin&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;      &lt;p&gt;&lt;span style="font-family:Courier New;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-family: &amp;quot;Courier New&amp;quot;;" lang="EN-GB"&gt;lib/ant/bin/ant -f setup.xml&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Follow the installer instructions, accepting EULA and any defaults presented...&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;This will unpack and install the server, creating a default domain called "domain1"&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;      &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;A domain is an administrative "unit" - possibly related to, but not the same as an actual domain.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;All domains live in: &lt;span style="font-family: courier new;"&gt;{glassfish_home}/domains/&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;      &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;We need just one for now, so all our stuff will be in:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="font-family: courier new;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;{glassfish_home}/domains/&lt;wbr&gt;domain1/&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;the installation process will create a default empty domain, domain1 with a default config file, the main configuration file is called &lt;b&gt;&lt;span style="font-weight: bold;"&gt;domain.xml&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;      &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;e.g. &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;" lang="EN-GB"&gt;{glassfish_home}/domains/&lt;wbr&gt;domain1/config.xml&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-GB"&gt;&lt;/span&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;This file may contain some host /installation specific information, as well as stuff specific to our application.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-weight: bold;" lang="EN-GB"&gt;Starting and stopping GlassFish AS:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family:Courier New;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-family: &amp;quot;Courier New&amp;quot;;" lang="EN-GB"&gt;{glassfish_home}/bin/asadmin start-domain domain1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family:Courier New;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-family: &amp;quot;Courier New&amp;quot;;" lang="EN-GB"&gt;{glassfish_home}/bin/asadmin stop-domain domain1&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;If all is good you will see confirmation on the command prompt when started, such as:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;i&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-style: italic;" lang="EN-GB"&gt;Domain domain1 started&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-weight: bold;" lang="EN-GB"&gt;Managing GlassFish AS:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;By default, the web based management console is available on port :4848&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;The default admin account is username = admin, password = adminadmin&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;URL is: http://{hostname}:4848&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-weight: bold;" lang="EN-GB"&gt;Web-app deployment options:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;There are a few options, the main two are:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Manually, using autodeploy directory&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Simply copy .war file to: &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;" lang="EN-GB"&gt;{glassfish_home}/domains/&lt;wbr&gt;domain1/autodeploy&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-GB"&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Deploying via the admin console:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;On main menu on left, click on and expand the Web Applications menu entry&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Click on the Deploy button, typically when deploying from a local file, use the "Packaged file to be uploaded to the server" browse button to locate the local war file. Browse for the war file, select it and click Ok&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;When completed, the web app will appear in the application list (if all is well)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;The other settings can be left as defaults. Optionally we can chose to pre-compile JSPs here etc.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-weight: bold;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-weight: bold;" lang="EN-GB"&gt;Server Logs:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;The main server logs appear in the domain under logs, i.e.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family:Courier New;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-family: &amp;quot;Courier New&amp;quot;;" lang="EN-GB"&gt;{glassfish_home}/domains/&lt;wbr&gt;domain1/logs/server.log&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Logs can also be viewed (and configured, including log rotation) via the admin console, under the Application Server menu entry&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-weight: bold;" lang="EN-GB"&gt;Monitoring and management:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;JConsole:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;GlassFish is a JMX compliant app server (listening by default to port 8686)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Using jconsole, remote connect to: &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;" lang="EN-GB"&gt;http://{hostname}:8686&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-GB"&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Using the same default account: &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;;" lang="EN-GB"&gt;admin/adminadmin&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-GB"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;      &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-weight: bold;" lang="EN-GB"&gt;Admin console:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;Under the Application Server in the main menu - there are entries for server Monitoring.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;      &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;This includes a built in chart and call flow logging - which is potentially very useful for diagnostics and monitoring…&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt; font-weight: bold;" lang="EN-GB"&gt;HTTPS / SSL:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;GlassFish AS will do HTTPS out of the box (using a default Sun Microsystems certificate).&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;HTTPS is served by default on port &lt;b&gt;&lt;span style="font-weight: bold;"&gt;:8181&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;b&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;b&gt;&lt;span style="font-weight: bold;"&gt;Hopefully in the near future I'll but together something to cover clustering and load balancing too.&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Times New Roman;font-size:100%;"&gt;&lt;span style="font-size: 12pt;" lang="EN-GB"&gt;.&lt;b&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-8561612171528015572?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/8561612171528015572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=8561612171528015572' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8561612171528015572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8561612171528015572'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/06/glassfish-v21-b60e-crib-sheet.html' title='GlassFish v2.1 b60e crib sheet / installation notes'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-2457206946518252134</id><published>2009-06-03T11:20:00.000-07:00</published><updated>2009-06-03T11:30:37.138-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='signed'/><category scheme='http://www.blogger.com/atom/ns#' term='certs'/><category scheme='http://www.blogger.com/atom/ns#' term='X509'/><category scheme='http://www.blogger.com/atom/ns#' term='selfsigned'/><category scheme='http://www.blogger.com/atom/ns#' term='crt'/><category scheme='http://www.blogger.com/atom/ns#' term='Certificates'/><title type='text'>Super quick guide for creating self-signed certificates</title><content type='html'>Something I've done many times, but every time it's typically been so long in between that I've usually forgotten the specific details, so here is a super quick crib:&lt;br /&gt;&lt;br /&gt;Create the private keys:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;openssl genrsa -des3 -out server1.key 1024&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Create a Certificate Signing Request (CSR):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;openssl req -new -key server1.key -out server1.csr&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Enter details, example below:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Country Name (2 letter code) [AU]:GB&lt;br /&gt;State or Province Name (full name) [Some-State]:Kent&lt;br /&gt;Locality Name (eg, city) []:Royal Tunbridge Wells&lt;br /&gt;Organization Name (eg, company) [Internet Widgits Pty Ltd]:Acme Co&lt;br /&gt;Organizational Unit Name (eg, section) []:Financial Systems&lt;br /&gt;Common Name (eg, YOUR name) []:www.myexactdomainname.com&lt;br /&gt;Email Address []:louis.botterill@netbuilder.com&lt;br /&gt;&lt;br /&gt;Please enter the following 'extra' attributes&lt;br /&gt;to be sent with your certificate request&lt;br /&gt;A challenge password []:&lt;br /&gt;An optional company name []:&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Copy the passphrase protected key:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;cp server1.key server1.key.org&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Export the actual key without pass-phrase protection:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;openssl rsa -in server1.key.org -out server1.key&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Sign the CSR using the key to create a Certificate (.crt):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;openssl x509 -req -days 365 -in server1.csr -signkey server1.key -out server1.crt&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Easy huh! :)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-2457206946518252134?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/2457206946518252134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=2457206946518252134' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2457206946518252134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2457206946518252134'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/06/super-quick-guide-for-creating-self.html' title='Super quick guide for creating self-signed certificates'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-6179693976790822197</id><published>2009-05-21T13:36:00.000-07:00</published><updated>2009-05-21T14:59:07.781-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='POX'/><category scheme='http://www.blogger.com/atom/ns#' term='Compression'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET 3.5'/><category scheme='http://www.blogger.com/atom/ns#' term='GZIP'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>How to add GZIP compression to a .NET WCF REST POX client</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Bandwidth is important!&lt;/span&gt; Even these days where everyone has broadband, now we want the same performance on the move, over wireless and 3G networks. Even when clients individually have enough bandwidth, put 100 or 1000 users together in a corporate environment and it's the IT department that may start have the headache instead. Then there's the server side, ultimately all this traffic comes together down a finite number of "pipes" to our servers, so really we still have to consider bandwidth usage at all levels.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;We needed to add GZip compression support to a .NET 3.5sp1 client application using WCF for REST POX web services.&lt;/span&gt; The responses were sent compressed using GZIP, so the client needed to be able to decompress these, before passing up the stack to the Data Serialisers and application code layers.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The server in this instance is a Java EE web application returning XML, GZipped using a filter servlet.&lt;/span&gt; Implementing the server side filter is fairly trivial, however it's companion in .NET on the client side is not.&lt;br /&gt;&lt;br /&gt;Since this gave me a little bit of a challenge recently (very little documentation around or good examples) I thought I'd put up a quick blog about it. It's not that there's a lot of code involved, it's understanding the WCF with sufficient clarity to be able to extend it, and debug it when it's not quite right.&lt;br /&gt;&lt;br /&gt;One of the issues that crops up straight away is that most examples of extending the WCF for compression are based around the WS.* web service support, the original incarnation of WCF.&lt;br /&gt;&lt;br /&gt;However, later versions of the WCF added support for REST/POX web services, and this is where I wanted to add the GZIP compression support. &lt;span style="font-weight: bold;"&gt;You can not mix WS.* and Rest (aka Web in WCF) web services in the WCF, without creating a runtime error as the WCF channel is instantiated.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So, enough of the preamble already, lets cut to the chase, what's needed?&lt;br /&gt;&lt;br /&gt;Well, assuming you have a WebHttpBinding to start with...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WebHttpBinding webHttpBinding = new WebHttpBinding();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Then, in order to add the GZIP compression support, we need to pull apart the binding, into its constituent elements and then reassemble it, adding in the new binding element.&lt;br /&gt;&lt;br /&gt;I enlisted the help of a content mapper to force the content to XML:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class XMLMapper : WebContentTypeMapper&lt;br /&gt;{&lt;br /&gt;  public override WebContentFormat GetMessageFormatForContentType(string contentType)&lt;br /&gt;  {&lt;br /&gt;      return WebContentFormat.Xml; // always&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;First, get the binding elements out of the WebHttpBinding, using the CreateBindingElements() function.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;BindingElementCollection bec = webHttpBinding.CreateBindingElements();&lt;br /&gt;&lt;br /&gt;WebMessageEncodingBindingElement wmbe = bec.Remove&lt;webmessageencodingbindingelement&gt;();&lt;br /&gt;HttpTransportBindingElement htbe = bec.Remove&lt;httptransportbindingelement&gt;();&lt;br /&gt;&lt;br /&gt;wmbe.ContentTypeMapper = new XMLMapper();&lt;br /&gt;&lt;br /&gt;GZipMessageEncodingBindingElement compBindingElement = new GZipMessageEncodingBindingElement(wmbe);&lt;br /&gt;&lt;br /&gt;bec.Add(compBindingElement);&lt;br /&gt;bec.Add(htbe);&lt;br /&gt;&lt;br /&gt;CustomBinding cb = new CustomBinding(bec);&lt;br /&gt;&lt;br /&gt;binding = cb;&lt;br /&gt;&lt;br /&gt;HttpRequestMessageProperty httpRequestMessageProperty = new HttpRequestMessageProperty();&lt;br /&gt;&lt;br /&gt;httpRequestMessageProperty.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip");&lt;br /&gt;httpRequestMessageProperty.Headers.Add(HttpRequestHeader.ContentEncoding, "gzip");&lt;br /&gt;&lt;/httptransportbindingelement&gt;&lt;/webmessageencodingbindingelement&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Ok, so now binding is a rebuilt binding, based on WebHttpBinding where a GZIP encoder has been used to wrap the &lt;span style="font-family:courier new;"&gt;WebMessageEncodingBindingElement&lt;/span&gt; from the original binding's binding elements.&lt;br /&gt;&lt;br /&gt;Note that the &lt;span style="font-family:courier new;"&gt;HttpTransportBindingElement&lt;/span&gt; must be the last binding element in the binding element collection (protocol stack) or a runtime error will be thrown when trying to instantiate the channel.&lt;br /&gt;&lt;br /&gt;Now we can create the channel in the normal way:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// create a channel factory&lt;br /&gt;ChannelFactory&lt;iservice&gt; cf = new ChannelFactory&lt;iservice&gt;(binding, hostPath);&lt;br /&gt;              &lt;br /&gt;// create webhttpbehavior for rest / pox get/invoke behaviour support&lt;br /&gt;WebHttpBehavior webHttpBehavior = new WebHttpBehavior();&lt;br /&gt;webHttpBehavior.DefaultOutgoingRequestFormat = WebMessageFormat.Xml;&lt;br /&gt;webHttpBehavior.DefaultOutgoingResponseFormat = WebMessageFormat.Xml;&lt;br /&gt;              &lt;br /&gt;// add webhttpbehahvior to channelfactory endpoint&lt;br /&gt;cf.Endpoint.Behaviors.Add(webHttpBehavior);&lt;br /&gt;&lt;br /&gt;if (ENABLE_COMPRESSION)&lt;br /&gt;{&lt;br /&gt;   // add our custom behavior...&lt;br /&gt;   cf.Endpoint.Behaviors.Add(new HttpEndpointBehavior());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// create our IService channel&lt;br /&gt;channel = cf.CreateChannel();&lt;br /&gt;&lt;/iservice&gt;&lt;/iservice&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So far so good, but what about this &lt;span style="font-family:courier new;"&gt;GZipMessageEncodingBindingElement&lt;/span&gt;?&lt;br /&gt;&lt;br /&gt;Well, this can be found in the Microsoft WCF samples:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms751458.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms751458.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Detailed steps of integrating the MS WCF GZip example into your code:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.vistax64.com/indigo/113763-wcf-client-j2ee-server-using-gzip.html"&gt;http://www.vistax64.com/indigo/113763-wcf-client-j2ee-server-using-gzip.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note: I had to make some minor modifications to make my client work correctly, details can be provided if anyone leaves a comment expressing an interest.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Further Resources:&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span  lang="EN-GB" style="font-family:Arial;"&gt;&lt;br /&gt;Various threads discussing similar problems:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;  &lt;p&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span  lang="EN-GB" style="font-family:Arial;"&gt;&lt;a href="http://social.msdn.microsoft.com/forums/en-US/wcf/thread/5c67b0da-9e50-4ee1-b7ac-a4733c580980/" target="_blank"&gt;http://social.msdn.microsoft.&lt;wbr&gt;com/forums/en-US/&lt;span class="il"&gt;wcf&lt;/span&gt;/thread/&lt;wbr&gt;5c67b0da-9e50-4ee1-b7ac-&lt;wbr&gt;a4733c580980/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span  lang="EN-GB" style="font-family:Arial;"&gt;&lt;a href="http://social.msdn.microsoft.com/forums/en-US/wcf/thread/ddfe06b1-f07c-4da2-a1f1-d06126e4f96e/" target="_blank"&gt;http://social.msdn.microsoft.&lt;wbr&gt;com/forums/en-US/&lt;span class="il"&gt;wcf&lt;/span&gt;/thread/&lt;wbr&gt;ddfe06b1-f07c-4da2-a1f1-&lt;wbr&gt;d06126e4f96e/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span  lang="EN-GB" style="font-family:Arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span  lang="EN-GB" style="font-family:Arial;"&gt;&lt;a href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24644" target="_blank"&gt;http://aspnet.codeplex.com/&lt;wbr&gt;Release/ProjectReleases.aspx?&lt;wbr&gt;ReleaseId=24644&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;p&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span  lang="EN-GB" style="font-family:Arial;"&gt;Neomax - provide software products to extend the WCF framework, including support for compression:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;   &lt;p&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span  lang="EN-GB" style="font-family:Arial;"&gt;&lt;a href="http://www.noemax.com/products/wcfx/features.html#gzip_compression" target="_blank"&gt;http://www.noemax.com/&lt;wbr&gt;products/wcfx/features.html#&lt;wbr&gt;gzip_compression&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span  lang="EN-GB" style="font-family:Arial;"&gt;&lt;a href="http://www.noemax.com/products/wcfx/features.html#gzip_compression" target="_blank"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;   &lt;h2  style="font-weight: normal;font-family:arial;"&gt;&lt;span style="font-size:100%;"&gt;Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1: BETA&lt;/span&gt;&lt;/h2&gt;      &lt;p&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span  lang="EN-GB" style="font-family:Arial;"&gt;&lt;a href="http://www.microsoft.com/downloads/thankyou.aspx?familyId=a91dc12a-fc94-4027-b67e-46bab7c5226c&amp;amp;displayLang=en" target="_blank"&gt;http://www.microsoft.com/&lt;wbr&gt;downloads/thankyou.aspx?&lt;wbr&gt;familyId=a91dc12a-fc94-4027-&lt;wbr&gt;b67e-46bab7c5226c&amp;amp;displayLang=&lt;wbr&gt;en&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=";font-family:Arial;font-size:100%;"  &gt;&lt;span  lang="EN-GB" style="font-family:Arial;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-6179693976790822197?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/6179693976790822197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=6179693976790822197' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6179693976790822197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6179693976790822197'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/05/how-to-add-gzip-compression-to-wcf-rest.html' title='How to add GZIP compression to a .NET WCF REST POX client'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-6253346418958086589</id><published>2009-05-16T15:03:00.000-07:00</published><updated>2009-05-31T14:00:45.228-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SJSWS'/><category scheme='http://www.blogger.com/atom/ns#' term='Load balancer loadbalancer'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenSolaris'/><category scheme='http://www.blogger.com/atom/ns#' term='Glassfish'/><title type='text'>Quick notes on OpenSolaris 111a &amp; GlassFish clustering</title><content type='html'>Some quick notes on upgrading 111 to 111a and preparing for GlassFish v2.1 clustering and load balancing tests:&lt;br /&gt;&lt;br /&gt;(Note: This is really a scratch-pad of notes and resources for my own benefit, rather than a structured Blog for others to follow, however some of the resources might be useful for someone, somewhere)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;OpenSolaris upgrade problems:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Graphical login failed to start&lt;br /&gt;&lt;br /&gt;Simply restarting gdm fixed this problem!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;svcadm disable gdm&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;svcadm enable gdm&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Installing GlassFish v2.1 - problems:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Running java -Xmx256m -jar glassfish_xxx.jar reported "Not Enough Space Available"&lt;br /&gt;&lt;br /&gt;zfs list showed 8gig space available&lt;br /&gt;&lt;br /&gt;check for large files in swap directories:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;pfexec du -k /tmp|sort -n&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;pfexec du -k /etc/svc/volatile|sort -n&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Increasing swap space, adding a second swap file:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;zfs create -V2G rpool/swap2 ; swap -a /dev/zvol/dsk/rpool/swap2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;GlassFish clustering:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Steps for setting up GlassFish clustering:&lt;br /&gt;&lt;br /&gt;Setup default clustering profile;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lib/ant/bin/ant -f setup-cluster.xml&lt;/span&gt;  &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Start the DAS;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;bin/asadmin start-domain --user admin&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;/span&gt;  &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Create the node agent;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;bin/asadmin create-node-agent&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Start the node agent;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;bin/asadmin start-node-agent&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Create cluster and instances (for node agent) in GlassFish admin console.&lt;br /&gt;&lt;br /&gt;Download Load Balancer plug-in according to platform&lt;br /&gt;&lt;br /&gt;&lt;a href="http://download.java.net/javaee5/external/"&gt;http://download.java.net/javaee5/external/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Guide to setting up GlassFish clustering:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://blogs.sun.com/dadelhardt/entry/clustering_web_applications_with_glassfish1"&gt;&lt;br /&gt;http://blogs.sun.com/dadelhardt/entry/clustering_web_applications_with_glassfish1&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Guide to setting up GlassFish with Load Balancer plugin:&lt;br /&gt;&lt;br /&gt;&lt;a href="https://glassfish.dev.java.net/javaee5/build/GlassFish_LB_Cluster.html"&gt;https://glassfish.dev.java.net/javaee5/build/GlassFish_LB_Cluster.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Further resources:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Clustering with Apache HTTPd:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.sun.com/jluehe/entry/supporting_apache_loadbalancer_with_glassfish"&gt;http://blogs.sun.com/jluehe/entry/supporting_apache_loadbalancer_with_glassfish&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Interesting thread about clustering problems:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.nabble.com/Cluster-session-replication-not-working-td20691318.html"&gt;http://www.nabble.com/Cluster-session-replication-not-working-td20691318.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;GlassFish V2 Clustering presentation:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.sun.com/stripathi/resource/Preso/GlassFishv2Clustering.pdf"&gt;http://blogs.sun.com/stripathi/resource/Preso/GlassFishv2Clustering.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Sun Clustering with GlassFish v2:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developers.sun.com/appserver/reference/techart/glassfishcluster/"&gt;http://developers.sun.com/appserver/reference/techart/glassfishcluster/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Setting up GlassFish SSL support:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://java.sun.com/mailers/techtips/enterprise/2007/TechTips2_Nov07.html"&gt;http://java.sun.com/mailers/techtips/enterprise/2007/TechTips2_Nov07.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;GlassFish JMX / JConsole:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://docs.sun.com/app/docs/doc/820-4335/ablwi?a=view"&gt;http://docs.sun.com/app/docs/doc/820-4335/ablwi?a=view&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sun Java web server (for load balancing):&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_SMI-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=SJWS6.1SP5-OTH-G-F@CDS-CDS_SMI"&gt;https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_SMI-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=SJWS6.1SP5-OTH-G-F@CDS-CDS_SMI&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-6253346418958086589?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/6253346418958086589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=6253346418958086589' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6253346418958086589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6253346418958086589'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/05/quick-notes-on-opensolaris-111a.html' title='Quick notes on OpenSolaris 111a &amp; GlassFish clustering'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-5975807849253079570</id><published>2009-04-08T11:58:00.000-07:00</published><updated>2009-04-08T15:14:47.089-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='salesforce.com'/><category scheme='http://www.blogger.com/atom/ns#' term='Cloud computing'/><category scheme='http://www.blogger.com/atom/ns#' term='azure'/><category scheme='http://www.blogger.com/atom/ns#' term='force.com'/><category scheme='http://www.blogger.com/atom/ns#' term='cloudforce'/><category scheme='http://www.blogger.com/atom/ns#' term='appengine'/><title type='text'>Cloud computing - cloudforce and beyond...</title><content type='html'>Having recently attended Cloudforce UK - London (07th-04-2009) I though I'd blog a little with some resources and links.&lt;br /&gt;&lt;br /&gt;I don't really want to re-invent the wheel and attempt to explain what cloud computing is exactly, hopefully some of the resources and links should cover that. For an overview, the Wikipedia entry is a good start &lt;a href="http://en.wikipedia.org/wiki/Cloud_computing"&gt;http://en.wikipedia.org/wiki/Cloud_computing&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A couple of terms that crop up in this domain are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;SaaS - Software as a Service&lt;/li&gt;&lt;li&gt;PaaS - Platform as a Service&lt;/li&gt;&lt;li&gt;IaaS - Infrastructure as a Service&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Cloudforce itself is a worldwide tour of salesforce.com - evangelising and spreading the word about their cloud products and frameworks, customer success stories and break out sessions covering aspects from development to opportunities.&lt;br /&gt;&lt;br /&gt;Details on the event &lt;a href="http://www.chinwag.com/events/2009/04/cloudforce-london-2009"&gt;http://www.chinwag.com/events/2009/04/cloudforce-london-2009&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Salesforce cloud platform:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.salesforce.com/platform/"&gt;http://www.salesforce.com/platform/&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Main features at a glance:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Product portfolio including CRM&lt;/li&gt;&lt;li&gt;Application store - the AppExchange&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Multiple server, massively scalable environment&lt;/li&gt;&lt;li&gt;Multi-tenant database optimised for cloud usage&lt;/li&gt;&lt;li&gt;Disaster recovery&lt;/li&gt;&lt;li&gt;Database, web service, business logic and presentation layers&lt;/li&gt;&lt;li&gt;Fast app creation, instant deployment&lt;/li&gt;&lt;li&gt;Live update of applications, can copy to sandbox to develop new versions&lt;/li&gt;&lt;li&gt;No built in source code control / visioning&lt;/li&gt;&lt;li&gt;Eclipse force plug ins available for development integration&lt;/li&gt;&lt;li&gt;Presentation framework and components (Visual Force)&lt;/li&gt;&lt;li&gt;Strongly types OO language - Apex (an on-demand language)&lt;/li&gt;&lt;li&gt;Web service creation API and integration support&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Integration with Mobile devices - iPhone, Blackberry and Windows mobile based devices&lt;/li&gt;&lt;li&gt;Integration with Twitter, Facebook, Google API's supported&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Site gallery / reference sites:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developer.force.com/sitesgallery"&gt;http://developer.force.com/sitesgallery&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Force.com Applications:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The platform has an App Exchange,  a place where cloud based applications can be shared and exchanged &lt;a href="http://www.salesforce.com/platform/appexchange/"&gt;http://www.salesforce.com/platform/appexchange/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The Salesforce platform offers a number of off the shelf, customisable applications products, such as Salesforce CRM &lt;a href="http://www.salesforce.com/products/"&gt;http://www.salesforce.com/products/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;App Development:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Salesforce developer home is here &lt;a href="http://developer.force.com/"&gt;http://developer.force.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The platform framework offers some technologies such as Visual Force for GUI components and component creation and Apex for code/page creation - &lt;a href="http://wiki.developerforce.com/index.php/Apex"&gt;http://wiki.developerforce.com/index.php/Apex&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Salesforce blerb about Apex "Force.com Apex Code is a strongly-typed programming language that executes on the Force.com platform. Apex is used to add business logic to applications, to write database triggers, and to program controllers in the user interface layer. It has a tight integration with the database and query language, good web services support, and includes features such as futures and governors for execution in a multi-tenant environment."&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Cloudforce take-aways:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As well as the above, the overall event gave an impression of some key takeaway points.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The service cloud, service applications now integrating and utilising knowledge from social networking sources such as Twitter, Facebook etc as well as traditional sources such as Phone. &lt;/li&gt;&lt;li&gt;Easy of application creation&lt;/li&gt;&lt;li&gt;Speed of development&lt;/li&gt;&lt;li&gt;Enable business to meet customer demands in terms of cost or time to market that might otherwise be impossible&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Some other providers:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Many over companies offer computing in the cloud, such as:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Microsoft - Windows Azure &lt;a href="http://en.wikipedia.org/wiki/Azure_Services_Platform"&gt;http://en.wikipedia.org/wiki/Azure_Services_Platform&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Google - App engine &lt;a href="http://code.google.com/appengine/"&gt;http://code.google.com/appengine/&lt;/a&gt; - recently with support for Java! read more here &lt;a href="http://blogoscoped.com/archive/2009-04-08-n87.html"&gt;http://blogoscoped.com/archive/2009-04-08-n87.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;3tera - &lt;a href="http://www.3tera.com/"&gt;http://www.3tera.com/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;SAP AG - SAP business as a service &lt;a href="http://en.wikipedia.org/wiki/SAP_Business_ByDesign"&gt;http://en.wikipedia.org/wiki/SAP_Business_ByDesign&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Amazon - EC2 (Elastic Compute Cloud) - &lt;a href="http://en.wikipedia.org/wiki/Amazon_Elastic_Compute_Cloud"&gt;http://en.wikipedia.org/wiki/Amazon_Elastic_Compute_Cloud&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Well, having just signed up for the Google App engine, expect more blogs in the future as I play around and experiment up in the clouds...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Further Resources:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Google AppEngine blogspot - &lt;a href="http://googleappengine.blogspot.com/"&gt;http://googleappengine.blogspot.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Sun Cloud Computing Primer (Need a Sun account) - &lt;a href="http://www.sun.com/offers/details/cloud_computing_primer.html"&gt;http://www.sun.com/offers/details/cloud_computing_primer.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-5975807849253079570?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/5975807849253079570/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=5975807849253079570' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/5975807849253079570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/5975807849253079570'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/04/cloud-computing-cloudforce-and-beyond.html' title='Cloud computing - cloudforce and beyond...'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-5301468620463132776</id><published>2009-04-02T14:18:00.000-07:00</published><updated>2009-04-10T06:45:15.547-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='DotNet'/><category scheme='http://www.blogger.com/atom/ns#' term='CSharp'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>.NET and C# - an introduction</title><content type='html'>Not so much an actual blog today, rather a link to a presentation I recently gave as an introduction to the .NET framework and C# - to a mixed audience of C, C++, Java and web developers.&lt;br /&gt;&lt;br /&gt;It's mainly a high level overview of the .NET framework and then an introduction to the C# language, from a programmers perspective, for programmers familiar with other languages like Java and C++, to help get familiar with the basics.&lt;br /&gt;&lt;a href="http://www.chillipower.com/Primers/IntroductionToDotNetandCsharpPresentation.odp"&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;Available in OpenOffice format ODP:&lt;br /&gt;&lt;a href="http://www.chillipower.com/Primers/IntroductionToDotNetandCsharpPresentation.odp"&gt;http://www.chillipower.com/Primers/IntroductionToDotNetandCsharpPresentation.odp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Or MS PowerPoint presentation format PPT:&lt;br /&gt;&lt;a href="http://www.chillipower.com/Primers/IntroductionToDotNetandCsharpPresentation.ppt"&gt;http://www.chillipower.com/Primers/IntroductionToDotNetandCsharpPresentation.ppt&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-5301468620463132776?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/5301468620463132776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=5301468620463132776' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/5301468620463132776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/5301468620463132776'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/04/net-and-c-introduction.html' title='.NET and C# - an introduction'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-6948130754652244736</id><published>2009-03-30T04:27:00.000-07:00</published><updated>2009-04-01T10:58:47.352-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Metro'/><category scheme='http://www.blogger.com/atom/ns#' term='Glassfish Portfolio'/><category scheme='http://www.blogger.com/atom/ns#' term='Jersey'/><category scheme='http://www.blogger.com/atom/ns#' term='Glassfish 3'/><category scheme='http://www.blogger.com/atom/ns#' term='Web stack'/><category scheme='http://www.blogger.com/atom/ns#' term='Glassfish'/><title type='text'>Some notes from Sun GlassFish portfolio tech talk, London</title><content type='html'>Sun GlassFish and GlassFish portfolio - Sun talk London, Regis House 25-03-2009&lt;br /&gt;&lt;br /&gt;Some notes that I  managed to take whilst at the talk.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.glassfish.org/"&gt;www.glassfish.org&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Claimed to be the fastest Java EE AS&lt;br /&gt;&lt;br /&gt;V2.0 -&gt; reference implementation for Java EE 5&lt;br /&gt;V3.x -&gt; reference implementation for Java EE 6&lt;br /&gt;&lt;br /&gt;Java EE standard 10 years old&lt;br /&gt;&lt;br /&gt;Metro -&gt; Interop between MS and Java WS.* standards&lt;br /&gt;&lt;br /&gt;GlassFish is Open Source under CDDL and GPL 2 license&lt;br /&gt;&lt;br /&gt;&lt;a href="http://java.sun.com/javaee"&gt;java.sun.com/javaee&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Transparent development&lt;br /&gt;&lt;br /&gt;Organic growth into middleware areas&lt;br /&gt;&lt;br /&gt;First appearance 2005&lt;br /&gt;V2 in 2007&lt;br /&gt;Current v2.1 in Feb 2009&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.beta.glassfish.java.net:81/maps"&gt;www.beta.glassfish.java.net:81/maps&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;6-700 downloads per month, 8 million in the last year / ~28k per day&lt;br /&gt;&lt;br /&gt;GlassFish portfolio is a set of related technologies including the AS&lt;br /&gt;&lt;ul&gt;&lt;li&gt;  Enterprise server (including support for SNMP)&lt;/li&gt;&lt;li&gt;  Web space server (joined with Life Ray - social networking &amp;amp; portal technologies)&lt;/li&gt;&lt;li&gt;  Web sack (a complete (L)(S)(?)AMP stack)&lt;/li&gt;&lt;li&gt;  GlassFish ESB (SOA platform) for integration, connectors, adaptors&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Java EE + Ruby on Rails, PHP and other frameworks&lt;br /&gt;&lt;br /&gt;(note - what is SFA?)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Enterprise version adds:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Performance advisor, performance monitor, SNMP, self management and alert manager&lt;/li&gt;&lt;li&gt;Update center&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example / reference sites:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;wotif.com - Glassfish &amp;amp; OpenMQ&lt;/li&gt;&lt;li&gt;www.travelmuse.com GlassFish, message queue and mysql (started by using community edition)&lt;/li&gt;&lt;li&gt;North american Nationwide Health Information Network - connect (NHIN- Connect)&lt;/li&gt;&lt;li&gt;OpenESB&lt;/li&gt;&lt;li&gt;ESB.SOA framework&lt;/li&gt;&lt;li&gt;Facebook - large mysql based system ~70million users&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;GlassFish has same levels and structure in terms of support and licensing as MySQL&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Web Services:&lt;/span&gt;  &lt;span style="font-weight: bold;"&gt;WS.*&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Metro is core in GlassFish AS&lt;/li&gt;&lt;li&gt;Project Metro Web services stack provides high level WS stack with security, reliability etc -&gt; .NET 3 interoperability (incorporates project tango - MS .NET interop)&lt;/li&gt;&lt;/ul&gt; &lt;span style="font-weight: bold;"&gt;&lt;br /&gt;REST&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JAX-RS JSR-311 Java API for RESTFul Web Services&lt;/li&gt;&lt;li&gt;Annotation based server side API&lt;/li&gt;&lt;li&gt;HTTP Centric&lt;/li&gt;&lt;li&gt;Server Side only&lt;/li&gt;&lt;li&gt;Servlet or SE deployment&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Jersey project provides implementation for JSR-311&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Performance:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Similar / faster than Weblogic and Websphere&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;GlassFish V3:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;OSGi: Apache Felix as default (origins in JSR-8)&lt;/li&gt;&lt;li&gt;1 sec startup&lt;/li&gt;&lt;li&gt;21Mb download&lt;/li&gt;&lt;li&gt;admin and update tool downloaded on demand&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Add-ons, modules available from update center:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;  EJB 3.1 (preview&lt;/li&gt;&lt;li&gt;  jRuby on Rails (new WAR packaging required)&lt;/li&gt;&lt;li&gt;  Grails (also on GFv2)&lt;/li&gt;&lt;li&gt;  Jersey and Metro (Web services)&lt;/li&gt;&lt;li&gt;  jMaki (AJAX)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Tools:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;  NetBeans and Eclipse&lt;/li&gt;&lt;li&gt;  Embedded GlassFish API&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;MicroKernel approach - modularity - base App server + on demand module loading, extensible and customizable&lt;br /&gt;&lt;br /&gt;("Eclipse Con" -&gt; announces GlassFiish bundle available)&lt;br /&gt;&lt;br /&gt;Db connection pooling and connection (connector) pooling (JCA)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;V3 Prelude&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;available from http://glassfish.org -&gt; using modular (microkernel) v3 ideas with existing EE5 technologies -&gt; &lt;span style="font-weight: bold;"&gt;this version is supported!&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;v3 prelude is Java EE Web layer only (i.e. servlets, JSPs etc but no Enterprise beans etc)&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Compile / Deploy on Change support, dynamic debug loop (netbeans &amp;amp; eclipse), incremental compile of all Java EE artifacts. Auto-deply of all Java EE and static artifacts&lt;br /&gt;&lt;br /&gt;Support for: JRuby, Ruby, Groovy, Grails, Python, jython, django, jmaki, JavaScript phobos&lt;br /&gt;&lt;br /&gt;Ruby / jRuby and rails can be run on 2.1 today (by packaging up dependancies), on v3 available as OSGi jRuby container&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;PHP&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Quercis (Caucho) opensource GPL php 5 implementation in Java&lt;/li&gt;&lt;li&gt;War Packaging&lt;/li&gt;&lt;li&gt;Java Bridge&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;V2 -&gt; ee 5&lt;br /&gt;V3 -&gt; prelude with EE5 support&lt;br /&gt;V3 -&gt; early access is EE6 spec (but not supported)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;GF Web Stack:&lt;/span&gt; &lt;ul&gt;&lt;li&gt;  Apache HTTPd&lt;/li&gt;&lt;li&gt;  Sun web server 7 (most scalable web server - now open sourced!) optimized for multi-core CMT (chip-based Multithreaded) systems - 2x scaling vs. Apache &amp;amp; Tomcat&lt;/li&gt;&lt;li&gt;  lightpd&lt;/li&gt;&lt;li&gt;  memcached&lt;/li&gt;&lt;li&gt;  mod_jk, perl, ruby, PHP Ruby, Python, Squid, Tomcat&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Current GF web stack is 1.4 (Python 2.5.2, Squid 2.6, Tomcat 5.5.27, memcached 1.2.5, mysql 5.0.67)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;GF ESB:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JSR 208 JBI (Java business Integration)&lt;/li&gt;&lt;li&gt;Plug-able integration into backbone&lt;/li&gt;&lt;li&gt;"Metacontainer" - add new containers within the container, extend the AS&lt;/li&gt;&lt;li&gt;BPEL, WS-*, XSLT, FTP, LDAP, HTTP, DB service and binding&lt;/li&gt;&lt;li&gt;Based on OpnESB -&gt; http://openesb.org / community open-esb.dev.java.net/Components.html&lt;/li&gt;&lt;li&gt;Maybe engines and connectors to things like Corba etc&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;What's next -&gt; &lt;a href="http://fuji.dev.java.net/"&gt;http://fuji.dev.java.net&lt;/a&gt; -&gt; OpenESB V3 - next gen of SOA&lt;br /&gt;&lt;br /&gt;(JBI and SCA stated as "complimentary, not conflicting")&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;GF: Web Space server (project web synergy)&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Portlet spec JSR-268 and more (social networking, communities)&lt;/li&gt;&lt;li&gt;OpenSSO, identify mechanisms&lt;/li&gt;&lt;li&gt;Compelling web UIs&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;GF enterprise manager:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Performance advisor&lt;/li&gt;&lt;li&gt;Alerts&lt;/li&gt;&lt;li&gt;JDBC pool management - automatically tunes JDBC connection pool to optimize performance etc&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Sailfin (Ericson contribution) telco, SIP, VOIP, Instant messaging&lt;br /&gt;&lt;br /&gt;dtrace etends into Apache and PHP&lt;br /&gt;&lt;br /&gt;Revamped PetStore 4 part tutorial - &lt;a href="http://developer.sun.com/"&gt;developer.sun.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;OpenSSO -&gt; new concept "express builds" - milestone interim builds from Open Source community in between main supported releases&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;WhitePapers:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;New White-papers on GlassFish portfolio launch:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Comparison with Tomcat&lt;/li&gt;&lt;li&gt;Performance optimization&lt;/li&gt;&lt;li&gt;GF with identify and MySQL&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Training available in Camberly, BSG in London etc&lt;br /&gt;&lt;br /&gt;www.javapassion.com&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Books:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;GlassFish&lt;/li&gt;&lt;li&gt;Database-driven application development&lt;/li&gt;&lt;li&gt;Others available (I didn't get time to note them down)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;a href="http://blogs.sun.com/theaquarium"&gt;blogs.sun.com/theaquarium&lt;/a&gt; -&gt; god launch pad for developer information&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.sun.com/stories"&gt;blogs.sun.com/stories&lt;/a&gt; -&gt; gives examples and real usage info&lt;br /&gt;&lt;br /&gt;Migration tools:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://migrate2glassfish.dev.java.net/blogs/blogs.html"&gt;migrate2glassfish.dev.java.net/blogs/blogs.html&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;built in tools to detect and advise on code usage (for EE standards and vendor specific code dependancies)&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Examples:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;JavaFX mobile - answer to J2ME shortcomings&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.javafx.com/"&gt;www.javafx.com&lt;/a&gt; -&gt; many tutorials and demos&lt;br /&gt;&lt;br /&gt;GlassFish profiles - Developer mode (no clustering etc) but fast start up and change deployment&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Clustering:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;DAS - Domain Administration server looks after a cluster, deploy to the domain administration server and it deploys to the cluster nodes.&lt;br /&gt;&lt;br /&gt;Session replication between cluster nodes, zero down time when switching between nodes&lt;br /&gt;&lt;br /&gt;install with -cluster switch&lt;br /&gt;&lt;br /&gt;Cluster elements run &lt;span style="font-weight: bold;"&gt;"node-agents"&lt;/span&gt; to talk to the &lt;span style="font-weight: bold;"&gt;DAS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Extra sections in the admin console -&gt; shows cluster nodes&lt;br /&gt;&lt;br /&gt;GlassFish performance monitor - enterprise only (TBC)?&lt;br /&gt;&lt;br /&gt;V3 Prelude - web tier only (web apps) but fully functional&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Presentation has now been published here: &lt;a href="http://uk.sun.com/sunnews/events/2009/mar/glassfish/pdf/UK-GlassFish-Portfolio-Launch-mar09.pdf"&gt;http://uk.sun.com/sunnews/events/2009/mar/glassfish/pdf/UK-GlassFish-Portfolio-Launch-mar09.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-6948130754652244736?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/6948130754652244736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=6948130754652244736' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6948130754652244736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6948130754652244736'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/03/some-notes-from-sun-glassfish-portfolio.html' title='Some notes from Sun GlassFish portfolio tech talk, London'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-4964192149282778638</id><published>2009-03-08T01:59:00.000-08:00</published><updated>2009-04-13T11:59:01.150-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='interface builder'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='xcode'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone dev'/><category scheme='http://www.blogger.com/atom/ns#' term='objective-c'/><title type='text'>Apple iPhone Development - introduction and resources</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Apple iPhone Development:&lt;/span&gt;&lt;div&gt;&lt;br /&gt;So, it seems like everyone's doing it these days, but that's no excuse for me not to join in is it?...&lt;br /&gt;&lt;br /&gt;Objective-C you say, isn't that a bit like Smalltalk?&lt;br /&gt;xCode, what's that exactly?&lt;br /&gt;Cocoa, Nibs? what the?!?&lt;br /&gt;&lt;br /&gt;Well there's much to learn, but most of it seems reasonably straightforward. The Apple documentation is good, there are videos to watch and tutorials, most of these resources can be found via the Apple iPhone dev center on the Apple website. From what I've gathered so far, its quite far removed from previous mobile development I've done, such as J2ME and .NET CF.&lt;br /&gt;&lt;br /&gt;Armed with a new Apple Mac I'm making some notes as I venture into the unknown.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Firstly, here are a bunch of useful resources:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;iPhone Dev center:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developer.apple.com/iphone/"&gt;http://developer.apple.com/iphone/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;iPhone Developer Program:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developer.apple.com/iphone/program/"&gt;http://developer.apple.com/iphone/program/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;iPhone SDK:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developer.apple.com/iphone/download.action?path=/iphone/iphone_sdk_for_iphone_os_2.2.1__9m2621a__final/iphone_sdk_for_iphone_os_2.2.19m2621afinal.dmg"&gt;http://developer.apple.com/iphone/download.action?path=/iphone/iphone_sdk_for_iphone_os_2.2.1__9m2621a__final/iphone_sdk_for_iphone_os_2.2.19m2621afinal.dmg&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Objective-C:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/ObjC.pdf"&gt;http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/ObjC.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Objective-C is an object orientated version of the C language. Specifically for the iPhone, Objective-C 2.0 is used.&lt;br /&gt;&lt;br /&gt;Objective-C has been influenced by Smalltalk, yes that's the OO language with all the [] in it.&lt;br /&gt;&lt;br /&gt;iPhone development guide:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developer.apple.com/iphone/library/documentation/Xcode/Conceptual/iphone_development/iPhone_Development.pdf"&gt;http://developer.apple.com/iphone/library/documentation/Xcode/Conceptual/iphone_development/iPhone_Development.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;First iPhone application:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhone101/iPhone101.pdf"&gt;http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhone101/iPhone101.pdf&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;The current latest version of the iPhone OS and iPhone SDK is 2.2.1 (whilst at the time of writing this 3.0 is in beta preview).&lt;br /&gt;&lt;br /&gt;The next version, 3.0 is to be officially launched soon, the SDK should be available before the official OS release, in theory. What's in it, what's different I don't know yet, but hopefully it will be largly compatible with the current version, whilst adding some interesting new features into the mix. Rumoured are things like the much awaited support for copy, cut and paste for example.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;HTTP and XML, web services:&lt;/span&gt;&lt;br /&gt;Interested in hooking up an iPhone application with some web services, some means to make an HTTP request and parse XML is needed, here are a couple of resources on this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Simple solution using some utility code:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.atrexis.com/index.cfm/2008/7/28/iPhone--Parse-XML-to-custom-objects"&gt;http://blog.atrexis.com/index.cfm/2008/7/28/iPhone--Parse-XML-to-custom-objects&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A more advanced solution:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/touchcode/wiki/TouchXML"&gt;http://code.google.com/p/touchcode/wiki/TouchXML&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Useful article on RESTful clients:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developer.apple.com/safari/articles/creatingrestfulclients.html"&gt;http://developer.apple.com/safari/articles/creatingrestfulclients.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-4964192149282778638?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/4964192149282778638/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=4964192149282778638' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4964192149282778638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4964192149282778638'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/03/apple-iphone-development-introduction.html' title='Apple iPhone Development - introduction and resources'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-6510153153931590597</id><published>2009-03-01T14:01:00.000-08:00</published><updated>2009-03-02T11:52:11.569-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='Prime factorization'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Prime factorization, a comparison between Haskell and Scala</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Haskell &lt;/span&gt;is a powerful and expressive pure lazy functional programming language with some interesting properties. &lt;a href="http://www.haskell.org/"&gt;http://www.haskell.org/&lt;/a&gt; Haskell is of course named after the famous logician Haskell Curry &lt;a href="http://en.wikipedia.org/wiki/Haskell_Curry"&gt;http://en.wikipedia.org/wiki/Haskell_Curry&lt;/a&gt; who's name can be found in both the Haskell language and the process of "currying" functions.&lt;br /&gt;&lt;br /&gt;By way of example and comparison the task of finding prime numbers is shown in Haskell and then its equivalent is shown in Scala.&lt;br /&gt;&lt;br /&gt;We can see the conciseness of Haskell and the power of lazyness in expressions of the form:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;font-family:courier new;" &gt;[3..]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;which creates an infinite list of integers from 3 upwards. This seeming impossibility can be handled in a lazy functional language because the infinite list is not evaluated up front, rather the list is only evaluated when needed so the list is finite at any given point in time.&lt;br /&gt;&lt;br /&gt;So, in essence a lazy language is one where an expression is only evaluated when it's needed, unlike an imperative language where it's evaluated when declared.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Haskell: prime factorization example:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;divides :: Integer -&amp;gt; Integer -&amp;gt; Bool&lt;br /&gt;divides d n = rem n d == 0&lt;br /&gt;&lt;br /&gt;ld :: Integer -&amp;gt; Integer&lt;br /&gt;ld n = ldf 2 n&lt;br /&gt;&lt;br /&gt;ldf :: Integer -&amp;gt; Integer -&amp;gt; Integer&lt;br /&gt;ldf k n | divides k n = k&lt;br /&gt; | k^2 &amp;gt; n = n&lt;br /&gt; | otherwise = ldf (k+1) n&lt;br /&gt;&lt;br /&gt;factors :: Integer -&amp;gt; [Integer]&lt;br /&gt;factors n | n &amp;lt; 1 = error "Invalid argument: argument must be positive"&lt;br /&gt;   | n == 1 = []&lt;br /&gt;   | otherwise = p : factors (div n p) where p = ld n&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If the above is saved in a file (called say primefactorization) and loaded into Hugs (Hugs is a Haskell interpreter shell based on Haskell 98 - &lt;a href="http://www.haskell.org/hugs/"&gt;http://www.haskell.org/hugs/&lt;/a&gt;) using the :l command as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Main&gt; :l c:\Dev\haskell\primefactorisation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Scala: prime factorization example:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;object PrimeFactorisationTest {&lt;br /&gt;&lt;br /&gt; def divides(d : Int, n : Int) = {&lt;br /&gt;   (n % d) == 0&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def ld(n : Int) : Int = {&lt;br /&gt;   ldf(2, n)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def ldf(k : Int, n : Int) : Int = {&lt;br /&gt;   if (divides(k, n)) k&lt;br /&gt;   else if ((k*k) &amp;gt; n) n&lt;br /&gt;   else ldf((k+1), n)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def factors(n : Int) : List[Int] = n match {&lt;br /&gt;   case 1 =&amp;gt; Nil;&lt;br /&gt;   case _ =&amp;gt; {&lt;br /&gt;     val p = ld(n)&lt;br /&gt;     p :: factors(n / p)&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def main(args : Array[String]) {&lt;br /&gt;   if (args.length == 1)&lt;br /&gt;   {&lt;br /&gt;     val n = Integer.parseInt(args(0))&lt;br /&gt;     println(factors(n))&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Results:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Main&gt; factors 12343434&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[2,3,79,26041]&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Both programs produce the same output and are functionally equivalent - it's also clear to see there's a reasonably similarity in both conciseness and expressiveness of the two languages, where Haskell possibly has the slight edge in some respects such as use of the "where" construct.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Following on from the excellent comments on the Haskell version from &lt;span style="font-weight: bold;"&gt;Don Stewart&lt;/span&gt;, turning the code into something that can be compiled and executed natively, rather than being interpreted using Hugs, roughly involves the following steps.&lt;br /&gt;&lt;br /&gt;Install GHC &lt;a href="http://www.haskell.org/ghc/"&gt;http://www.haskell.org/ghc/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Rename the file to have a .hs file extension&lt;br /&gt;&lt;br /&gt;Add a main that can process the arguments:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;main = do&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  [n] &lt;- getArgs&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  print (factors (read n))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;add import to provide environment functions such as getArgs to the top of the file:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;import System.Environment&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Compile the file:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;$ghc --make primefactorisation.hs&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Run the executable:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;$ time ./primefactorisation.exe 12343434&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;[2,3,79,26041]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;real    0m0.140s&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;user    0m0.015s&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;sys     0m0.015s&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and there we have it, a functional executable.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Don Stewart&lt;/span&gt; also makes a good point about being able to leave out all the type information.&lt;br /&gt;&lt;br /&gt;In particular Haskell uses the powerful &lt;span style="font-weight: bold;"&gt;Hindley-Milner&lt;/span&gt; type inference algorithm to allow minimal (often zero) use of explicit type declarations.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://c2.com/cgi/wiki?HindleyMilnerTypeInference"&gt;http://c2.com/cgi/wiki?HindleyMilnerTypeInference&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-6510153153931590597?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/6510153153931590597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=6510153153931590597' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6510153153931590597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6510153153931590597'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/03/prime-factorization-comparison-between.html' title='Prime factorization, a comparison between Haskell and Scala'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-3693527580786115673</id><published>2009-02-23T14:08:00.001-08:00</published><updated>2009-03-15T15:53:32.160-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OpenSolaris libc'/><title type='text'>OpenSolaris, libc problem upgrading to b107</title><content type='html'>Just a quick note, upgrading from b106 to 107 left me with a foobared installation. It turns out that &lt;span style="font-weight: bold;"&gt;libc.so.1&lt;/span&gt; ends up being an incompatible version for the Kernel.&lt;br /&gt;&lt;br /&gt;Luckily the fix / work around is fairly trivial :)&lt;br /&gt;&lt;br /&gt;On my machine it was roughly as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;beadm mount opensolaris-19 /a&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;rm /a/lib/libc.so.1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;rm /a/lib/amd64/libc.so.1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;pkg -R /a fix SUNWcsl&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;beadm unmount opensolaris-19&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Reboot into opensolaris-19&lt;br /&gt;&lt;br /&gt;Problem fixed!&lt;br /&gt;&lt;br /&gt;The bug if filed here: &lt;a href="http://defect.opensolaris.org/bz/show_bug.cgi?id=3562"&gt;http://defect.opensolaris.org/bz/show_bug.cgi?id=3562&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;But that's not all, I was then faced with a second problem - which turned out to be unsupported "stuff" left over in the /etc/X11/xorg.conf, in particular an "RgbPath" related config line - so this needed to be removed.&lt;br /&gt;&lt;br /&gt;gdm then restarted&lt;br /&gt;&lt;br /&gt;svcadm disable gdm&lt;br /&gt;svcadm enable gdm&lt;br /&gt;&lt;br /&gt;X11 logs can also be checked for further errors:&lt;br /&gt;&lt;br /&gt;/var/log/Xorg.0.log&lt;br /&gt;&lt;br /&gt;and viola, a graphical login appears at last...&lt;br /&gt;&lt;br /&gt;For further details on b107 issues, see &lt;a href="http://blogs.sun.com/alanc/entry/xorg_1_5_3_in"&gt;http://blogs.sun.com/alanc/entry/xorg_1_5_3_in&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update:&lt;/span&gt; Since these problems with 107, 108 has come out and it seems to address these issues, upgrading from 107 to 108 was completely painless and problem free!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Additional note:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Recently trying to install OpenSolaris 109 under VirtualBox 2.1.4 resulted in a frozen white screen  before the graphical login. After some digging around and debugging the problem appeared to be an incompatibility with VirtualBox guest additions (GA).&lt;br /&gt;&lt;br /&gt;I believe the problem is captured here (as a major fault).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.virtualbox.org/ticket/3408"&gt;http://www.virtualbox.org/ticket/3408&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The work around / temp solution is to:&lt;br /&gt;&lt;br /&gt;Boot into single user command line login (edit boot grub)&lt;br /&gt;Remove VirtualBox GA installation&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&gt;pkginfo | grep -i box&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&gt;pkgrm SUNWvboxguest&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Delete xorg.conf (/etc/X11/)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&gt;rm  /etc/X11/xorg.conf&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Restart GDM (svcadm restart gdm)&lt;br /&gt;&lt;br /&gt;Check logs:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&gt;tail -f /var/log/Xorg.0.log&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;To install VirtualBox Guest Additions, select "Devices -&gt; Install Guest Additions..."&lt;br /&gt;&lt;br /&gt;Navigate to the installer resources (usually visible on the guest OS desktop)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&gt;pkgadd -d ./VBoxSolarisAdditions.pkg&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-3693527580786115673?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/3693527580786115673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=3693527580786115673' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/3693527580786115673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/3693527580786115673'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/02/opensolaris-libc-problem-upgrading-to.html' title='OpenSolaris, libc problem upgrading to b107'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-5411184347346134003</id><published>2009-02-22T03:59:00.001-08:00</published><updated>2009-02-22T04:23:26.040-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='anonymous class'/><category scheme='http://www.blogger.com/atom/ns#' term='implicit'/><category scheme='http://www.blogger.com/atom/ns#' term='implicit conversion'/><title type='text'>Scala, implicit conversions</title><content type='html'>Today, a small posting on the &lt;span style="font-weight: bold;"&gt;implicit conversion&lt;/span&gt; feature of &lt;span style="font-weight: bold;"&gt;Scala&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Implicit conversions provide a powerful way to extend classes with new functionality, as if already built into the library or even the language itself. There are similarities with C# extension methods, but Scala's implicit conversion mechanism is more concise, flexible and maintainable.&lt;br /&gt;&lt;br /&gt;To define an implicit conversion in Scala, the syntax is:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;impict def myImplicitConversionName(n: type) = new MyConversionType(n)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The scenario is that you want to add some new method(s) or functionality to instances of an existing class for which may be final/sealed or where sub-classing is inappropriate or not possible / effective. Implicit conversions provide a very natural way to add functionality and to users it will appear as natural features of the language/library, no special syntax is required.&lt;br /&gt;&lt;br /&gt;A good example is provided on the Scala site: &lt;a href="http://www.scala-lang.org/node/226"&gt;http://www.scala-lang.org/node/226&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Which is a good example because it shows exactly the reasons why you might want to extend the language or library. In this case, the type &lt;span style="font-style: italic;"&gt;int&lt;/span&gt; provides a good candidate for extension - to add the ! factorial function as if it was natural function of the type int.&lt;br /&gt;&lt;br /&gt;I wanted to expand on this example by providing a couple of examples of the same thing with further explanation.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example 1:&lt;/span&gt; explicitly defining a class that provides the extensions and using it in the implicit def&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;object extendBuiltins2 {&lt;br /&gt;&lt;br /&gt;// the important bit, it says there's an implicit conversion from int to Factorizer(n : int)&lt;br /&gt;implicit def int2fact(n: Int) = new Factorizer(n)&lt;br /&gt;&lt;br /&gt;def main(args : Array[String]) = {&lt;br /&gt;&lt;br /&gt;  // when the compiler sees this, it will first 'look for' ! method in int,&lt;br /&gt;  // when it doesn't find it, it will look for an implicit conversion on int that provides !&lt;br /&gt;  // which is of course exactly what we've just provided in the Factorizer class&lt;br /&gt;  println("10! = " + (10!))&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// define ! as a method on a class that can be constructed from int - this class will&lt;br /&gt;// provide the implicit conversion that supplied an implementation of ! on int&lt;br /&gt;class Factorizer(n: Int) {&lt;br /&gt;&lt;br /&gt;  def ! = fact(n)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// the plain old factorial function&lt;br /&gt;def fact(n: Int): BigInt =&lt;br /&gt;  if (n == 0) 1 else fact(n-1) * n&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The key line that defines the implicit conversion is this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;implicit def int2fact(n: Int) = new Factorizer(n)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;what we are saying is that there is an implicit conversion from type &lt;span style="font-style: italic;"&gt;int &lt;/span&gt;to type &lt;span style="font-style: italic;"&gt;Factorizer(int)&lt;/span&gt; - so where we have an int, if ! is called the compiler will look for ! on int and fail to find it. It will then seek an implicit conversion that can convert from int in order to provide this method ! - where it finds our implicit conversion definition that uses the Factorizer class to provide the implementation of !&lt;br /&gt;&lt;br /&gt;One reason this is more powerful than extension methods is that a whole class of functionality can be added to an existing class without explicitly extending all the methods individually. This has important benefits when it comes to maintenance, if the definition of the extending class changes, you get those changes automatically, you do not have to modify all the extension methods to match.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example 2:&lt;/span&gt; equivalent to the above example but using an anonymous class for a more concise solution where the explicit definition of a class is of no other use.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/* More concise way of adding ! as a method on int's - no explicit class definition */&lt;br /&gt;object extendBuiltins {&lt;br /&gt;&lt;br /&gt;implicit def int2fact(n: Int) = new {&lt;br /&gt;&lt;br /&gt;  def fact(n: Int): BigInt =&lt;br /&gt;    if (n == 0) 1 else fact(n-1) * n&lt;br /&gt;&lt;br /&gt;  def ! = fact(n);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def main(args : Array[String]) = {&lt;br /&gt;&lt;br /&gt;  println("10! = " + (10!))&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This achieves the same this as example 1 but does so more concisely with the &lt;span style="font-weight: bold;"&gt;anonymous class&lt;/span&gt;, constructed using the convenient &lt;span style="font-weight: bold;font-family:courier new;" &gt;= new {} &lt;/span&gt;syntax.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-5411184347346134003?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/5411184347346134003/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=5411184347346134003' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/5411184347346134003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/5411184347346134003'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/02/scala-implicit-conversions.html' title='Scala, implicit conversions'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-3539311282457495003</id><published>2009-02-20T11:08:00.000-08:00</published><updated>2009-03-02T12:06:34.333-08:00</updated><title type='text'>Some interesting reading material and resources...</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Some interesting reading material and resources...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Nothing much to see here, I just wanted to capture some links to interesting resources and reading material...&lt;br /&gt;&lt;br /&gt;Papers and articles on Lambdas&lt;a href="http://library.readscheme.org/page1.html"&gt; http://library.readscheme.org/page1.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Functional Java library - &lt;a href="http://functionaljava.org/"&gt;http://functionaljava.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This library brings some functional programming constructs and library functions to Java, using either Java bgga prototype compiler based on JDK 7 or a more traditional anonymous class approach using standard Java 5. Both are JRE 5 compatible.&lt;br /&gt;&lt;br /&gt;The Java Closures BGGA proposal&lt;span style="text-decoration: underline;"&gt; &lt;/span&gt;&lt;a href="http://javac.info/"&gt;http://javac.info/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;.Net functional extension method library &lt;a href="http://www.mono-project.com/Rocks"&gt;http://www.mono-project.com/Rocks&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Apple iPhone Dev centre - &lt;a href="http://developer.apple.com/iphone/index.action"&gt;http://developer.apple.com/iphone/index.action&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;a href="http://www.iolanguage.com/"&gt;http://www.iolanguage.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-3539311282457495003?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/3539311282457495003/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=3539311282457495003' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/3539311282457495003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/3539311282457495003'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/02/some-interesting-reading-material-and.html' title='Some interesting reading material and resources...'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-8624506581395072720</id><published>2009-02-18T11:54:00.000-08:00</published><updated>2009-02-21T12:18:51.664-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='Lamda'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Currying'/><category scheme='http://www.blogger.com/atom/ns#' term='partial application'/><category scheme='http://www.blogger.com/atom/ns#' term='partial functions'/><category scheme='http://www.blogger.com/atom/ns#' term='Curried functions'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Currying, some examples and comparisons between C# and Scala</title><content type='html'>I'm back again! It's been some 3 weeks since my last blog - I've been in New York for 5 days and busy either side sorting out commitments and work and home.&lt;br /&gt;&lt;br /&gt;So, in this posting I'd like to continue on the theme of Lamda and functional programming with some simple examples of Currying in both C# .Net (3.0+) and Scala.&lt;br /&gt;&lt;br /&gt;I've tried to keep the examples equivalent as closely as possible but Scala has a few different options when it comes to syntax, so the Scala version is a little longer as it delves into these extra possibilities.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What is currying?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In a nutshell currying is "the process of reducing a function that takes multiple arguments into a series of functions that each take one argument"&lt;br /&gt;&lt;br /&gt;Named after Haskell Curry - &lt;a href="http://en.wikipedia.org/wiki/Haskell_Curry"&gt;http://en.wikipedia.org/wiki/Haskell_Curry&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A good explanation and definition can be found here &lt;a href="http://www.haskell.org/haskellwiki/Currying"&gt;http://www.haskell.org/haskellwiki/Currying&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;C# .Net example using C# 3.0+ syntax for Lamdas:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;using System;&lt;br /&gt;&lt;br /&gt;static class Program&lt;br /&gt;{&lt;br /&gt;    static void Main()&lt;br /&gt;    {&lt;br /&gt;        Func&amp;lt;int, int, int&amp;gt; add = (x, y) =&amp;gt; x + y;&lt;br /&gt;&lt;br /&gt;        var curriedAdd = add.Curry();&lt;br /&gt;&lt;br /&gt;        var curriedIncrement = add.Curry()(1);&lt;br /&gt;        var curriedDecrement = add.Curry()(-1);&lt;br /&gt;&lt;br /&gt;        Console.WriteLine(&amp;quot;curriedAdd(10)(11) = &amp;quot; + curriedAdd(10)(11));&lt;br /&gt;        Console.WriteLine(&amp;quot;curriedIncrement(41) = &amp;quot; + curriedIncrement(41));&lt;br /&gt;        Console.WriteLine(&amp;quot;curriedDecrement(41) = &amp;quot; + curriedDecrement(41));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // a simple 2 arg curry template function&lt;br /&gt;    static Func&amp;lt;TArg1, Func&amp;lt;TArg2, TResult&amp;gt;&amp;gt; Curry&amp;lt;TArg1, TArg2, TResult&amp;gt;(this Func&amp;lt;TArg1, TArg2, TResult&amp;gt; f)&lt;br /&gt;    {&lt;br /&gt;        return a1 =&amp;gt; a2 =&amp;gt; f(a1, a2);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Results:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;curriedAdd(10)(11) = 21&lt;br /&gt;curriedIncrement(41) = 42&lt;br /&gt;curriedDecrement(41) = 40&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Notes:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The use of the var keyword for implicit typing&lt;/li&gt;&lt;li&gt;C# does not provide implicit functions/ partial application so a Curry template function for 2 arguments has been provided explicitly.&lt;/li&gt;&lt;li&gt;The Curry method is defined as an extension method so it appears as-if defined on add&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Extension Method:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;static Func&amp;lt;TArg1, Func&amp;lt;TArg2, TResult&amp;gt;&amp;gt; Curry&amp;lt;TArg1, TArg2, TResult&amp;gt;(this Func&amp;lt;TArg1, TArg2, TResult&amp;gt; f)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Take the above definition of a method, the this keyword in the (this Func...) parameter definition makes the function an extension method, so it can be used as if it were declared on the add function - to illustrate the point, without the extension syntax the Curry function could only be invoked in the regular way as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;var curriedAdd = Curry(add);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As an extension method, it's valid to use the original add.Curry() or Curry(add) syntax interchangeably.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Scala example:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test;&lt;br /&gt;&lt;br /&gt;object Currying {&lt;br /&gt;&lt;br /&gt;  def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;    // regular syntax function add&lt;br /&gt;    def add(x : int, y : int) = {&lt;br /&gt;&lt;br /&gt;      x + y&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // create curried add using 1 and -1 for increment and decrement by invoking partial function (a:int, _:int):int&lt;br /&gt;    var curriedIncrement = add(1, _ : int)&lt;br /&gt;    var curriedDecrement = add(-1, _ : int)&lt;br /&gt;&lt;br /&gt;    // test funtions&lt;br /&gt;    println("add(10, 11) = " + add(10, 11))&lt;br /&gt;    println("curriedIncrement(41) = " + curriedIncrement(41));&lt;br /&gt;    println("curriedDecrement(41) = " + curriedDecrement(41));&lt;br /&gt;&lt;br /&gt;    // curried syntax function add&lt;br /&gt;    def add2(x : int)(y : int) = {&lt;br /&gt;&lt;br /&gt;      x + y&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // create curried functions using partial functions&lt;br /&gt;    var curriedIncrement2 = add2(1)(_ : int)&lt;br /&gt;    var curriedDecrement2 = add2(-1)(_ : int)&lt;br /&gt;&lt;br /&gt;    println("add2(10)(11) = " + add2(10)(11))&lt;br /&gt;    println("curriedIncrement2(41) = " + curriedIncrement2(41));&lt;br /&gt;    println("curriedDecrement2(41) = " + curriedDecrement2(41));&lt;br /&gt;&lt;br /&gt;    // special {} syntax&lt;br /&gt;    val res1 = add2(10) {&lt;br /&gt;      11&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    println("res1 = " + res1)&lt;br /&gt;&lt;br /&gt;    // more complex example&lt;br /&gt;    val x = 1&lt;br /&gt;    val y = 2&lt;br /&gt;&lt;br /&gt;    val z = add2(10) {&lt;br /&gt;&lt;br /&gt;      add2(20) {&lt;br /&gt;&lt;br /&gt;        x + y&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    println("z = " + z)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Results:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;add(10, 11) = 21&lt;br /&gt;curriedIncrement(41) = 42&lt;br /&gt;curriedDecrement(41) = 40&lt;br /&gt;add2(10)(11) = 21&lt;br /&gt;curriedIncrement2(41) = 42&lt;br /&gt;curriedDecrement2(41) = 40&lt;br /&gt;res1 = 21&lt;br /&gt;z = 33&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Notes:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Scala supports f(x:int)(y:int) syntax for explicit curried functions&lt;/li&gt;&lt;li&gt;Scala supports implicit currying using partial application, using the placeholder _ syntax&lt;/li&gt;&lt;li&gt;Scala supports curried parameter in {} syntax for functions that appear to extend the language by taking parameter from the body of the call.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Update:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I realised that the way I'd defined the curried add functions in the Scala example is perhaps not as verbose or explicit as it could have been, and therefore perhaps less easy to understand or compare to the C# example. So here is another code snipped that shows a more verbose currying:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;object Currying {&lt;br /&gt;&lt;br /&gt;  def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;    def add3(x : int) = {&lt;br /&gt;&lt;br /&gt;        (y : int) =&gt; {&lt;br /&gt;           x + y&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    println("add3(1)(2) = " + add3(1)(2));&lt;br /&gt;&lt;br /&gt;    val res = add3(5){&lt;br /&gt;&lt;br /&gt;        3&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    println("res = " + res)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Results:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;add3(1)(2) = 3&lt;br /&gt;res = 8&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Resourses:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Good explanation of currying in C#.Net &lt;a href="http://diditwith.net/2007/08/15/TheArtOfCurrying.aspx"&gt;http://diditwith.net/2007/08/15/TheArtOfCurrying.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-8624506581395072720?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/8624506581395072720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=8624506581395072720' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8624506581395072720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8624506581395072720'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/02/currying-some-examples-and-comparisons.html' title='Currying, some examples and comparisons between C# and Scala'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-5133553157120526589</id><published>2009-01-23T11:15:00.000-08:00</published><updated>2009-01-25T12:18:50.574-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='Euclid&apos;s Algorithm'/><category scheme='http://www.blogger.com/atom/ns#' term='tuples'/><category scheme='http://www.blogger.com/atom/ns#' term='tuples by example'/><title type='text'>Scala, a small example of Euclid's Algorithm</title><content type='html'>A small posting today, a simple example of Euclid's algorithm in Scala. This algorithm can be expressed very concisely and simply using recursion. This example demonstrates the use of &lt;span style="font-weight: bold;"&gt;tuples&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;map&lt;/span&gt; in the Scala language.&lt;br /&gt;&lt;br /&gt;If you don't know, Euclid's algorithm is a ancient, simple algorithm for finding the &lt;span style="font-style: italic;"&gt;greatest common divisor&lt;/span&gt; (GCD) for two integers, without factoring either of the two integers in question.&lt;br /&gt;&lt;br /&gt;The algorithm can be expressed recursively thus:&lt;br /&gt;&lt;pre&gt;&lt;b style="font-family: courier new;"&gt;function&lt;/b&gt;&lt;span style="font-family:courier new;"&gt; gcd(x, y)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;if&lt;/b&gt;&lt;span style="font-family:courier new;"&gt; (y == 0) x&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;else&lt;/b&gt;&lt;span style="font-family:courier new;"&gt; gcd(y, x &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;mod&lt;/b&gt;&lt;span style="font-family:courier new;"&gt; y)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The particular construction worth noting in this example is the use of tuples.&lt;br /&gt;&lt;br /&gt;Tuples are like records, structures or groupings of variables that can be constructed using a (x, y, z) syntax when x, y and z are variables. A tuple can be decomposed by accessing its elements using the t _1 syntax, where t is the tuple and _1 is a method that accesses the first element in tuple. Tuple elements are therefore indexed using a base of 1.&lt;br /&gt;&lt;br /&gt;The example defines numbers as a list of tuples, each tuple contains a pair of integers - the two integers to be applied to the GCD algorithm (Euclid's Algorithm).&lt;br /&gt;&lt;br /&gt;The list of tuples is then "mapped" using the map function that takes each tuple and calls the function x =&gt; ((Int, Int), Int, Boolean), where x will be each tuple in the list in turn.&lt;br /&gt;&lt;br /&gt;The tuple x is decomposed into its two integer component parts using the x _1 and x _2 syntax.&lt;br /&gt;&lt;br /&gt;The returned tuple ((Int, Int), Int, Boolean) contains the original tuple of integers to be tested, the gcd values and a boolean indicating if the numbers are co-prime. The numbers are co-prime if the GCD is equal to 1.&lt;br /&gt;&lt;br /&gt;I've included a few different ways to represent the function used by map, to use and decompose the tuple. The first solution using the tuple argument directly and accesses its members using the _1, _2 syntax directly. The second solution uses a function literal and the _ placeholder syntax on the map argument. The function literal uses the val (a, b) = x; sytax to decompose the tuple into and and b, but this is a bit clumsey/verbose. The 3rd solution is essentially the same as a the 2nd but the function is defined in-line.&lt;br /&gt;&lt;br /&gt;The last solution is probably the nicest, it uses the case(a, b) syntax to decompose the tuple into a and b using pattern matching.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example Code:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;object EuclidsAlgorithm {&lt;br /&gt;&lt;br /&gt; def main(arg : Array[String]) = {&lt;br /&gt;&lt;br /&gt;   // define a list of tuples (Int, Int), pairs to test for coprimeness&lt;br /&gt;   val numbers = (3, 6) :: (3, 7) :: (4, 8) :: (5, 45) :: (5, 43) :: (1071, 1029) :: (1071, 1023) :: (1071, 1021) :: Nil&lt;br /&gt;&lt;br /&gt;   // #1. Working with the tuple directly, using the tuple _1, _2 syntax&lt;br /&gt;   val res1 = numbers map ( x =&amp;gt; ((x _1, x _2),  gcd(x _1, x _2), gcd(x _1, x _2) == 1 )  )&lt;br /&gt;&lt;br /&gt;   // #2. Defining a function literal&lt;br /&gt;   val f = (x : (Int, Int)) =&amp;gt; { val (a, b) = x;  ((a, b), gcd(a, b), gcd(a, b) == 1) }&lt;br /&gt;&lt;br /&gt;   // and using it with the _ placeholder syntax for the parameter representing each element of the list&lt;br /&gt;   val res2 = numbers map ( f(_) )&lt;br /&gt;&lt;br /&gt;   // #3. Using the #2 above but in-line&lt;br /&gt;   val res3 = numbers map ( x =&amp;gt; { val (a, b) = x; ((a, b), gcd(a, b), gcd(a, b) == 1) }  )&lt;br /&gt;&lt;br /&gt;   // #3. Using a case match on the tuple to expose its components a and b. This is probably the nicest and most concise way&lt;br /&gt;   val res4 = numbers map ( { case (a, b) =&amp;gt; ((a, b), gcd(a, b), gcd(a, b) == 1) } )&lt;br /&gt;&lt;br /&gt;   res4.foreach(println)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; // Euclids algorithm, finds the GCD&lt;br /&gt; def gcd(a : Int, b : Int) : Int = {&lt;br /&gt;&lt;br /&gt;   if (b == 0)&lt;br /&gt;     a&lt;br /&gt;   else&lt;br /&gt;     gcd(b, a % b)&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Results:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;((3,6),3,false)&lt;br /&gt;((3,7),1,true)&lt;br /&gt;((4,8),4,false)&lt;br /&gt;((5,45),5,false)&lt;br /&gt;((5,43),1,true)&lt;br /&gt;((1071,1029),21,false)&lt;br /&gt;((1071,1023),3,false)&lt;br /&gt;((1071,1021),1,true)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-5133553157120526589?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/5133553157120526589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=5133553157120526589' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/5133553157120526589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/5133553157120526589'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/01/scala-small-example-of-euclids.html' title='Scala, a small example of Euclid&apos;s Algorithm'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-4191983638449350636</id><published>2009-01-19T11:27:00.000-08:00</published><updated>2009-01-20T04:16:31.666-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='pattern matching'/><category scheme='http://www.blogger.com/atom/ns#' term='insertion sorting'/><category scheme='http://www.blogger.com/atom/ns#' term='sorting'/><category scheme='http://www.blogger.com/atom/ns#' term='sort'/><title type='text'>Scala, insertion sort and pattern matching</title><content type='html'>This posting shows insertion sorting in Scala. Insertion sort is not a particularly efficient algorithm but this example code does demonstrate the use of pattern matching on lists using the &lt;span style="font-family:courier new;"&gt;match&lt;/span&gt; keyword and the case &lt;span style="font-family:courier new;"&gt;x :: y type&lt;/span&gt; expression.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;val result = values match {&lt;br /&gt;&lt;br /&gt; case List() =&amp;gt; List()&lt;br /&gt;&lt;br /&gt; case value :: valuesTail =&amp;gt; insert(value, iSort(valuesTail))&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above code pattern matched the List values against 2 cases. The first being the empty list, in which case an empty list &lt;span style="font-family: courier new;"&gt;List()&lt;/span&gt; is returned. the second is the pattern &lt;span style="font-family: courier new;"&gt;value :: valuesTail&lt;/span&gt;, which puts the head of the list in value and the tail (the rest of the list) in &lt;span style="font-family: courier new;"&gt;valuesTail&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example code:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;// Nb: This is not an efficient sorting algorithm but it domostrates&lt;br /&gt;// some aspects of scala for representing algorithms, along with functions as first class objects and currying&lt;br /&gt;object SortingTest {&lt;br /&gt;&lt;br /&gt;   def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;       val list1 = 5 :: 2 :: 3 :: 1 :: 0 :: -1 :: 2 :: Nil&lt;br /&gt;&lt;br /&gt;       val matcher = (x : Int, y : Int) =&amp;gt; x &amp;lt; y&lt;br /&gt;&lt;br /&gt;       val sortedList = insertionSort(list1, matcher)&lt;br /&gt;&lt;br /&gt;       println("sortedList = " + sortedList.mkString(", "))&lt;br /&gt;&lt;br /&gt;       val revMatcher = (x : Int, y : Int) =&amp;gt; x &amp;gt;= y&lt;br /&gt;&lt;br /&gt;       val revSortedList = insertionSort(list1, revMatcher)&lt;br /&gt;&lt;br /&gt;       println("revSortedList = " + revSortedList.mkString(", "))&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   def insertionSort(values : List[Int], matcher : (Int, Int) =&amp;gt; Boolean) : List[int] = {&lt;br /&gt;&lt;br /&gt;       def iSort(values : List[Int]) : List[int] = {&lt;br /&gt;&lt;br /&gt;           val result = values match {&lt;br /&gt;&lt;br /&gt;               case List() =&amp;gt; List()&lt;br /&gt;&lt;br /&gt;               case value :: valuesTail =&amp;gt; insert(value, iSort(valuesTail))&lt;br /&gt;           }&lt;br /&gt;&lt;br /&gt;           println("iSort called with " + values + ", result = " + result)&lt;br /&gt;&lt;br /&gt;           result&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       def insert(value : Int, values : List[Int]) : List[Int] = {&lt;br /&gt;&lt;br /&gt;           val result = values match {&lt;br /&gt;&lt;br /&gt;               // if list is empty return new list with single element in it&lt;br /&gt;               case List() =&amp;gt; List(value)&lt;br /&gt;&lt;br /&gt;               // otherwise insert into list in order, recursively&lt;br /&gt;               case x :: xTail =&amp;gt;&lt;br /&gt;                   if (matcher(value, x)) {&lt;br /&gt;                       value :: values&lt;br /&gt;                   }&lt;br /&gt;                   else {&lt;br /&gt;                       x :: insert(value, xTail)&lt;br /&gt;                   }&lt;br /&gt;           }&lt;br /&gt;          &lt;br /&gt;           println("insert called with " + value + ", values " + values + ", result = " + result)&lt;br /&gt;&lt;br /&gt;           result&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       iSort(values)&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Results:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you run the above example code the results are as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;iSort called with List(), result = List()&lt;br /&gt;insert called with 2, values List(), result = List(2)&lt;br /&gt;iSort called with List(2), result = List(2)&lt;br /&gt;insert called with -1, values List(2), result = List(-1, 2)&lt;br /&gt;iSort called with List(-1, 2), result = List(-1, 2)&lt;br /&gt;insert called with 0, values List(2), result = List(0, 2)&lt;br /&gt;insert called with 0, values List(-1, 2), result = List(-1, 0, 2)&lt;br /&gt;iSort called with List(0, -1, 2), result = List(-1, 0, 2)&lt;br /&gt;insert called with 1, values List(2), result = List(1, 2)&lt;br /&gt;insert called with 1, values List(0, 2), result = List(0, 1, 2)&lt;br /&gt;insert called with 1, values List(-1, 0, 2), result = List(-1, 0, 1, 2)&lt;br /&gt;iSort called with List(1, 0, -1, 2), result = List(-1, 0, 1, 2)&lt;br /&gt;insert called with 3, values List(), result = List(3)&lt;br /&gt;insert called with 3, values List(2), result = List(2, 3)&lt;br /&gt;insert called with 3, values List(1, 2), result = List(1, 2, 3)&lt;br /&gt;insert called with 3, values List(0, 1, 2), result = List(0, 1, 2, 3)&lt;br /&gt;insert called with 3, values List(-1, 0, 1, 2), result = List(-1, 0, 1, 2, 3)&lt;br /&gt;iSort called with List(3, 1, 0, -1, 2), result = List(-1, 0, 1, 2, 3)&lt;br /&gt;insert called with 2, values List(3), result = List(2, 3)&lt;br /&gt;insert called with 2, values List(2, 3), result = List(2, 2, 3)&lt;br /&gt;insert called with 2, values List(1, 2, 3), result = List(1, 2, 2, 3)&lt;br /&gt;insert called with 2, values List(0, 1, 2, 3), result = List(0, 1, 2, 2, 3)&lt;br /&gt;insert called with 2, values List(-1, 0, 1, 2, 3), result = List(-1, 0, 1, 2, 2, 3)&lt;br /&gt;iSort called with List(2, 3, 1, 0, -1, 2), result = List(-1, 0, 1, 2, 2, 3)&lt;br /&gt;insert called with 5, values List(), result = List(5)&lt;br /&gt;insert called with 5, values List(3), result = List(3, 5)&lt;br /&gt;insert called with 5, values List(2, 3), result = List(2, 3, 5)&lt;br /&gt;insert called with 5, values List(2, 2, 3), result = List(2, 2, 3, 5)&lt;br /&gt;insert called with 5, values List(1, 2, 2, 3), result = List(1, 2, 2, 3, 5)&lt;br /&gt;insert called with 5, values List(0, 1, 2, 2, 3), result = List(0, 1, 2, 2, 3, 5)&lt;br /&gt;insert called with 5, values List(-1, 0, 1, 2, 2, 3), result = List(-1, 0, 1, 2, 2, 3, 5)&lt;br /&gt;iSort called with List(5, 2, 3, 1, 0, -1, 2), result = List(-1, 0, 1, 2, 2, 3, 5)&lt;br /&gt;sortedList = -1, 0, 1, 2, 2, 3, 5&lt;br /&gt;iSort called with List(), result = List()&lt;br /&gt;insert called with 2, values List(), result = List(2)&lt;br /&gt;iSort called with List(2), result = List(2)&lt;br /&gt;insert called with -1, values List(), result = List(-1)&lt;br /&gt;insert called with -1, values List(2), result = List(2, -1)&lt;br /&gt;iSort called with List(-1, 2), result = List(2, -1)&lt;br /&gt;insert called with 0, values List(-1), result = List(0, -1)&lt;br /&gt;insert called with 0, values List(2, -1), result = List(2, 0, -1)&lt;br /&gt;iSort called with List(0, -1, 2), result = List(2, 0, -1)&lt;br /&gt;insert called with 1, values List(0, -1), result = List(1, 0, -1)&lt;br /&gt;insert called with 1, values List(2, 0, -1), result = List(2, 1, 0, -1)&lt;br /&gt;iSort called with List(1, 0, -1, 2), result = List(2, 1, 0, -1)&lt;br /&gt;insert called with 3, values List(2, 1, 0, -1), result = List(3, 2, 1, 0, -1)&lt;br /&gt;iSort called with List(3, 1, 0, -1, 2), result = List(3, 2, 1, 0, -1)&lt;br /&gt;insert called with 2, values List(2, 1, 0, -1), result = List(2, 2, 1, 0, -1)&lt;br /&gt;insert called with 2, values List(3, 2, 1, 0, -1), result = List(3, 2, 2, 1, 0, -1)&lt;br /&gt;iSort called with List(2, 3, 1, 0, -1, 2), result = List(3, 2, 2, 1, 0, -1)&lt;br /&gt;insert called with 5, values List(3, 2, 2, 1, 0, -1), result = List(5, 3, 2, 2, 1, 0, -1)&lt;br /&gt;iSort called with List(5, 2, 3, 1, 0, -1, 2), result = List(5, 3, 2, 2, 1, 0, -1)&lt;br /&gt;revSortedList = 5, 3, 2, 2, 1, 0, -1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-4191983638449350636?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/4191983638449350636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=4191983638449350636' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4191983638449350636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4191983638449350636'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/01/scala-insertion-sort-and-pattern.html' title='Scala, insertion sort and pattern matching'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-7582470330297515516</id><published>2009-01-16T11:12:00.000-08:00</published><updated>2009-01-16T11:27:28.525-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='BigInt'/><category scheme='http://www.blogger.com/atom/ns#' term='Diffie-Hellman'/><title type='text'>Scala, example of Diffie-Hellman</title><content type='html'>Another in the sequence of postings on Scala by simple example, this one shows an example of Diffie-Hellman to establish a shared secret over a public communication channel without that secret being revealed. Diffie-Hellman itself is prone to man-in-the-middle attacks, this example does not attempt to deal with that problem (normally addressed with authentication of some type).&lt;br /&gt;&lt;br /&gt;The example sets up the canonical Alice and Bob, with shared public parameters g (generator) = 5 and p (prime modulus) = a large 128 random prime number.&lt;br /&gt;&lt;br /&gt;Alice and Bob each create their secret key [sk] (a large 128 random number) and generate:&lt;br /&gt;&lt;br /&gt;y = g^sk mod p&lt;br /&gt;&lt;br /&gt;Alice and Bob then swap the result of this calculation.&lt;br /&gt;&lt;br /&gt;From this, Alice and Bob both perform y^sk mod p to create a new value, the shared secret key which will be the same for both Bob and Alice even though they start with different random secret keys.&lt;br /&gt;&lt;br /&gt;This is because:&lt;br /&gt;&lt;br /&gt;(g^x)^y is the same as (g^y)^x&lt;br /&gt;&lt;br /&gt;From a Scala perspective, the interesting things to note are:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Ease of use of large integers using the BigInt class as if it were a primitive type.&lt;/li&gt;&lt;li&gt;Constructors to create immutable instances containing g, p and name.&lt;/li&gt;&lt;li&gt;Companion object to provide helper function to wrap probable prime function.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example code:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;import scala.util.Random;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;object DiffieHellmanTest {&lt;br /&gt;&lt;br /&gt;   val p = DiffieHellman.randomPrime(128)&lt;br /&gt;   val g = 5&lt;br /&gt;&lt;br /&gt;   def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;       // alice and bob initialise with the public parameters for DH, g and p&lt;br /&gt;       val alice = new DiffieHellman(g, p, "Alice")&lt;br /&gt;       val bob = new DiffieHellman(g, p, "Bob")&lt;br /&gt;&lt;br /&gt;       // alice and bob generate their own secret keys and public keys&lt;br /&gt;       alice.createSecretKey();&lt;br /&gt;       bob.createSecretKey();&lt;br /&gt;&lt;br /&gt;       val a1 = alice.getPublicKey();&lt;br /&gt;       val b1 = bob.getPublicKey();&lt;br /&gt;&lt;br /&gt;       println("a1 = " + a1)&lt;br /&gt;       println("b1 = " + b1)&lt;br /&gt;&lt;br /&gt;       // alice and bob exchange public keys&lt;br /&gt;       bob.setPeerPublicKey(a1)&lt;br /&gt;       alice.setPeerPublicKey(b1)&lt;br /&gt;&lt;br /&gt;       // alice and bob compute their shared secret key&lt;br /&gt;       val alicesk = alice.createSharedKey()&lt;br /&gt;       val bobsk = bob.createSharedKey()&lt;br /&gt;&lt;br /&gt;       println("Done, alice sk = " + alicesk + ", bob sk = " + bobsk)&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;object DiffieHellman {&lt;br /&gt;&lt;br /&gt;   def randomPrime(n : Int) : BigInt = { // return a random value with n digits&lt;br /&gt;&lt;br /&gt;       val rnd = new Random();&lt;br /&gt;&lt;br /&gt;       BigInt.probablePrime(n, rnd)&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class DiffieHellman(val g : Int, p : BigInt, name : String) {&lt;br /&gt;&lt;br /&gt;   var secretKey : BigInt = 0&lt;br /&gt;   var peerPublicKey : BigInt = 0&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   def createSecretKey() {&lt;br /&gt;&lt;br /&gt;       secretKey = random(128)&lt;br /&gt;&lt;br /&gt;       println(name + " secretKey = " + secretKey)&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   def setPeerPublicKey(x : BigInt) {&lt;br /&gt;&lt;br /&gt;       peerPublicKey = x&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   def getPublicKey() : BigInt = {&lt;br /&gt;&lt;br /&gt;       doExpMod(g, secretKey, p)&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   def random(n : Int) : BigInt = { // return a random value with n digits&lt;br /&gt;&lt;br /&gt;       val rnd = new Random();&lt;br /&gt;&lt;br /&gt;       BigInt(n, rnd)&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   def createSharedKey() : BigInt = {&lt;br /&gt;&lt;br /&gt;       doExpMod(peerPublicKey, secretKey, p)&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private def doExpMod(x : BigInt) : BigInt = {&lt;br /&gt;&lt;br /&gt;       println("doExpMod g = " + g + ", x = " + x + ", p = " + p)&lt;br /&gt;       doExpMod(g, x, p)&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private def doExpMod(g : BigInt, x : BigInt, m : BigInt) : BigInt = {&lt;br /&gt;&lt;br /&gt;       g.modPow(x, m)&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Results:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(Numbers may vary between runs of course!)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Alice secretKey = 197977683133285508684427285955258922592&lt;br /&gt;Bob secretKey = 54690551885126631242925351374829949140&lt;br /&gt;a1 = 4317900055693480003952964194026338337&lt;br /&gt;b1 = 58782279533775365647086521912939284670&lt;br /&gt;Done, alice sk = 275531174494727646906973085281579443284, bob sk = 275531174494727646906973085281579443284&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The secret keys for Alice and Bob normally wouldn't be revealed, but they've been output here for debug purposes.&lt;br /&gt;&lt;br /&gt;Note that the final shared secret key is the same for both Alice and Bob, which could then be used to establish a secure communication channel using symmetric encryption.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-7582470330297515516?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/7582470330297515516/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=7582470330297515516' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/7582470330297515516'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/7582470330297515516'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/01/scala-example-of-diffie-hellman.html' title='Scala, example of Diffie-Hellman'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-4314513642502562393</id><published>2009-01-11T05:12:00.000-08:00</published><updated>2009-01-11T12:22:20.851-08:00</updated><title type='text'>Scala, Square roots, Netwon's method, closures and foldLeft</title><content type='html'>A simple Scala example. This one computes square roots by successive approximation using Newton's method, defined in a class &lt;span style="font-style: italic;"&gt;SquareRoot&lt;/span&gt;. A companion object is also used to define the precision constant, the target tolerance we'll use to decide when to stop approximating.&lt;br /&gt;&lt;br /&gt;There are two version of the function. &lt;span style="font-style: italic;"&gt;squareRootSimple &lt;/span&gt;is a simple implementation. The method &lt;span style="font-style: italic;"&gt;squareRoot&lt;/span&gt; improves on this by refactoring the code to use a closure to capture x, the value for which we are finding the square root. Also, the overloaded average function takes a List and uses &lt;span style="font-family:courier new;"&gt;list.foldLeft(0.0).(_ + _)&lt;/span&gt; which means apply x+y to list element pairs, starting with 0.0, running through all the elements in the list, thus summing all the elements.&lt;br /&gt;&lt;br /&gt;Example of the use of foldLeft:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;list.foldLeft(0.0).(_ + _)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Which could also be written as:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;(start /: list)(_ + _)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;/: is the foldLeft operator, equivalent to the .foldLeft method on a list&lt;/li&gt;&lt;li&gt;\: is the foldRight operator, equivalent to the .foldRight method on a list&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The fold operator is like a pattern that crops up fairly often in imperative programming, it looks something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="java"&gt;B b &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; startItem&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;for&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;final&lt;/span&gt; T a &lt;span style="color: rgb(51, 153, 51);"&gt;:&lt;/span&gt; listOfT&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt; &lt;span style="color: rgb(0, 153, 0);"&gt;{&lt;/span&gt;&lt;br /&gt; b &lt;span style="color: rgb(51, 153, 51);"&gt;=&lt;/span&gt; method&lt;span style="color: rgb(0, 153, 0);"&gt;(&lt;/span&gt;b, a&lt;span style="color: rgb(0, 153, 0);"&gt;)&lt;/span&gt;&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;return&lt;/span&gt; b&lt;span style="color: rgb(51, 153, 51);"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example code:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;object SquareRootsTest {&lt;br /&gt;&lt;br /&gt;    def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;        val squareRoot = new SquareRoot()&lt;br /&gt;&lt;br /&gt;        assert(((squareRoot.squareRoot(9) - 3) abs) &lt; SquareRoot.precision)&lt;br /&gt;        assert(((squareRoot.squareRoot(64) - 8) abs) &lt; SquareRoot.precision)&lt;br /&gt;&lt;br /&gt;        val res1 = squareRoot.squareRoot(842)&lt;br /&gt;        println("square root of 842 = " + res1 + ", " + res1 + " squared = " + res1 * res1)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;object SquareRoot {&lt;br /&gt;&lt;br /&gt;    val precision = 0.000001&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class SquareRoot {&lt;br /&gt;&lt;br /&gt;    def squareRootSimple(x : Double) : Double = (&lt;br /&gt;&lt;br /&gt;        squareRootIter(1.0, x)&lt;br /&gt;    )&lt;br /&gt;&lt;br /&gt;    def squareRootIter(guess : Double, x : Double) : Double = {&lt;br /&gt;&lt;br /&gt;        if (goodEnough(guess, x)) {&lt;br /&gt;          guess&lt;br /&gt;        }&lt;br /&gt;        else {&lt;br /&gt;          squareRootIter(improveGuess(guess, x), x)&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private def improveGuess(guess : Double, x : Double) : Double = {&lt;br /&gt;&lt;br /&gt;        val newguess = average(guess, x / guess)&lt;br /&gt;        println("guess for x " + x + " improved to = " + newguess)&lt;br /&gt;        newguess&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private def goodEnough(guess : Double, x : Double) = {&lt;br /&gt;&lt;br /&gt;        (square(guess) - x).abs  &lt; SquareRoot.precision&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def squareRoot(x : Double) : Double = {&lt;br /&gt;&lt;br /&gt;        def squareRootIter(guess : Double, x : Double) : Double = {&lt;br /&gt;&lt;br /&gt;            if (goodEnough(guess)) {&lt;br /&gt;              guess&lt;br /&gt;            }&lt;br /&gt;            else {&lt;br /&gt;              squareRootIter(improveGuess(guess), x)&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        def improveGuess(guess : Double) : Double = {&lt;br /&gt;&lt;br /&gt;            val newguess = average(List(guess, x / guess))&lt;br /&gt;            println("guess for x " + x + " improved to = " + newguess)&lt;br /&gt;            newguess&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        def goodEnough(guess : Double) = {&lt;br /&gt;&lt;br /&gt;            (square(guess) - x).abs  &lt; SquareRoot.precision&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        squareRootIter(1.0, x)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private def average(x : Double, y : Double) : Double = {&lt;br /&gt;&lt;br /&gt;        (x + y) / 2&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private def average(list : List[Double]) : Double = {&lt;br /&gt;&lt;br /&gt;        //println("value = " + list.mkString)&lt;br /&gt;        //(0.0 /: list)(_ + _) / list.size&lt;br /&gt;        list.foldLeft(0.0)(_ + _) / list.size&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private def square(value : Double) : Double = {&lt;br /&gt;&lt;br /&gt;        value * value&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Results:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;guess for x 9.0 improved to = 5.0&lt;br /&gt;guess for x 9.0 improved to = 3.4&lt;br /&gt;guess for x 9.0 improved to = 3.023529411764706&lt;br /&gt;guess for x 9.0 improved to = 3.00009155413138&lt;br /&gt;guess for x 9.0 improved to = 3.000000001396984&lt;br /&gt;guess for x 64.0 improved to = 32.5&lt;br /&gt;guess for x 64.0 improved to = 17.234615384615385&lt;br /&gt;guess for x 64.0 improved to = 10.474036101145005&lt;br /&gt;guess for x 64.0 improved to = 8.292191785986859&lt;br /&gt;guess for x 64.0 improved to = 8.005147977880979&lt;br /&gt;guess for x 64.0 improved to = 8.000001655289593&lt;br /&gt;guess for x 64.0 improved to = 8.00000000000017&lt;br /&gt;guess for x 842.0 improved to = 421.5&lt;br /&gt;guess for x 842.0 improved to = 211.7488137603796&lt;br /&gt;guess for x 842.0 improved to = 107.86261164282149&lt;br /&gt;guess for x 842.0 improved to = 57.83441917633403&lt;br /&gt;guess for x 842.0 improved to = 36.19661181949908&lt;br /&gt;guess for x 842.0 improved to = 29.729228773452704&lt;br /&gt;guess for x 842.0 improved to = 29.025762097895374&lt;br /&gt;guess for x 842.0 improved to = 29.017237509256656&lt;br /&gt;guess for x 842.0 improved to = 29.017236257093842&lt;br /&gt;square root of 842 = 29.017236257093842, 29.017236257093842 squared = 842.0000000000015&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Source Scheme Code:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define (sqrt-iter guess x)&lt;br /&gt;(if (good-enough? guess x)&lt;br /&gt;guess&lt;br /&gt;(sqrt-iter (improve guess x)&lt;br /&gt;x)))&lt;br /&gt;A guess is improved by averaging it with the quotient of the radicand and the old guess:&lt;br /&gt;(define (improve guess x)&lt;br /&gt;(average guess (/ x guess)))&lt;br /&gt;where&lt;br /&gt;(define (average x y)&lt;br /&gt;(/ (+ x y) 2))&lt;br /&gt;We also have to say what we mean by ``good enough.'' The following will do for illustration, but it is not&lt;br /&gt;really a very good test. (See exercise 1.7.) The idea is to improve the answer until it is close enough so that&lt;br /&gt;its square differs from the radicand by less than a predetermined tolerance (here 0.001):22&lt;br /&gt;(define (good-enough? guess x)&lt;br /&gt;(&lt; (abs (- (square guess) x)) 0.001)) &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;References:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Blog about fold Left: &lt;a href="http://blog.tmorris.net/scalalistfoldleft-for-java-programmers/"&gt;http://blog.tmorris.net/scalalistfoldleft-for-java-programmers/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-4314513642502562393?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/4314513642502562393/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=4314513642502562393' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4314513642502562393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4314513642502562393'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/01/scala-square-roots-netwons-method.html' title='Scala, Square roots, Netwon&apos;s method, closures and foldLeft'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-8568174540534818891</id><published>2009-01-10T10:27:00.000-08:00</published><updated>2009-06-20T10:06:56.177-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='zipWithIndex'/><category scheme='http://www.blogger.com/atom/ns#' term='scala for'/><category scheme='http://www.blogger.com/atom/ns#' term='for comprehensions'/><category scheme='http://www.blogger.com/atom/ns#' term='scala for comprehesions'/><title type='text'>Scala, for comprehensions</title><content type='html'>This post contains some examples of Scala's &lt;span style="font-weight: bold;"&gt;for comprehension&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;A for loop in Scala can be written in the imperative style and will behave rather much the same as a Java for loop, especially the enhanced Java for loop from Java 5.0.&lt;br /&gt;&lt;br /&gt;However, this type of simple imperative looping doesn't touch on the power and flexibility of Scala's for comprehension, when used as used in a functional programming context.&lt;br /&gt;&lt;br /&gt;In particular, some of the key differences are:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A for comprehension can be a value itself. The value is a product of the &lt;span style="font-weight: bold; font-style: italic;"&gt;yield &lt;/span&gt;statement used within the expression body. Since a for comprehension iterates over a list or sequence, the resulting value of a for comprehension is typically a list too.&lt;/li&gt;&lt;li&gt;A for comprehension uses a &lt;span style="font-weight: bold; font-style: italic;"&gt;generator&lt;/span&gt;, written in the form &lt;span style="font-family:courier new;"&gt;item &lt;- listOfItems&lt;/span&gt; to define the items to be iterated over &lt;/li&gt;&lt;li&gt;Multiple generators may be used, somewhat analogous to a nested for loop within a for loop in imperative programming&lt;/li&gt;&lt;li&gt;In addition to generators, a &lt;span style="font-weight: bold; font-style: italic;"&gt;guard &lt;/span&gt;can be used to filter or restrict the values&lt;/li&gt;&lt;li&gt;The for syntax can use parenthesis with semicolon delimited generators and guards or braces - both are equivalent&lt;/li&gt;&lt;li&gt;The iterations my differ when compared to a seeming equivalent imperative construct, because the implementation is fundamentally different. In particular the list of items to be used is determined using the generator(s) and guard(s) before the body is run, so for example flags used in guards that are modified in the body may not produce the expected result (from an imperative perspective).&lt;/li&gt;&lt;li&gt;Generators can be "&lt;span style="font-weight: bold; font-style: italic;"&gt;projected&lt;/span&gt;" using the .project function.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Examples of Scala for comprehension:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;object ForComprehensionTest {&lt;br /&gt;    def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;        // create a couple of simple lists...&lt;br /&gt;        val list1 = &amp;quot;Apples&amp;quot; :: &amp;quot;Oranges&amp;quot; :: &amp;quot;Bananas&amp;quot; :: &amp;quot;Avocados&amp;quot; :: Nil&lt;br /&gt;        val list2 = 11 :: 22 :: 33 :: 44 :: 55 :: 66 :: Nil&lt;br /&gt;&lt;br /&gt;        // simple comprehension with one generator and guard&lt;br /&gt;        val res1 = for(item1 &amp;lt;- list1 if item1.startsWith(&amp;quot;A&amp;quot;))&lt;br /&gt;            yield item1&lt;br /&gt;&lt;br /&gt;        assert(res1 == List(&amp;quot;Apples&amp;quot;, &amp;quot;Avocados&amp;quot;))&lt;br /&gt;        res1.foreach(println);&lt;br /&gt;&lt;br /&gt;        // more complex comprehension, two generators within {brace} syntax with two guards&lt;br /&gt;        val res2 = for {&lt;br /&gt;                item1 &amp;lt;- list1 if item1.startsWith(&amp;quot;A&amp;quot;)&lt;br /&gt;                item2 &amp;lt;- list2 if item2 % 3 == 0&lt;br /&gt;            }&lt;br /&gt;            yield item2 + &amp;quot; &amp;quot; + item1&lt;br /&gt;&lt;br /&gt;        assert(res2 == List(&amp;quot;33 Apples&amp;quot;, &amp;quot;66 Apples&amp;quot;, &amp;quot;33 Avocados&amp;quot;, &amp;quot;66 Avocados&amp;quot;))&lt;br /&gt;        res2.foreach(println);&lt;br /&gt;&lt;br /&gt;        // as above but using () parens and ; semi-colon syntax instead&lt;br /&gt;        val res3 = for ( item1 &amp;lt;- list1 if item1.startsWith(&amp;quot;A&amp;quot;);&lt;br /&gt;                        item2 &amp;lt;- list2 if item2 % 3 == 0 )&lt;br /&gt;            yield item2 + &amp;quot; &amp;quot; + item1&lt;br /&gt;&lt;br /&gt;        assert(res3 == List(&amp;quot;33 Apples&amp;quot;, &amp;quot;66 Apples&amp;quot;, &amp;quot;33 Avocados&amp;quot;, &amp;quot;66 Avocados&amp;quot;))&lt;br /&gt;        res3.foreach(println);&lt;br /&gt;&lt;br /&gt;        println(&amp;quot;simple guard item == 22&amp;quot;)&lt;br /&gt;        for (item &amp;lt;- list2 if item == 22) println(item)&lt;br /&gt;&lt;br /&gt;        println(&amp;quot;simple comprehension mkString = &amp;quot; + (for (item &amp;lt;- list2 if item % 2 == 0) yield item).mkString)&lt;br /&gt;&lt;br /&gt;        // from an imperative / Java perspective you might expect this to stop with item = 22&lt;br /&gt;        // but it continues on because !found is evaluated as always true (irrefutable pattern) when determining what to iterate over&lt;br /&gt;        var found = false&lt;br /&gt;        for (item &amp;lt;- list2 if !found) {&lt;br /&gt;&lt;br /&gt;            if (item == 22)&lt;br /&gt;                found = true&lt;br /&gt;&lt;br /&gt;            println(&amp;quot;without projection, item == 22? item = &amp;quot; + item)&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // with the .projection call, it works more like you might expect from an imperative perspective&lt;br /&gt;        found = false&lt;br /&gt;        for (item &amp;lt;- list2.projection if !found) {&lt;br /&gt;&lt;br /&gt;            if (item == 22)&lt;br /&gt;                found = true&lt;br /&gt;&lt;br /&gt;            println(&amp;quot;with .projection, item==22? item = &amp;quot; + item)&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        found = false&lt;br /&gt;        for (item &amp;lt;- list2.projection.takeWhile(item =&amp;gt; !found)) {&lt;br /&gt;&lt;br /&gt;            if (item == 22)&lt;br /&gt;                found = true&lt;br /&gt;&lt;br /&gt;            println(&amp;quot;.projection.takeWhile(item =&amp;gt; ! found) = &amp;quot; + item)&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Results:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Apples&lt;br /&gt;Avocados&lt;br /&gt;33 Apples&lt;br /&gt;66 Apples&lt;br /&gt;33 Avocados&lt;br /&gt;66 Avocados&lt;br /&gt;33 Apples&lt;br /&gt;66 Apples&lt;br /&gt;33 Avocados&lt;br /&gt;66 Avocados&lt;br /&gt;simple guard item == 22&lt;br /&gt;22&lt;br /&gt;simple comprehension mkString = 224466&lt;br /&gt;without projection, item == 22? item = 11&lt;br /&gt;without projection, item == 22? item = 22&lt;br /&gt;without projection, item == 22? item = 33&lt;br /&gt;without projection, item == 22? item = 44&lt;br /&gt;without projection, item == 22? item = 55&lt;br /&gt;without projection, item == 22? item = 66&lt;br /&gt;with .projection, item==22? item = 11&lt;br /&gt;with .projection, item==22? item = 22&lt;br /&gt;.projection.takeWhile(item =&gt; ! found) = 11&lt;br /&gt;.projection.takeWhile(item =&gt; ! found) = 22&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Other useful things to know:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In a for comprehension if you want to iterate over a collection you can create a &lt;span style="font-style: italic;"&gt;tuple&lt;/span&gt; of (element, index) pairs using syntax of the form:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;for ((elem, index) &lt;- iter.zipWithIndex) {&lt;br /&gt;    // now we can access element of each iteration along with its associated numerical index!&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Resources:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A good explanation of for comprehensions can be found here &lt;a href="http://creativekarma.com/ee.php/weblog/comments/the_scala_for_comprehension_from_a_java_perspective/"&gt;http://creativekarma.com/ee.php/weblog/comments/the_scala_for_comprehension_from_a_java_perspective/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-8568174540534818891?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/8568174540534818891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=8568174540534818891' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8568174540534818891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8568174540534818891'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/01/scala-for-comprehensions.html' title='Scala, for comprehensions'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-6371794181292069449</id><published>2009-01-08T11:20:00.000-08:00</published><updated>2009-01-08T11:46:25.688-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ZFS'/><category scheme='http://www.blogger.com/atom/ns#' term='Open Solaris'/><category scheme='http://www.blogger.com/atom/ns#' term='2008.11'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenSolaris'/><category scheme='http://www.blogger.com/atom/ns#' term='Zones'/><title type='text'>OpenSolaris - ZFS and Zones</title><content type='html'>Today, just a quick note on setting up an &lt;span style="font-weight: bold; font-style: italic;"&gt;OpenSolaris &lt;/span&gt;10 system &lt;span style="font-weight: bold; font-style: italic;"&gt;local zone&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Firstly, you need to ensure there's a suitable &lt;span style="font-weight: bold;"&gt;ZFS&lt;/span&gt; file system created for the zone, then you define and install the zone itself. The basic steps are quite simple, here's a basic example as a starter:&lt;br /&gt;&lt;br /&gt;Note: Global zone means the default zone, the basic machine assuming no zones have been created yet. Local zone is a created zone within the global zone, as described here.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As root on the global zone:&lt;br /&gt;&lt;br /&gt;Take a look at available pools:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# rpool list&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;On my system, with one disk fully used, I have rpool already, but no other pools.&lt;br /&gt;&lt;br /&gt;Creating a new ZFS filesystem under rpool as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# zfs create /rpool/zones&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now create a new zone configuration, here is a really basic minimal zone config with networking, taken from the zone FAQ.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# zonecfg -z my-zone&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# zonecfg:my-zone&gt; create&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# zonecfg:my-zone&gt; set zonepath=/zones/zone_roots/my-zone&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# zonecfg:my-zone&gt; add net&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# zonecfg:my-zone:net&gt; set address=10.1.1.1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# zonecfg:my-zone:net&gt; set physical=hm0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# zonecfg:my-zone:net&gt; end&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# zonecfg:my-zone&gt; commit&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# zonecfg:my-zone&gt; exit&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Install the zone (if this fails, check permissions, shown as *1 below)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# zoneadm -z my-zone install&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;Boot the installation!&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;global# zoneadm -z my-zone boot&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Login to the new zone:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;global# zlogin -C my-zone&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;*1 change permissions on the dataset if necessary&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# chown root /rpool/zones/my-zone&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;global# chmod 700 /rpool/zones/my-zone&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A more complete zone configuration, for reference:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;create -b&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set zonepath=/zones/dev1&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set autoboot=true&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;add inherit-pkg-dir&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set dir=/lib&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;add inherit-pkg-dir&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set dir=/platform&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;add inherit-pkg-dir&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set dir=/sbin&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;add inherit-pkg-dir&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set dir=/usr&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;add inherit-pkg-dir&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set dir=/opt/apache22&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;add inherit-pkg-dir&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set dir=/opt/csw&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;add inherit-pkg-dir&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set dir=/opt/mysql5&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;add inherit-pkg-dir&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set dir=/opt/pgsql829&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;add inherit-pkg-dir&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set dir=/opt/php5&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;add fs&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set dir=/opt/SUNWspro&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set special=/opt/SUNWspro&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set type=lofs&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;add options ro&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;add net&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set address=10.80.117.152&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;set physical=bge0&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Resources:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;ZFS: &lt;a href="http://www.linuxdynasty.org/zfs-howto-howto-create-a-zfs-file-system.html"&gt;http://www.linuxdynasty.org/zfs-howto-howto-create-a-zfs-file-system.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Zones: &lt;a href="http://opensolaris.org/os/community/zones/faq/#sa_create"&gt;http://opensolaris.org/os/community/zones/faq/#sa_create&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-6371794181292069449?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/6371794181292069449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=6371794181292069449' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6371794181292069449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6371794181292069449'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/01/opensolaris-zfs-and-zones.html' title='OpenSolaris - ZFS and Zones'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-1723280548980208640</id><published>2009-01-05T13:43:00.000-08:00</published><updated>2009-01-07T11:15:35.933-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='traits and mixins'/><title type='text'>Scala, traits and mix-ins</title><content type='html'>Continuing on in the series of Scala blogs, showing Scala features by example, this post attempts to show the operation of &lt;span style="font-weight: bold;"&gt;Traits&lt;/span&gt;. Traits are rather like classes but designed to allow rich feature composition by allowing "mix-in" of required traits dynamically, at run time. Traits achieve what can look like multiple inheritance, without the pitfalls and limitations of multiple inheritance. Conversely then, you might think traits are equivalent to Java's interfaces. Whist similar, the key difference is that traits can (and usually do) contain implementations (method bodies). When a trait method implementation makes a call to &lt;span style="font-style: italic;"&gt;super&lt;/span&gt;, it is dynamically resolved as the class is &lt;span style="font-style: italic;"&gt;linearised&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;When traits are combined with classes to create extended behaviour, this process is known as &lt;span style="font-style: italic;"&gt;mixin&lt;/span&gt; and the traits are said to be mixed-in or mixins.&lt;br /&gt;&lt;br /&gt;The example below shows the behaviour of the plain traits class using its &lt;span style="font-style: italic;"&gt;putMsg &lt;/span&gt;method, and then its behaviour when mixed-in with &lt;span style="font-style: italic;"&gt;TraitAddA&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;TraitAddA&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;TraitAddB&lt;/span&gt; and then with &lt;span style="font-style: italic;"&gt;TraitAddA&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;TraitAddB&lt;/span&gt; reversed (ordering of the with parts is significant).&lt;br /&gt;&lt;br /&gt;As well as mixin with the new keyword, class &lt;span style="font-style: italic;"&gt;TraitABClass &lt;/span&gt;shows that traits can be used as mixins with normal classes too, at the point they are declared using the with keyword.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example Scala file showing the operation of &lt;/span&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;Traits&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;object TraitsTest {&lt;br /&gt;&lt;br /&gt;  def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;    val traits : Traits = new Traits()&lt;br /&gt;&lt;br /&gt;    traits.putMsg("Hello!")&lt;br /&gt;&lt;br /&gt;    println("traits, value = " + traits.toString)&lt;br /&gt;&lt;br /&gt;    val traitsA : Traits = new Traits() with TraitAddA&lt;br /&gt;&lt;br /&gt;    traitsA.putMsg("Hello!")&lt;br /&gt;    &lt;br /&gt;    println("traitsA, value = " + traitsA.toString)&lt;br /&gt;&lt;br /&gt;    val traitsAB : Traits = new Traits() with TraitAddA with TraitAddB&lt;br /&gt;&lt;br /&gt;    traitsAB.putMsg("Hello!")&lt;br /&gt;&lt;br /&gt;    println("traitsAB, value = " + traitsAB.toString)&lt;br /&gt;&lt;br /&gt;    val traitsBA : Traits = new Traits() with TraitAddB with TraitAddA&lt;br /&gt;&lt;br /&gt;    traitsBA.putMsg("Hello!")&lt;br /&gt;&lt;br /&gt;    println("traitsBA, value = " + traitsBA.toString)&lt;br /&gt;&lt;br /&gt;    val traitsABClass : TraitsABClass = new TraitsABClass&lt;br /&gt;&lt;br /&gt;    traitsABClass.putMsg("Hello2")&lt;br /&gt;&lt;br /&gt;    println("traitsABClass, value = " + traitsABClass.toString)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class TraitsABClass extends Traits with TraitAddA with TraitAddB&lt;br /&gt;&lt;br /&gt;class Traits {&lt;br /&gt;&lt;br /&gt;  var msg : String = ""&lt;br /&gt;&lt;br /&gt;  def putMsg(m : String) {&lt;br /&gt;&lt;br /&gt;    msg = m&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  override def toString = {&lt;br /&gt;&lt;br /&gt;    msg&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;trait TraitAddA extends Traits {&lt;br /&gt;&lt;br /&gt;  abstract override def putMsg(m : String) = {&lt;br /&gt;&lt;br /&gt;    super.putMsg("A" + m)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;trait TraitAddB extends Traits {&lt;br /&gt;&lt;br /&gt;  abstract override def putMsg(m : String) = {&lt;br /&gt;&lt;br /&gt;    super.putMsg("B" + m)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Program execution results:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;traits, value = Hello!&lt;br /&gt;traitsA, value = AHello!&lt;br /&gt;traitsAB, value = ABHello!&lt;br /&gt;traitsBA, value = BAHello!&lt;br /&gt;traitsABClass, value = ABHello2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-1723280548980208640?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/1723280548980208640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=1723280548980208640' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/1723280548980208640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/1723280548980208640'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/01/scala-traits-and-mix-ins.html' title='Scala, traits and mix-ins'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-7508219527971408186</id><published>2009-01-04T10:56:00.000-08:00</published><updated>2009-01-04T11:08:28.679-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='Modular exponentiation'/><title type='text'>Modular exponentiation</title><content type='html'>For any inquisitive minds, the fast Modular exponentiation used in the last post (Scala example) might at first glance seem odd, perhaps.&lt;br /&gt;&lt;br /&gt;What we want to achieve is &lt;span style="font-weight: bold;"&gt;x = b^n mod m&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;where b^n is performed first, the result in then operated on by mod m. Mathematically this is what we are doing, this is what we want to achieve.&lt;br /&gt;&lt;br /&gt;However, the &lt;span style="font-style: italic; font-family: courier new;"&gt;expmod &lt;/span&gt;function computes the value recursively, applying mod at each step of recursion (on each recursion result).&lt;br /&gt;&lt;br /&gt;This is in fact a better way to approach the problem, as the intermediate values are kept small (between 0 and m-1) rather than growing exponentially (with potential overflow/performance problems), only to be operated on by modulus to shrink the value back down again!&lt;br /&gt;&lt;br /&gt;Here is a simple Scala snippet that compares &lt;span style="font-family: courier new;"&gt;expMod &lt;/span&gt;with &lt;span style="font-family: courier new;"&gt;fastExp mod m&lt;/span&gt;, with some debugging added to show the intermediate values at each stage of recursion.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;import java.util.Random;&lt;br /&gt;&lt;br /&gt;object ExpTest {&lt;br /&gt;&lt;br /&gt; def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;   println("fastExpt(4, 7) % 9) = " + fastExpt(4, 7) % 9)&lt;br /&gt;   println("expMod(4, 7, 9) = " + expMod(4, 7, 9))&lt;br /&gt;&lt;br /&gt;   println("fastExpt(5, 12) % 6) = " + fastExpt(5, 12) % 6)&lt;br /&gt;   println("expMod(5, 12, 6) = " + expMod(5, 12, 6))&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt; def expMod(base : Int, exp : Int, m : Int) : Int = {&lt;br /&gt;&lt;br /&gt;   val res = if (exp == 0)&lt;br /&gt;     1&lt;br /&gt;   else if (even(exp))&lt;br /&gt;     remainder(square(expMod(base, (exp / 2), m)), m)&lt;br /&gt;   else&lt;br /&gt;     remainder(base * expMod(base, exp - 1, m), m)&lt;br /&gt;&lt;br /&gt;   println("expMod: b = " + base + ", exp = " + exp + ", m = " + m + ", res = " + res)&lt;br /&gt;   res&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def fastExpt(b : Int,  exp : Int) : Int = {&lt;br /&gt;&lt;br /&gt;   val res = if (exp == 0)&lt;br /&gt;     1&lt;br /&gt;   else if (even(exp))&lt;br /&gt;     square(fastExpt(b, exp / 2))&lt;br /&gt;   else&lt;br /&gt;     b * fastExpt(b, exp - 1)&lt;br /&gt;&lt;br /&gt;   println("fastExpt: b = " + b + ", exp = " + exp + ", res = " + res)&lt;br /&gt;   res&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def square(n : Int) : Int = {&lt;br /&gt;&lt;br /&gt;   n * n&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def even(n : Int) : Boolean = {&lt;br /&gt;&lt;br /&gt;   remainder(n, 2) == 0&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def remainder(n : Int, d : Int) : Int = {&lt;br /&gt;&lt;br /&gt;     n % d&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Results are as follows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;fastExpt: b = 4, exp = 0, res = 1&lt;br /&gt;fastExpt: b = 4, exp = 1, res = 4&lt;br /&gt;fastExpt: b = 4, exp = 2, res = 16&lt;br /&gt;fastExpt: b = 4, exp = 3, res = 64&lt;br /&gt;fastExpt: b = 4, exp = 6, res = 4096&lt;br /&gt;fastExpt: b = 4, exp = 7, res = 16384&lt;br /&gt;fastExpt(4, 7) % 9) = 4&lt;br /&gt;expMod: b = 4, exp = 0, m = 9, res = 1&lt;br /&gt;expMod: b = 4, exp = 1, m = 9, res = 4&lt;br /&gt;expMod: b = 4, exp = 2, m = 9, res = 7&lt;br /&gt;expMod: b = 4, exp = 3, m = 9, res = 1&lt;br /&gt;expMod: b = 4, exp = 6, m = 9, res = 1&lt;br /&gt;expMod: b = 4, exp = 7, m = 9, res = 4&lt;br /&gt;expMod(4, 7, 9) = 4&lt;br /&gt;fastExpt: b = 5, exp = 0, res = 1&lt;br /&gt;fastExpt: b = 5, exp = 1, res = 5&lt;br /&gt;fastExpt: b = 5, exp = 2, res = 25&lt;br /&gt;fastExpt: b = 5, exp = 3, res = 125&lt;br /&gt;fastExpt: b = 5, exp = 6, res = 15625&lt;br /&gt;fastExpt: b = 5, exp = 12, res = 244140625&lt;br /&gt;fastExpt(5, 12) % 6) = 1&lt;br /&gt;expMod: b = 5, exp = 0, m = 6, res = 1&lt;br /&gt;expMod: b = 5, exp = 1, m = 6, res = 5&lt;br /&gt;expMod: b = 5, exp = 2, m = 6, res = 1&lt;br /&gt;expMod: b = 5, exp = 3, m = 6, res = 5&lt;br /&gt;expMod: b = 5, exp = 6, m = 6, res = 1&lt;br /&gt;expMod: b = 5, exp = 12, m = 6, res = 1&lt;br /&gt;expMod(5, 12, 6) = 1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Most importantly, the functions yield the same results, but expMod achieves it in a more efficient and scalable way.&lt;br /&gt;&lt;br /&gt;Just a small posting, as whilst appearing simple, modular exponentiation underpins much of modern cryptographic methods, and efficient algorithms are important.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-7508219527971408186?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/7508219527971408186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=7508219527971408186' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/7508219527971408186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/7508219527971408186'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/01/modular-exponentiation.html' title='Modular exponentiation'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-759502063327147877</id><published>2009-01-03T04:11:00.000-08:00</published><updated>2009-01-04T05:11:07.357-08:00</updated><title type='text'>Scala, Fermat's little theorem</title><content type='html'>Today, another Scala posting by way of example, using the interesting &lt;span style="font-weight: bold;"&gt;Fermat's Little Theorem&lt;/span&gt; test for primality. This is a probabilistic test that provides no false negatives (if a number is found not prime,  that is certain) but can provide false positives (a number indicated as prime is not certain to be so). The test can be run a number of times with a different base value (a) to gain increasing confidence that the number is prime.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;Fermat's Little Theorem:&lt;/span&gt; If n is a prime number and a is any positive integer less than n, then a raised to the nth power is congruent to a modulo n.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are a small set of special numbers that "fool" this test, these are the &lt;span style="font-weight: bold;"&gt;Carmichael&lt;/span&gt; numbers. Further details can be found here &lt;a href="http://en.wikipedia.org/wiki/Carmichael_number"&gt;http://en.wikipedia.org/wiki/Carmichael_number&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Carmichael numbers are extremely rare. There are only 255 Carmichael numbers below 100,000,000. The smallest few are 561, 1105, 1729, 2465, 2821, and 6601.&lt;br /&gt;&lt;br /&gt;Because the Carmichael numbers are a special subset of the Fermat prime numbers that satisfy the same condition, they can be known as &lt;b&gt;absolute Fermat pseudoprimes&lt;/b&gt;. The Fermat "primes" can be known as Fermat &lt;a href="http://en.wikipedia.org/wiki/Pseudoprime" title="Pseudoprime"&gt;pseudoprimes&lt;/a&gt;. If we remove the &lt;b&gt;absolute Fermat pseudoprimes&lt;/b&gt; from the Fermat Pseudoprimes then we end up with the absolute primes.&lt;br /&gt;&lt;br /&gt;There are revised versions of this test that remove the false positive Carmichael numbers, such as the famous Miller-Rabin test (Miller 1976, Rabin 1980). This starts from an alternate form of Fermat's Little Theorem, which states that if n is a prime number and a is any positive integer less than n, then a raised to the (n - 1)st power is congruent to 1 modulo n.&lt;br /&gt;&lt;br /&gt;For this Scala example, I'm only using the original Fermat's Little Theorem. Here is the Scala file, the main contains a number of test cases.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import java.util.Random;&lt;br /&gt;&lt;br /&gt;object FermatsLittleTheorem {&lt;br /&gt;&lt;br /&gt; def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;   val attempts = 10;  // the number of attempts, higher numbers give greater confidence in positive results.&lt;br /&gt;&lt;br /&gt;   var n = 17;&lt;br /&gt;   println("result1: n = " + n + ", res = " + fastPrime(n, attempts))  // should be true&lt;br /&gt;   n = 13&lt;br /&gt;   println("result2: n = " + n + ", res = " + fastPrime(n, attempts))  // should be true&lt;br /&gt;   n = 11&lt;br /&gt;   println("result3: n = " + n + ", res = " + fastPrime(n, attempts))  // should be true&lt;br /&gt;   n = 9&lt;br /&gt;   println("result4: n = " + n + ", res = " + fastPrime(n, attempts))  // should be false&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def fastPrime(n : Int, times : Int) : Boolean = {&lt;br /&gt;&lt;br /&gt;   if (times == 0)&lt;br /&gt;     true&lt;br /&gt;   else&lt;br /&gt;     if (fermatTest(n)) fastPrime(n, times - 1) else false&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def expmod(base : Int, exp : Int, m : Int) : Int = {&lt;br /&gt;&lt;br /&gt;   if (exp == 0)&lt;br /&gt;     1&lt;br /&gt;   else if (even(exp))&lt;br /&gt;     remainder(square(expmod(base, (exp / 2), m)), m)&lt;br /&gt;   else&lt;br /&gt;     remainder(base * expmod(base, exp - 1, m), m)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def square(n : Int) : Int = {&lt;br /&gt;&lt;br /&gt;   n * n&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def even(n : Int) : Boolean = {&lt;br /&gt;&lt;br /&gt;   remainder(n, 2) == 0&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def remainder(n : Int, d : Int) : Int = {&lt;br /&gt;&lt;br /&gt;     n % d&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def fermatTest(n : Int) : Boolean = {&lt;br /&gt;&lt;br /&gt;   def tryIt(a : Int) : Boolean = {&lt;br /&gt;&lt;br /&gt;     val res = expmod(a, n, n)&lt;br /&gt;     println("res = " + res + ", a = " + a + ", n = " + n + ", a % n = " + a % n)&lt;br /&gt;     res == a % n&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   tryIt(random(n - 1) + 1)    // get a random int between 1 and n&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; def random(n : Int) : Int = { // return a random value between 0 and n - 1&lt;br /&gt;&lt;br /&gt;   val random = new Random();&lt;br /&gt;&lt;br /&gt;   random.nextInt(n);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This was refactored from the following Scheme code, as an exercise in Scala:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define (expmod base exp m)&lt;br /&gt; (cond ((= exp 0) 1)&lt;br /&gt;   ((even? exp)&lt;br /&gt;    (remainder (square (expmod base (/ exp 2) m))&lt;br /&gt;      m))&lt;br /&gt;   (else&lt;br /&gt;     (remainder (* base (expmod base (- exp 1) m))&lt;br /&gt;      m))))&lt;br /&gt;&lt;br /&gt; (define (even? n)&lt;br /&gt;   (= (remainder n 2) 0))&lt;br /&gt;&lt;br /&gt; (define (fermat-test n)&lt;br /&gt;   (define (try-it a)&lt;br /&gt;     (= (expmod a n n) a))&lt;br /&gt;     (try-it (+ 1 (random (- n 1)))))&lt;br /&gt;&lt;br /&gt; (define (fast-prime? n times)&lt;br /&gt;   (cond ((= times 0) true)&lt;br /&gt;     ((fermat-test n) (fast-prime? n (- times 1)))&lt;br /&gt;   (else false)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A note of the tail recursiveness of the function &lt;span style="font-weight:bold;"&gt;fastPrime&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;Comment (summary) from PaulP from #scala:&lt;br /&gt;&lt;br /&gt;"It's not tail recursive but only for one reason. It's neither final nor private. It just needs to be able to determine it won't be overridden. It'd be tailrec if in an object.&lt;br /&gt;&lt;br /&gt;There has also been discussion of a @tailrec annotation so you could get a compiler warning if a tagged function wasn't compiled tailrec as you'd thought."&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-759502063327147877?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/759502063327147877/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=759502063327147877' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/759502063327147877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/759502063327147877'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/01/scala-fermats-little-theorem.html' title='Scala, Fermat&apos;s little theorem'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-150332309312111726</id><published>2009-01-02T07:22:00.000-08:00</published><updated>2009-01-02T07:36:55.621-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='placeholders'/><category scheme='http://www.blogger.com/atom/ns#' term='partially applied functions'/><category scheme='http://www.blogger.com/atom/ns#' term='partial functions'/><title type='text'>Scala, placeholders and partial functions</title><content type='html'>A couple of Scala examples to demonstrate the use of place-holder syntax and partial functions. These two things are related but partial functions goes beyond syntactical conciseness to provide new and powerful constructions.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Substitution:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;object Placeholders {&lt;br /&gt;&lt;br /&gt;  def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;    val myNumbers = 1 to 10 //List(1, 2, 3, 4, 5, 6, 7, 8, 9);&lt;br /&gt;&lt;br /&gt;    println("Greater than 3")&lt;br /&gt;&lt;br /&gt;    var result = myNumbers.filter((x : Int) =&gt; x &gt; 3)&lt;br /&gt;&lt;br /&gt;    result.foreach(println) // result.foreach((x) =&gt; println(x))&lt;br /&gt;&lt;br /&gt;    println("Greater than 4")&lt;br /&gt;&lt;br /&gt;    result = myNumbers.filter(x =&gt; x &gt; 4)&lt;br /&gt;&lt;br /&gt;    result.foreach(println)&lt;br /&gt;&lt;br /&gt;    println("Greater than 5")&lt;br /&gt;&lt;br /&gt;    result = myNumbers.filter(_ &gt; 5) // _ placeholder _ for&lt;br /&gt;&lt;br /&gt;    result.foreach(println)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Partially applied functions:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Partial functions are functions defined with only some of the arguments (or none), as the following example demonstrates:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;object PartiallyAppliedFunctionsTest {&lt;br /&gt;&lt;br /&gt;  def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;    val partiallyAppliedFunctions = new PartiallyAppliedFunctions();&lt;br /&gt;&lt;br /&gt;    println("sum 4 arg 1 + 2 + 3 + 4 = " + partiallyAppliedFunctions.getSum4arg()(1, 2, 3, 4))                  // expect 10&lt;br /&gt;&lt;br /&gt;    println("partiallyAppliedFunction 3 arg, 1 + 2 + 3 = " + partiallyAppliedFunctions.getSum3arg()(1, 2, 3))   // expect 6&lt;br /&gt;&lt;br /&gt;    println("partiallyAppliedFunction 2 arg, 1 + 2 = " + partiallyAppliedFunctions.getSum2arg()(1, 2))          // expect 3&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class PartiallyAppliedFunctions() {&lt;br /&gt;&lt;br /&gt;  private def sum(i1 : Int, i2 : Int, i3 : Int, i4 : Int) = {&lt;br /&gt;&lt;br /&gt;    i1 + i2 + i3 + i4&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def getSum4arg() = {&lt;br /&gt;&lt;br /&gt;    sum _&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def getSum3arg() : (Int, Int, Int) =&gt; Int = {&lt;br /&gt;&lt;br /&gt;    sum(0, _ : Int, _ : Int, _ : Int)&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def getSum2arg() : (Int, Int) =&gt; Int = {&lt;br /&gt;&lt;br /&gt;    sum(0, 0,  _ : Int, _ : Int)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The above example shows the &lt;span style="font-weight: bold;font-family:courier new;" &gt;function _ &lt;/span&gt;syntax to reference a function as a value.&lt;br /&gt;&lt;br /&gt;Also, functions getSum3arg() and getSum4arg() show the use of partial functions to re-use an existing function by partially defining and supplying some of the arguments.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-150332309312111726?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/150332309312111726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=150332309312111726' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/150332309312111726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/150332309312111726'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/01/scala-placeholders-and-partial.html' title='Scala, placeholders and partial functions'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-9209481490157346917</id><published>2009-01-02T01:15:00.000-08:00</published><updated>2009-01-04T04:58:13.821-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='if expression'/><category scheme='http://www.blogger.com/atom/ns#' term='functional programming'/><category scheme='http://www.blogger.com/atom/ns#' term='SICP'/><category scheme='http://www.blogger.com/atom/ns#' term='Scheme'/><category scheme='http://www.blogger.com/atom/ns#' term='primes'/><category scheme='http://www.blogger.com/atom/ns#' term='LISP'/><title type='text'>Scala, example finding prime numbers</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Firstly, Happy New Year! Happy 2009!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Continuing on with Scala, here is a further example, a simple test for prime numbers, also showing re-factoring from Scheme to Scala.&lt;br /&gt;&lt;br /&gt;This simple example tests for primality, based on the simple algorithm taken from SICP in the following example given in the programming language &lt;span style="font-weight: bold;"&gt;Scheme&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;object FindPrimes {&lt;br /&gt;&lt;br /&gt;  def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;    for (n &lt;- 1 to 500) {&lt;br /&gt;&lt;br /&gt;      val d = smallestDivisor(n)&lt;br /&gt;      println(n + ": lcd = " + d + (if (n == d) " prime!" else " not prime") )&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def isPrime(n : Int) : Boolean = {&lt;br /&gt;&lt;br /&gt;    n == smallestDivisor(n)&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def smallestDivisor(n : Int) : Int = {&lt;br /&gt;&lt;br /&gt;    findDivisor(n, 2)&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def findDivisor(n : Int, testDivisor : Int) : Int = {&lt;br /&gt;&lt;br /&gt;    if (square(testDivisor) &gt; n)&lt;br /&gt;      n&lt;br /&gt;    else if (divides(testDivisor, n))&lt;br /&gt;      testDivisor&lt;br /&gt;    else&lt;br /&gt;      findDivisor(n, testDivisor + 1)&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def square(n : Int) : Int = {&lt;br /&gt;&lt;br /&gt;    n * n&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  def divides(d : Int, n : Int) : Boolean = {&lt;br /&gt;&lt;br /&gt;    (n % d) == 0&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above example has a main that can be run. The code tests the first 500 integers for primality using the simple, unoptimised prime test algorithm which looks for the least divisor of n (below root(n)).&lt;br /&gt;&lt;br /&gt;It's worth pointing out that the findDivisor function is recursive, but if you look at the way it's constructed, the recursion appears at the end of the construction - and is thus amenable to tail recursion (optimisation).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Note:&lt;/span&gt; When testing for Primes in this way, if no divisor d of n is found less than root(n) then the number is prime, thus the search for divisors can end at root(n). This is because for any divisor d of n, there is a corresponding divisor n/d. So the maximum value for either/both occurs at root(n), beyond this, as d increases above root(n), n/d decreases below root(n) symmetrically.&lt;br /&gt;&lt;br /&gt;"If d is a divisor of n, then so is n/d. But d and n/d cannot both be greater than n."&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the statement:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;println(n + ": lcd = " + d + (if (n == d) " prime!" else " not prime") )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We can see the use of an if expression. In this situation is looks rather like Java's ternary if construct, but Scala's if expressions along with other expressions like for etc are fundamentally different, in that the construct equates to a value, in this example a value of type implicitly determined as String.&lt;br /&gt;&lt;br /&gt;However, it's worth noting that the following alteration to the println statement does not output "prime!" text:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;println(n + ": lcd = " + d + (if (n == d) " prime!") )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;My presumption (will confirm this) is that in the first case, all paths return String, so type inference determines type String. In the second case, the implicit else statement is missing, so not all paths return a String, so type inference probably determines a type of Nothing and the result is lost.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Update:&lt;/span&gt; As Jorge Ortiz has kindly pointed out in his comment, this is because the type inference of the Least Upper Bound (LUB). If not all paths return a type, the overall inference is Unit (like void) because this is the only safe inference that covers all cases.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-9209481490157346917?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/9209481490157346917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=9209481490157346917' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/9209481490157346917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/9209481490157346917'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2009/01/scala-example-finding-prime-numbers.html' title='Scala, example finding prime numbers'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-21589666677466093</id><published>2008-12-28T06:43:00.000-08:00</published><updated>2008-12-28T07:13:35.577-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='Ant'/><category scheme='http://www.blogger.com/atom/ns#' term='build'/><category scheme='http://www.blogger.com/atom/ns#' term='Scala ant'/><category scheme='http://www.blogger.com/atom/ns#' term='task'/><category scheme='http://www.blogger.com/atom/ns#' term='compile'/><title type='text'>Scala, Ant</title><content type='html'>&lt;font style="font-weight: bold;"&gt;An example of building Scala applications using Ant and the Scala Ant tasks:&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;In the complete Ant build file given below, the key lines are:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;taskdef resource="scala/tools/ant/antlib.xml"&amp;gt;&lt;br /&gt;       &amp;lt;classpath&amp;gt;&lt;br /&gt;           &amp;lt;pathelement location="${scala.home}/lib/scala-compiler.jar" /&amp;gt;&lt;br /&gt;           &amp;lt;pathelement location="${scala-library.jar}" /&amp;gt;&lt;br /&gt;       &amp;lt;/classpath&amp;gt;&lt;br /&gt;&amp;lt;/taskdef&amp;gt;&lt;br /&gt;&lt;/pre&gt;Which loads the task definition&lt;br /&gt;&lt;br /&gt;scala-library.jar defines Scala tasks for Ant, these are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;property name="scala-library.jar" value="${scala.home}/lib/scala-library.jar"&gt;scalac&lt;/property&gt;&lt;/li&gt;&lt;li&gt;&lt;property name="scala-library.jar" value="${scala.home}/lib/scala-library.jar"&gt;fsc&lt;/property&gt;&lt;/li&gt;&lt;li&gt;&lt;property name="scala-library.jar" value="${scala.home}/lib/scala-library.jar"&gt;scaladoc&lt;/property&gt;&lt;/li&gt;&lt;/ul&gt;&lt;property name="scala-library.jar" value="${scala.home}/lib/scala-library.jar"&gt;&lt;br /&gt;&lt;/property&gt;&lt;strong&gt;Note&lt;/strong&gt;: The Scala library &lt;code&gt;scala-library.jar&lt;/code&gt; must be present in the Java class path. The &lt;code&gt;actors&lt;/code&gt; and &lt;code&gt;dbc&lt;/code&gt; libraries are available as separate JAR files: &lt;code&gt;scala-actors.jar&lt;/code&gt;and &lt;code&gt;scala-dbc.jar&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;property name="scala-library.jar" value="${scala.home}/lib/scala-library.jar"&gt;&lt;font style="font-weight: bold;"&gt;Example build.xml&lt;/font&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// LJB 28-12-2008 - basic scala Ant build&lt;br /&gt;&amp;lt;project name="Scala test" default="build" basedir="../"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;property name="base.dir" value="${basedir}" /&amp;gt;&lt;br /&gt;&amp;lt;property name="sources.dir" value="${base.dir}/src" /&amp;gt;&lt;br /&gt;&amp;lt;property name="build.dir" value="${base.dir}/build//classes.tmp" /&amp;gt;&lt;br /&gt;&lt;br /&gt;// take scala ant libs from scala installation, assumes SCALA_HOME is set to home of scala in env vars&lt;br /&gt;&amp;lt;property environment="env"/&amp;gt;&lt;br /&gt;&amp;lt;property name="scala.home" value="${env.SCALA_HOME}" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="init"&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;property name="scala-library.jar" value="${scala.home}/lib/scala-library.jar" /&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;path id="build.classpath"&amp;gt;&lt;br /&gt;        &amp;lt;pathelement location="${scala-library.jar}" /&amp;gt;&lt;br /&gt;        &amp;lt;!--&amp;lt;pathelement location="${your.path}" /&amp;gt;--&amp;gt;&lt;br /&gt;        &amp;lt;pathelement location="${build.dir}"   /&amp;gt;&lt;br /&gt;  &amp;lt;/path&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;taskdef resource="scala/tools/ant/antlib.xml"&amp;gt;&lt;br /&gt;      &amp;lt;classpath&amp;gt;&lt;br /&gt;          &amp;lt;pathelement location="${scala.home}/lib/scala-compiler.jar" /&amp;gt;&lt;br /&gt;          &amp;lt;pathelement location="${scala-library.jar}" /&amp;gt;&lt;br /&gt;      &amp;lt;/classpath&amp;gt;&lt;br /&gt;  &amp;lt;/taskdef&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="build" depends="init"&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;mkdir dir="${build.dir}"   /&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;scalac srcdir="${sources.dir}"&lt;br /&gt;        destdir="${build.dir}"&lt;br /&gt;        classpathref="build.classpath"&lt;br /&gt;        force="changed"&amp;gt;&lt;br /&gt;&lt;br /&gt;      &amp;lt;!-- &amp;lt;src location="src" /&amp;gt; --&amp;gt;&lt;br /&gt;      &amp;lt;include name="**/*.scala" /&amp;gt;&lt;br /&gt;  &amp;lt;/scalac&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;target name="run" depends="build"&amp;gt;&lt;br /&gt;  &amp;lt;java classname="test.Test"&lt;br /&gt;      classpathref="build.classpath"&amp;gt;&lt;br /&gt;  &amp;lt;/java&amp;gt;&lt;br /&gt;&amp;lt;/target&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold;"&gt;Project directory structure:&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font face="courier new"&gt;/build&lt;/font&gt;&lt;br /&gt;&lt;font face="courier new"&gt;/build/build.xml&lt;/font&gt;&lt;br /&gt;&lt;font face="courier new"&gt;/src&lt;/font&gt;&lt;br /&gt;&lt;font face="courier new"&gt;/src/test.scala&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold;"&gt;Example "hello world" Scala test program&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;object Test {&lt;br /&gt;&lt;br /&gt;def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;println("Hello world")&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you type ant run in the /build directory, the application is compiled and run, giving "Hello world"...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold;"&gt;References:&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.scala-lang.org/node/98"&gt;http://www.scala-lang.org/node/98&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;/property&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-21589666677466093?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/21589666677466093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=21589666677466093' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/21589666677466093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/21589666677466093'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/12/scala-ant.html' title='Scala, Ant'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-4274340016101995363</id><published>2008-12-27T12:25:00.000-08:00</published><updated>2008-12-27T12:34:26.198-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='constructor'/><category scheme='http://www.blogger.com/atom/ns#' term='class'/><category scheme='http://www.blogger.com/atom/ns#' term='object'/><category scheme='http://www.blogger.com/atom/ns#' term='singleton'/><category scheme='http://www.blogger.com/atom/ns#' term='main'/><title type='text'>Scala - object, singletons, classes and constructors</title><content type='html'>Today, a simple example by way of explanation of the basic constructs of OO in Scala.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Things to note:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Scala does not use static methods, in this sense Scala is more purely OO than Java.&lt;/li&gt;&lt;li&gt;The equivalent is achieved using object singletons and companion objects.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The following code example demonstrates:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Use of object singleton and "main" application entry point&lt;/li&gt;&lt;li&gt;Declaration of new objects&lt;/li&gt;&lt;li&gt;Declaration of new class&lt;/li&gt;&lt;li&gt;Class primary constructor&lt;/li&gt;&lt;li&gt;Declaring fields&lt;/li&gt;&lt;li&gt;Declaring alternative constructors&lt;/li&gt;&lt;li&gt;Use of override keyword&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Example Code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package test&lt;br /&gt;&lt;br /&gt;// object declares a singleton (like Java static)&lt;br /&gt;object Test {&lt;br /&gt;  // the usual main, takes an Array[String] of arguments&lt;br /&gt;  def main(args : Array[String]) {&lt;br /&gt;&lt;br /&gt;      var myClass1 = new MyClass(5, "Louis")  // using primary constructor&lt;br /&gt;      var myClass2 = new MyClass(10);         // using alternate constructor&lt;br /&gt;&lt;br /&gt;      // access public field value&lt;br /&gt;      println("myClass1.value1 = " + myClass1.value1)&lt;br /&gt;&lt;br /&gt;      // output using overriden toString&lt;br /&gt;      println("myClass1 = " + myClass1)&lt;br /&gt;      println("myClass2 = " + myClass2)&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// define MyClass and its primary constructor (Int, String)&lt;br /&gt;class MyClass(v1 : Int, s1 : String) {&lt;br /&gt;&lt;br /&gt;  // these are fields (public)&lt;br /&gt;  def value1 : Int = v1&lt;br /&gt;  def string1 : String = s1&lt;br /&gt;&lt;br /&gt;  // this is an alternate constructor (calls primary constructor)&lt;br /&gt;  def this(v1 : Int) = {&lt;br /&gt;      this(v1, "hello")&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // can override toString like in Java, note no return statement required + the override keyword&lt;br /&gt;  override def toString() : String =&lt;br /&gt;  {&lt;br /&gt;      "MyClass: (" + value1 + ", " + string1 + ")"&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-4274340016101995363?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/4274340016101995363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=4274340016101995363' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4274340016101995363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4274340016101995363'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/12/scala-object-singletons-classes-and.html' title='Scala - object, singletons, classes and constructors'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-9033959055866191312</id><published>2008-12-24T01:14:00.000-08:00</published><updated>2010-02-13T05:56:34.016-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='functional'/><category scheme='http://www.blogger.com/atom/ns#' term='Scala-lang'/><category scheme='http://www.blogger.com/atom/ns#' term='JVM'/><title type='text'>Scala, an introduction</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Scala&lt;/span&gt; - "Scalable Java": a new Language which combines both Object Orientated and Functional programming paradigms.&lt;br /&gt;&lt;br /&gt;Scala is an extension of Java and runs on the JVM. Scala draws from languages such as Java, Smalltalk, Erlang and many others.&lt;br /&gt;&lt;br /&gt;Scala site: &lt;a style="" href="http://www.scala-lang.org/"&gt;http://www.scala-lang.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Downloads: &lt;a href="http://www.scala-lang.org/downloads"&gt;http://www.scala-lang.org/downloads&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Installation, using the IzPack Scala installer jar, run: &lt;span style="font-family:courier new;"&gt;java -jar scala-x-installer.jar&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Scala - main features:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Integrates with Java (is an extension of Java), and shares libraries and primitive types&lt;/li&gt;&lt;li&gt;Compiles to Java byte code - runs on JVM (also can be run on .Net)&lt;/li&gt;&lt;li&gt;Imperative and functional support&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Object Orientated (classes, objects)&lt;/li&gt;&lt;li&gt;Functional (functions as first class objects, referential transparency)&lt;/li&gt;&lt;li&gt;Statically typed&lt;/li&gt;&lt;li&gt;Type inference (more concise code that looks more like Dynamic/duck typed, but has the benefits of static / strong typing)&lt;/li&gt;&lt;li&gt;Supports closures and function literals&lt;/li&gt;&lt;li&gt;Concurrency model using Erlang Actors system (a 'safer' concurrency model)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Scala can be run stand alone, using the command line interpreter - using the "scala" command.&lt;br /&gt;&lt;br /&gt;Scala also has plugin support for NetBeans, Eclipse and InteliJ&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Syntax Overview:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Type inference means most type declarations can be omitted (but can still be explicitly declared).&lt;/li&gt;&lt;li&gt;Variables are defined as &lt;span style="font-family:courier new;"&gt;name : type&lt;/span&gt; rather than &lt;span style="font-family:courier new;"&gt;type name&lt;/span&gt; as per Java&lt;/li&gt;&lt;li&gt;Semicolons are often optional&lt;/li&gt;&lt;li&gt;Does not specify or define operators. +-*/ etc are valid method names are defined as such for appropriate types&lt;br /&gt;&lt;/li&gt;&lt;li&gt;var and val keywords - val declares a constant type (like Java's final, not reassignable), var declares a variable that can be reassigned. val, like var can still be mutable however, if the type is mutable.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Functions, declared using &lt;span style="font-family:courier new;"&gt;def&lt;/span&gt; keyword. e.g. &lt;span style="font-family:courier new;"&gt;def myFunction(x: Type1, y: Type2) : ReturnType&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Pre and post increment/decrement (i++, ++i, i--, --i) are not supported, use i = i + 1 or i += 1&lt;/li&gt;&lt;li&gt;Recommended indentation is 2 spaces&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Imperative &lt;span style="font-family:courier new;"&gt;for&lt;/span&gt; loops not supported, the functional equivalent, a for Expression is used instead&lt;/li&gt;&lt;li&gt;Arryays are indexed using (n) not [n]&lt;/li&gt;&lt;li&gt;Type parameters are specified using [type]. If both type and index are used, the ordering is [type](params)&lt;/li&gt;&lt;li&gt;Scala supports infix as method calls. e.g. 1 + 2 is equivalent to 1.+(2) where + is not a special operator, but a regular method&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Applying () to an object (recipient) is equivalent to calling .apply() on it. e.g. &lt;span style="font-family:courier new;"&gt;myThing(i) &lt;/span&gt;is equivalent to&lt;span style="font-family:courier new;"&gt; myThing.apply(i)&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The receiver of an = operator is equivalent to calling .update. e.g. &lt;span style="font-family:courier new;"&gt;myThing(i) = value&lt;/span&gt; is equivalent to &lt;span style="font-family:courier new;"&gt;myThing.update(i, value)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Method association is by default to the left, unless the method ends with a colon : e.g. 1 + 2 applies + to 1 giving 1.+(2) whereas x :: y applies :: (cons) to y, giving y.::(x)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The List type supports ::: (concat) and :: (&lt;span style="font-weight: bold; font-style: italic;"&gt;cons&lt;/span&gt;, prepend), both apply the operation and return the resulting new List&lt;/li&gt;&lt;li&gt;Arrays are always mutable, lists are always immutable. Sets and maps can be either, the default is immutable (from the trait scala.collection.immutable) but the mutable equivalents can be imported from scala.collection.mutable&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The -&gt; method provides &lt;span style="font-weight: bold; font-style: italic;"&gt;Implicit Conversion&lt;/span&gt;. e.g. x -&gt; y is x.-&gt;y which returns a key/value tuple containing x as the key and y as the value&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Some simple Functional examples:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Print all command line arguments, using foreach, passing println function:&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Verbose:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;args.foreach((arg: String) =&gt; println(arg))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Type inference on arg:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;args.foreach(arg =&gt; pringln(arg))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Concise:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;args.foreach(println)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The last example is a shorthand that can be applied when a function literal cosists of one statement that takes one argument - known as a &lt;span style="font-weight: bold; font-style: italic;"&gt;Partially Applied Function&lt;/span&gt;&lt;span style="font-style: italic;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;For Expressions:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Replacing imperative for loops, the syntax is of the form:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;for (arg &lt;- args)&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;println(arg) &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Note: In the above for expression example, arg is a val (final/const) not a var, and a new val variable is created for each "iteration".&lt;br /&gt;&lt;br /&gt;&lt;span&gt;or&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-family:courier new;"&gt;for (i &lt;- 1 to 30) ...&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Declaring Arrays:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;Very concisely:&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;val myArray = Array("value1", "value2")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;defines a string array (type inference) of size 2&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;br /&gt;This is equivalent to:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;val myArray = Array.apply("value1", "value2")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;where apply is called on the Array &lt;span style="font-weight: bold; font-style: italic;"&gt;Companion Object&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;More Verbosely the array could also be declared more traditionally as:&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;val myArray = new Array[String](2)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;or even&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;val myArray : Array[String] = new Array[String](2)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;but the former concise approach is the Scala recommended way, the later hints at the underlying Java roots.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Lists:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Defining new lists is easy with the &lt;span style="font-weight: bold; font-style: italic;"&gt;cons&lt;/span&gt; method, as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;val myList = 3 :: 2 :: 4 :: 5 :: Nil    // Nil is the Empty List, also so is List()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Note:&lt;/span&gt; The Nil (empty List) is needed so that working from right to left, the :: method is defined on Nil, which first gives Nil.::(5) returning List(5) which then gives 5.::(4) resulting in List(4, 5), and so on. Without the Nil there is a syntax error as :: (cons) is not defined on 5 (which is of type integer).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Examples:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Factorial !&lt;/span&gt; - Simple factorial, defined in a functional way:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;def factorial(value : int) : int = { if (value == 0) 1 else value * factorial(value - 1) }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;scala&gt; factorial(10)&lt;br /&gt;res15: int = 3628800&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Triangle Numbers:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;def tri(x : Int) : Int = { if (x == 0) 0 else x + tri(x-1) }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;scala&gt; tri(4)&lt;br /&gt;res14: Int = 10&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Scala for scripting:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Scala scripts can be run using &lt;span style="font-family:courier new;"&gt;scala myscript.scala&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Additionally, Scala can be used as a self contained scripting language by invoking the scala command line interpreter with the script, as follows:&lt;br /&gt;&lt;br /&gt;On 'nix platforms&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#!/bin/sh&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;exec scala "$0" "$@"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;!#&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;println("Hello world, hello " + args(0))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Don't forget to give the script execute permissions (&lt;span style="font-family:courier new;"&gt;chmod +x myscipt&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;Execute: &lt;span style="font-family:courier new;"&gt;myscript Louis&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A similar thing can be achieved on Windows...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Scala with build systems:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;With Ant:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.scala-lang.org/node/98"&gt;http://www.scala-lang.org/node/98&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;With Maven:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://scala-blogs.org/2008/01/maven-for-scala.html"&gt;http://scala-blogs.org/2008/01/maven-for-scala.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Further Resources:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Books:&lt;br /&gt;&lt;br /&gt;Artima book (excellent): &lt;a href="http://www.artima.com/shop/programming_in_scala"&gt;http://www.artima.com/shop/programming_in_scala&lt;/a&gt; released 17th Nov 2008, by &lt;span class="as"&gt;Martin Odersky, Lex Spoon, and Bill Venners.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Source code for book examples: &lt;a href="http://booksites.artima.com/programming_in_scala/progInScalaExamples1EdV6.zip"&gt;http://booksites.artima.com/programming_in_scala/progInScalaExamples1EdV6.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Browse book examples: &lt;a href="http://booksites.artima.com/programming_in_scala/examples"&gt;http://booksites.artima.com/programming_in_scala/examples&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;OReilly Programming Scala: &lt;a href="http://programming-scala.labs.oreilly.com/"&gt;http://programming-scala.labs.oreilly.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Blogs:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.scala-blogs.org/"&gt;http://www.scala-blogs.org/&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;Blog on Monads: &lt;a href="http://james-iry.blogspot.com/2007/09/monads-are-elephants-part-1.html"&gt;http://james-iry.blogspot.com/2007/09/monads-are-elephants-part-1.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Articles:&lt;br /&gt;&lt;br /&gt;Java refugees: &lt;a href="http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-1"&gt;http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-1&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Build tools:&lt;br /&gt;&lt;br /&gt;SBT: &lt;a href="http://code.google.com/p/simple-build-tool/"&gt;http://code.google.com/p/simple-build-tool/&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Interesting Blog about Scala and Lift (using Maven and Jetty).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://scala-blogs.org/2007/12/dynamic-web-applications-with-lift-and.html"&gt;http://scala-blogs.org/2007/12/dynamic-web-applications-with-lift-and.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;SIDs (software improvement Documents):&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.scala-lang.org/sids"&gt;http://www.scala-lang.org/sids&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Monads:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://projects.tmorris.net/public/what-does-monad-mean/artifacts/1.1/chunk-html/ar01s04s04.html"&gt;http://projects.tmorris.net/public/what-does-monad-mean/artifacts/1.1/chunk-html/ar01s04s04.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://vimeo.com/8729673"&gt;http://vimeo.com/8729673&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;IRC channel: &lt;span style="font-weight: bold;"&gt;#scala&lt;/span&gt; on irc.freenode.net&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(Also (unrelated): pastie - &lt;a href="http://pastie.org/"&gt;http://pastie.org/&lt;/a&gt; is handy for pasting those odd snippets of code around on the internet/IRC).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Interesting blog about Scala type-safe SQL / DB - SQuery - &lt;a href="http://szeiger.de/blog/2008/12/21/a-type-safe-database-query-dsl-for-scala/"&gt;http://szeiger.de/blog/2008/12/21/a-type-safe-database-query-dsl-for-scala/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Updated (13-09-2009): Came across this useful presentation: &lt;a href="http://www.slideshare.net/astubbs/scala-language-intro-inspired-by-the-love-game?src=embed"&gt;http://www.slideshare.net/astubbs/scala-language-intro-inspired-by-the-love-game?src=embed&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;99 Scala problems&lt;/span&gt; - an adaption of the 99 Prolog problems into Scala:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://aperiodic.net/phil/scala/s-99/#p10"&gt;http://aperiodic.net/phil/scala/s-99/#p10&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-9033959055866191312?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/9033959055866191312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=9033959055866191312' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/9033959055866191312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/9033959055866191312'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/12/scala-introduction.html' title='Scala, an introduction'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-1165651008266762164</id><published>2008-12-21T14:47:00.000-08:00</published><updated>2009-01-04T11:12:16.270-08:00</updated><title type='text'>PCWiz Mac OSX under VMware (2.0)</title><content type='html'>&lt;span style="font-family: times new roman;"&gt;(Note - I do not condone the use of illegal / pirated software. If you're going to use Mac OSX, please support Applet and buy a license for the OS.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Mac OSX can be run under VMware, using a special build such as the "pcwiz" version.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://pcwizcomputer.com/index.php?Itemid=48&amp;amp;id=76&amp;amp;option=com_content&amp;amp;task=view"&gt;&lt;span style="font-weight: bold;"&gt;http://pcwizcomputer.com/index.php?Itemid=48&amp;amp;id=76&amp;amp;option=com_content&amp;amp;task=view&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Performance is slow, but just about usable.&lt;/li&gt;&lt;li&gt;There's naturally no vmware tools at this time.&lt;/li&gt;&lt;li&gt;Networking can be made to work.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;When it comes to the screen resolution, there are no drivers as such to adjust but the screen resolution settings can be modified - see here for further details: &lt;a href="http://pcwizcomputer.com/index.php?option=com_content&amp;amp;task=view&amp;amp;id=31&amp;amp;Itemid=45"&gt;http://pcwizcomputer.com/index.php?option=com_content&amp;amp;task=view&amp;amp;id=31&amp;amp;Itemid=45&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-1165651008266762164?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/1165651008266762164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=1165651008266762164' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/1165651008266762164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/1165651008266762164'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/12/pcwiz-mac-osc-under-vmware.html' title='PCWiz Mac OSX under VMware (2.0)'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-91782439130847258</id><published>2008-12-13T16:08:00.000-08:00</published><updated>2008-12-13T16:43:46.671-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bootstrap'/><category scheme='http://www.blogger.com/atom/ns#' term='UNO'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenOffice'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenOffice 3.0'/><category scheme='http://www.blogger.com/atom/ns#' term='bootstrapconnector'/><category scheme='http://www.blogger.com/atom/ns#' term='URE'/><title type='text'>OpenOffice (3.0) / UNO API</title><content type='html'>Recently a project needed some reporting enhancements (spreadsheet charts) for which Apache POI didn't provide the necessary support. So, after some exploration, I decided on using OpenOffice with it's API, in this particular instance it was OpenOffice 3.0m9 (latest at the tine of writing) and the &lt;span style="font-weight: bold;"&gt;UNO &lt;/span&gt;Java API.&lt;br /&gt;&lt;br /&gt;&lt;a href="www.openoffice.org"&gt;www.openoffice.org&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;OpenOffice provides some very powerful tools, including Spreadsheets, Documents, PDF etc along compatibility with MS Office. In addition, OpenOffice is quite powerful at convertion document types and between versions. For example a MS word document could be loaded and then saved as a PDF.&lt;br /&gt;&lt;br /&gt;OpenOffice - &lt;a href="www.openoffice.org"&gt;www.openoffice.org&lt;/a&gt;&lt;br /&gt;Forum - &lt;a href="http://user.services.openoffice.org/en/forum/"&gt;http://user.services.openoffice.org/en/forum/&lt;/a&gt;&lt;br /&gt;Wiki - &lt;a href="http://wiki.services.openoffice.org/wiki/Main_Page"&gt;http://wiki.services.openoffice.org/wiki/Main_Page&lt;/a&gt; (including good developer section)&lt;br /&gt;FAQ - &lt;a href="http://wiki.services.openoffice.org/wiki/Uno/FAQ"&gt;http://wiki.services.openoffice.org/wiki/Uno/FAQ&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The OpenOffice suite comes with an SDK and the UNO API, supporting various languages, including Java.&lt;br /&gt;&lt;br /&gt;SDK download - &lt;a href="http://download.openoffice.org/3.0.0/sdk.html"&gt;http://download.openoffice.org/3.0.0/sdk.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The SDK/API is based on UNO (Unified Network Objects) which is an alternative/competator to COM, like CORBA etc, and allows the remote (out of process) communication and control of OpenOffice - "UNO is a component model that offers inter-operability between    different programming languages, different objects models,    different machine architectures, and different processes; either in a    LAN or via the Internet."&lt;br /&gt;&lt;br /&gt;Another acronym is URE - "Each component lives in a &lt;strong&gt;U&lt;/strong&gt;no    &lt;strong&gt;R&lt;/strong&gt;untime &lt;strong&gt;E&lt;/strong&gt;nvironment (&lt;strong&gt;URE&lt;/strong&gt;).    A URE is identified by the implementation language (e.g., C++,    Java, &lt;span lang="en-US"&gt;Perl&lt;/span&gt;, ...) and the current    process."&lt;br /&gt;&lt;br /&gt;See here for more details: &lt;a href="http://udk.openoffice.org/common/man/uno.html"&gt;http://udk.openoffice.org/common/man/uno.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When using OpenOffice on the server side to provide reports (in my case, as part of a web application), various SDK jars are needed along with a means to find the OpenOffice installation.&lt;br /&gt;&lt;br /&gt;The Java jars needed are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;juh.jar&lt;/li&gt;&lt;li&gt;jurt.jar&lt;/li&gt;&lt;li&gt;ridl.jar&lt;/li&gt;&lt;li&gt;jut.jar&lt;/li&gt;&lt;li&gt;unoil.jar&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I chose to include them in my web application WAR file.&lt;br /&gt;This can create problems, because the classpath to the jars will not be where OpenOffice is installed, to work around this the Java classes from the SDK can be loaded and bootstrapped in the class loaded, but this is tricky when using a web app container. For convienience I made use of the useful &lt;span style="font-weight: bold;"&gt;bootstrapconnector.jar&lt;/span&gt; utility library. This library can connect to OpenOffice regardless of the location of the jars, it just needs a path to an OpenOffice installation, which I set as an ENV variable called UNO_PATH.&lt;br /&gt;&lt;br /&gt;BootstrapSocketConnector - &lt;a href="http://user.services.openoffice.org/en/forum/viewtopic.php?f=44&amp;amp;t=2520"&gt;http://user.services.openoffice.org/en/forum/viewtopic.php?f=44&amp;amp;t=2520&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I also made use of the OpenOffice plugin for Netbeans 6.5 to get a quick start developing the code, before moving to the production solution.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Some things to watch out for:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One problem I stumbled into. Installing OpenOffice for the first time on a remote Linux (CentOS) machine over a terminal, when I came to run the web application the program appears to hang. Some investigation with &lt;span style="font-weight: bold;"&gt;ps&lt;/span&gt; showed that soffice was being started, but that I was getting many instances, all apparently hung. I replicated the setup on a different Linux installation, this time one with a desktop / display manager. It was then obvious what was happening, the first time OpenOffice is launched, it prompts the user with a registration wizard! Oops.&lt;br /&gt;&lt;br /&gt;So the solution to this is simple, pass an option when launching the OpenOffice process, this can be achieved conveniently using the bootstrapsocketconnect with something like the following:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;span style="font-family: courier new;"&gt;// Create OOo server with additional -nofirststartwizard option&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;List oooOptions = OOoServer.getDefaultOOoOptions();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;oooOptions.add("-nofirststartwizard");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;OOoServer oooServer = new OOoServer(OOO_EXEC_FOLDER, oooOptions);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;// Connect to OOo&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;BootstrapSocketConnector bootstrapSocketConnector = new BootstrapSocketConnector(oooServer);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;XComponentContext remoteContext = bootstrapSocketConnector.connect();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-91782439130847258?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/91782439130847258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=91782439130847258' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/91782439130847258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/91782439130847258'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/12/openoffice-30-uno-api.html' title='OpenOffice (3.0) / UNO API'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-8144667828145078029</id><published>2008-12-07T12:08:00.000-08:00</published><updated>2008-12-12T16:30:57.295-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='JSON'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>JSON, Java and JavaScript</title><content type='html'>JSON is so simple there's not a lot to say about it, but I thought it's worth putting up a few links and notes for reference.&lt;br /&gt;&lt;br /&gt;JSON is JavaScript Object Notation. Whilst it could be called an Object Notation (a simple one), it's not tied to JavaScript, although it's early origins are from that language (ECMAScript, &lt;a href="http://en.wikipedia.org/wiki/Ecma_International" title="Ecma International"&gt;ECMA&lt;/a&gt;-262 3rd Edition). JSON is essentially language independant, like XML. JSON, like XML can represent data structures and data (self describing) but unlike XML, JSON does not support namespaces, schema and other more advanced features. JSONs key strengths are its simpicity and low overhead, terse message size.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;JSON looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     "firstName": "John",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     "lastName": "Smith",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     "address": {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         "streetAddress": "21 2nd Street",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         "city": "New York",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         "state": "NY",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         "postalCode": 10021&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     },&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     "phoneNumbers": [&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         "212 555-1234",&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;         "646 555-4567"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     ]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Where { and } contain the object, the properties are listed as "name" : "value" pairs. Objects can be embedded within objects and arrays are denoted using comma separated lists within []&lt;br /&gt;&lt;br /&gt;So, special symbols (for escaping) are: {}[]:"&lt;br /&gt;&lt;br /&gt;Main Site: &lt;a href="http://www.json.org/"&gt;http://www.json.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Simple JSON for Java: &lt;a href="http://www.json.org/java/json_simple.zip"&gt;http://www.JSON.org/java/json_simple.zip&lt;/a&gt; &lt;a href="http://www.json.org/java/simple.txt"&gt;http://www.json.org&lt;/a&gt;&lt;a href="http://www.json.org/java/simple.txt"&gt;/java/simple.txt&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Simple JSON for JavaScript: &lt;a href="http://www.json.org/js.html"&gt;http://www.json.org/js.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Wikipedia: &lt;a href="http://en.wikipedia.org/wiki/JSON"&gt;http://en.wikipedia.org/wiki/JSON&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;JavaScript&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;Basic suppport for converting JSON messages into objects (deserialisation) is to use the often best avoided eval function, as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;var myObject = eval('(' + myJSONtext + ')');&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;where the outer '(' ')' are necessary for the JavaScript language, not JSON itself.&lt;br /&gt;&lt;br /&gt;Better (safer) still, various libaries are available, such as the Open Source version from www.json.org in json2.js&lt;br /&gt;&lt;br /&gt;Which essentially is used like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;var myObject = JSON.parse(myJSONtext, reviver);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;var myJSONText = JSON.stringify(myObject, replacer);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Java:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Create a JSON string using org.json.simple.JSONObject:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;JSONObject obj=new JSONObject();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;obj.put("name","foo");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;obj.put("num",new Integer(100));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;System.out.print(obj);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The toString() on the JSONObject serialises the JSON object (map of name value pairs) to a JSON string.&lt;br /&gt;&lt;br /&gt;JSON is simple, by design, so there isn't much more to be said on it.&lt;br /&gt;&lt;br /&gt;One of the main things to watch out for is encoding/escaping messages so they are JSON friendly, I'll add more on that soon.&lt;br /&gt;&lt;br /&gt;The following link may be useful when working with character escaping: &lt;a href="http://www.the-art-of-web.com/javascript/escape/"&gt;http://www.the-art-of-web.com/javascript/escape/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-8144667828145078029?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/8144667828145078029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=8144667828145078029' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8144667828145078029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8144667828145078029'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/12/json-java-and-javascript.html' title='JSON, Java and JavaScript'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-4984857063922694704</id><published>2008-11-23T10:40:00.000-08:00</published><updated>2008-12-12T16:32:22.561-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='BIOS'/><category scheme='http://www.blogger.com/atom/ns#' term='LBA'/><category scheme='http://www.blogger.com/atom/ns#' term='LBA-48'/><category scheme='http://www.blogger.com/atom/ns#' term='Large LBA'/><title type='text'>BIOS LBA / Hard disk, apparent failure problem "Blinking cursor of doom"</title><content type='html'>A rather interesting low level problem: If you ever get a machine inexplicably stuck after POST with a blinking cursor in the top right and nothing more and want to know why or fix it, please read on!&lt;br /&gt;&lt;br /&gt;Whilst there are a number of possible causes (like incorrect BIOS settings) I'm assuming all of those have been checked and ruled out, if so and the problem still persists then the following might be an explanation:&lt;br /&gt;&lt;br /&gt;A while back I upgraded my ageing Dell Ispiron 6000 laptop hard drive (80gb) with a 160gb drive. I cloned the original drive to retain everything but made the partition larger to make the extra space available. The machine ran XP Pro SP2 and had been stable for a couple of years, since I first got it (after a battle with a nasty virus that I evenually managed to win a few months previously).&lt;br /&gt;&lt;br /&gt;An easy enough job and all was good, for a while. One day the machine needed a reboot, after shutting down it came back with the &lt;span style="font-weight: bold;"&gt;Blinking cursor of Doom!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is where, straight after POST (Power On Self Test) the machine totally hangs (before Windows starts up). My first thoughts (after oh crap) where along the lines of, has the drive died, mbr gone wrong, virus trashed the drive, partition table messed up, file system corrupt etc?&lt;br /&gt;&lt;br /&gt;After many hours, I'd done a full chkdsk /r, fixmbr, checked the MBR (Master Boot Record) and Partition Table information, made sure the partition was active and so on, I even moved and resized the partition slightly, swapped the drive into another machine (was fine), tried a different drive in the laptop, also fine. Checked my BIOS (Basic Input Output System) for updates and so on - nothing seemed to be wrong - weird!&lt;br /&gt;&lt;br /&gt;The MBR is the sector at cylinder 0, head 0, sector 1 - it's launched according to the BIOS boot sequence, if the BIOS finds a valid MBR it's copied to memory and executed as part of the boot sequence of the machine.&lt;br /&gt;&lt;br /&gt;I also looked and the Windows MBR code (disassembly) from here &lt;a href="http://mirror.href.com/thestarman/asm/mbr/STDMBR.htm"&gt;http://mirror.href.com/thestarman/asm/mbr/STDMBR.htm&lt;/a&gt;  to check all paths through the boot loader - all likely paths result in a message of some sort like the archaic "Please insert boot disk" type messages. I just got a blank screen with flashing cursor - how come?&lt;br /&gt;&lt;br /&gt;I could see all the files on the disk, the disk and it's contents appears fine - so the question was &lt;span style="font-weight: bold;"&gt;what on earth was stopping the disk from being bootable!?&lt;/span&gt;. It defied any logic, surely if the file system is intact, has no errors, the partition table was fine and everything was set for the system to boot from it, why didn't it?&lt;br /&gt;&lt;br /&gt;After much time was spent on it (I really didn't want to have to set everything up again) eventually I decided it would be quicker to re-ghost from the original 80gb drive and get back to where I was 2 or 3 months previously, then copying over any new data from the fine but un-bootable 160gb drive.&lt;br /&gt;&lt;br /&gt;I did this and all was well again (but in the back of my mind I was never happy I'd not managed to get to the bottom of it).&lt;br /&gt;&lt;br /&gt;My machine was working but I was puzzled. The machine starts up in the System BIOS, it runs various checks and initialises the hardware and subsystems before trying to find a bootable volume. Assuming a bootable hard disk is found, the MBR is executed, the partiton tables are examined and active partition is bootstrapped, the first "file" lauched in a windows 2000/XP/NT platform being the ntldr program responsible for starting windows (and capable of multiboot).&lt;br /&gt;&lt;br /&gt;Whilst dissatisfied I'd not understood the problem, as days and weeks passed, the problem faded into a dim and distant memory...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Then, about 3 - 4 months later - after updating ITunes and needed to reboot, the same thing stuck again! Now this time, whilst rather disappointed, I knew there had to be an explanation. Maybe it was hardware related, maybe the machine was unreliable - how could I trust it again if it did this every so often?&lt;br /&gt;&lt;br /&gt;So, this time around I thought I need to get to the bottom of this - there must be a reason, it's happened twice in a row, and suspiciously in roughly similar time spans (3 months or so) from the original disk clone - this had to be a clue.&lt;br /&gt;&lt;br /&gt;So, after chkdsk /r etc just to check everything was ok, I got to work.&lt;br /&gt;&lt;br /&gt;The disk was un-bootable, but the file system was fine. It hung immediately after POST, but with the briefest of flashes of the hard disk light. This had to be something low level, before windows, after POST - not much happens, especially knowing the MBR and partition tables were intact and fine too.&lt;br /&gt;&lt;br /&gt;I renamed c:\ ntldr, IO.SYS and NTDETECT.COM, the low level bootstrap files for Windows.&lt;br /&gt;&lt;br /&gt;After booting, the machine did exactly the same. Ahah this was a clue of sorts, if the disk was bootable but it wasn't getting as far as running ntldr then the fault was prior to that. If MBR and partition table were ok, then the fault was prior to that also, so, the BIOS?&lt;br /&gt;&lt;br /&gt;I checked again for BIOS updates, nothing released matched the problem.&lt;br /&gt;&lt;br /&gt;Then, after much Googling came the clue. Some BIOSes have an intrinsic 137gb limit.&lt;br /&gt;&lt;br /&gt;That's 137gb of addressable disk, which might translate to less taking into account the overhead of the file system and block sizes etc.&lt;br /&gt;&lt;br /&gt;Whilst Windows is happy to grow the file system behond this limit, eventually the BIOS will reach this maximum and barf. So, it could explain it....&lt;br /&gt;&lt;br /&gt;There was only one way to find out. I resized the partition (made smaller) and created a new one in the new spare space. I copied files over from the original partition and then resized it smaller again, growing the new one until they were about the same size (2 x 80gb partitions rather than 1 x 160gb).&lt;br /&gt;&lt;br /&gt;I restart with the downsized partition this time the machine comes up with a more helpful missing ntldr error message - ahah! it's tried to boot from the disk!&lt;br /&gt;&lt;br /&gt;Booting up for a final time from the boot disk I renamed the files (ntldr etc) back.  Reboot one last time and hey presto, it's working fine. Nothing lost, and this time I only lost a few hours (3 or 4) from my life and most importantly, I got some closure on the problem and an understanding of what happened and how to avoid it forever.&lt;br /&gt;&lt;br /&gt;Greatly satisfied and relieve, I thought I'd share this experience in case it helps someone else in a similar position. Like anything, when you know the answer it's easy, but I've worked with computers for years and for a while there I was completely stumped with a problem that seemed, rather un-computer like, to defy all logic!&lt;br /&gt;&lt;br /&gt;Whilst I'm entirely happy with two smaller partitions, the longer term solution is known as 48bit LBA, AKA Big LBA - &lt;a href="http://en.wikipedia.org/wiki/Advanced_Technology_Attachment"&gt;http://en.wikipedia.org/wiki/Advanced_Technology_Attachment&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;References:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Master_boot_record"&gt;http://en.wikipedia.org/wiki/Master_boot_record&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Booting#Boot_loader"&gt;http://en.wikipedia.org/wiki/Booting#Boot_loader&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Windows_NT_Startup_Process"&gt;http://en.wikipedia.org/wiki/Windows_NT_Startup_Process&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mirror.href.com/thestarman/asm/mbr/STDMBR.htm"&gt;http://mirror.href.com/thestarman/asm/mbr/STDMBR.htm&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ata-atapi.com/hiwmbr.html"&gt;http://www.ata-atapi.com/hiwmbr.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Advanced_Technology_Attachment"&gt;http://en.wikipedia.org/wiki/Advanced_Technology_Attachment&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-4984857063922694704?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/4984857063922694704/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=4984857063922694704' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4984857063922694704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4984857063922694704'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/11/bios-lba-hard-disk-apparent-failure.html' title='BIOS LBA / Hard disk, apparent failure problem &quot;Blinking cursor of doom&quot;'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-4943541925734196154</id><published>2008-11-23T08:42:00.000-08:00</published><updated>2008-12-28T08:50:49.993-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Applet'/><category scheme='http://www.blogger.com/atom/ns#' term='example'/><category scheme='http://www.blogger.com/atom/ns#' term='integration'/><category scheme='http://www.blogger.com/atom/ns#' term='Java JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Function'/><category scheme='http://www.blogger.com/atom/ns#' term='JSObject'/><title type='text'>Applet &lt;-&gt; Javascript integration</title><content type='html'>It's been a while since I've done this, but I thought I'd refresh my memory on the options available. Maybe Applets have fallen out of favour a bit and whilst Javascript is popular for Rich, Dynamic Internet Applications, sometimes you need more and one way to do it is to use Applets, or integrate Applets with Javascript.&lt;br /&gt;&lt;br /&gt;This example shows some simple ways to achieve Applet/JavaScript integration:&lt;br /&gt;&lt;br /&gt;I've included example HTML with JavaScript source and Java source code for an Applet, to demonstrate so ways to achieve JavaScript to Java Applet integration. The simple example code demonstrates both JavaScript calling a Java Applet and a Java Applet calling JavaScript.&lt;br /&gt;&lt;br /&gt;The JavaScript function jsShowMsg(String) is called in two different ways from the Java Applet. A single string parameter is passed, and the JavaScript function displays this using the standard alert() function to create a dialog box.&lt;br /&gt;&lt;br /&gt;The Applet provides a showMessage(String) public method, which similarly is called by the JavaScript code when the button on the page is pressed. The String parameter is taken from the text field and displayed in the Applet.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;HTML Page:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Provides the Applet on the page. Provides the JavaScript function called by the Applet, calls the Applet public method when the button is clicked (takes the String value from the input text box.&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;HTML&amp;gt;&lt;br /&gt;&amp;lt;HEAD&amp;gt;&lt;br /&gt; &amp;lt;TITLE&amp;gt;Applet HTML Page&amp;lt;/TITLE&amp;gt;&lt;br /&gt;&amp;lt;/HEAD&amp;gt;&lt;br /&gt;&amp;lt;BODY&amp;gt;&lt;br /&gt;  &amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;   &lt;br /&gt;      /**&lt;br /&gt;       * jsShowMsg - demostrates being called by an Applet, being passed a single String argument, the message&lt;br /&gt;       */&lt;br /&gt;      function jsShowMsg(msg)&lt;br /&gt;      {&lt;br /&gt;          alert("Message from applet was: '" + msg + "'");&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      /**&lt;br /&gt;       * callApplet - demonstrates calling a public method on the Applet (showMessage(String))&lt;br /&gt;       */&lt;br /&gt;      function callApplet(msg)&lt;br /&gt;      {&lt;br /&gt;          //alert("before calling Applet method with msg=" + msg);&lt;br /&gt;&lt;br /&gt;          document.testApplet.showMessage(msg);&lt;br /&gt;&lt;br /&gt;          //alert("after calling Applet method");&lt;br /&gt;      }&lt;br /&gt;  &amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;H3&amp;gt;&amp;lt;HR WIDTH="100%"&amp;gt;Applet HTML Page - Applet &amp;lt;-&amp;gt; JavaScript integration example&amp;lt;HR WIDTH="100%"&amp;gt;&amp;lt;/H3&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;P&amp;gt;&lt;br /&gt;  &amp;lt;APPLET name="testApplet" codebase="classes" code="com/chillipower/TestApplet.class" width=400 height=150&amp;gt;&amp;lt;/APPLET&amp;gt;&lt;br /&gt;  &amp;lt;/P&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;input type="text" id="msgTb" name="msgTb" value="A message from JS!" /&amp;gt;&amp;lt;input type="button" value="button1" onclick="callApplet(getElementById('msgTb').value);" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/BODY&amp;gt;&lt;br /&gt;&amp;lt;/HTML&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Java Applet Class:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Calls the JavaScript function in two different ways when the Applet is started. Provides a showMessage public method that the JavaScript can call.&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package com.chillipower;&lt;br /&gt;&lt;br /&gt;import java.applet.Applet;&lt;br /&gt;import java.awt.Color;&lt;br /&gt;import java.awt.Graphics;&lt;br /&gt;import java.lang.reflect.InvocationTargetException;&lt;br /&gt;import java.lang.reflect.Method;&lt;br /&gt;import java.net.MalformedURLException;&lt;br /&gt;import java.net.URL;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* @author Louis B&lt;br /&gt;*/&lt;br /&gt;public class TestApplet extends Applet&lt;br /&gt;{&lt;br /&gt;  String JS_MESSAGE   = "Hello from Java Applet to JavaScript (using JavaScript alert)";&lt;br /&gt;  String JS_FUNC_NAME = "jsShowMsg";&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * init - applet init function&lt;br /&gt;   */&lt;br /&gt;  @Override&lt;br /&gt;  public void init()&lt;br /&gt;  {&lt;br /&gt;      setBackground(new Color(0xFAFAFF));&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * start - applet start function&lt;br /&gt;   */&lt;br /&gt;  @Override&lt;br /&gt;  public void start()&lt;br /&gt;  {&lt;br /&gt;      callJsByProto(JS_FUNC_NAME, JS_MESSAGE + " using showDocument :javascript protocol method");&lt;br /&gt;            &lt;br /&gt;      callJsFunc(JS_FUNC_NAME, JS_MESSAGE + " using JSObject method");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * Overide paint with simple text rendering&lt;br /&gt;   *&lt;br /&gt;   * @param g&lt;br /&gt;   */&lt;br /&gt;  @Override&lt;br /&gt;  public void paint(Graphics g)&lt;br /&gt;  {&lt;br /&gt;       g.drawString("The Applet", 20, 20);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * Simple function to show a message&lt;br /&gt;   *&lt;br /&gt;   * @param msg&lt;br /&gt;   */&lt;br /&gt;  public void showMessage(String msg)&lt;br /&gt;  {&lt;br /&gt;      Graphics g = getGraphics();&lt;br /&gt;      g.setColor(Color.RED);&lt;br /&gt;      g.drawString("Message from JS: '" + msg + "'", 20, 40);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * Call a named JS function, passing a single String parameter&lt;br /&gt;   *&lt;br /&gt;   * @param funcName&lt;br /&gt;   * @param msg&lt;br /&gt;   */&lt;br /&gt;  private void callJsByProto(String funcName, String msg)&lt;br /&gt;  {&lt;br /&gt;      try&lt;br /&gt;      {&lt;br /&gt;          getAppletContext().showDocument&lt;br /&gt;              (new URL("javascript:" + funcName + "(\"" + msg +"\")"));&lt;br /&gt;      }&lt;br /&gt;      catch (MalformedURLException ex)&lt;br /&gt;      {&lt;br /&gt;          System.out.println("ex: " + ex.getMessage());&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * callJsFunc - call the named JavaScript function, passing the String msg argument&lt;br /&gt;   *&lt;br /&gt;   * @param funcName&lt;br /&gt;   * @param msg&lt;br /&gt;   */&lt;br /&gt;  private void callJsFunc(String funcName, String msg)&lt;br /&gt;  {&lt;br /&gt;      String jscmd = funcName + "('" + msg + "')";    // Buiild the JavaScript command&lt;br /&gt;      String jsresult = null;&lt;br /&gt;      boolean success = false;&lt;br /&gt;&lt;br /&gt;      try&lt;br /&gt;      {&lt;br /&gt;          Method getw = null;&lt;br /&gt;          Method eval = null;&lt;br /&gt;          Object jswin = null;&lt;br /&gt;          Class c = Class.forName("netscape.javascript.JSObject"); /* works in IE too */&lt;br /&gt;          Method ms[] = c.getMethods();&lt;br /&gt;      &lt;br /&gt;          for (int i = 0; i &amp;lt; ms.length; i++)&lt;br /&gt;          {&lt;br /&gt;              if (ms[i].getName().compareTo("getWindow") == 0)&lt;br /&gt;              {&lt;br /&gt;                  getw = ms[i];&lt;br /&gt;              }&lt;br /&gt;              else if (ms[i].getName().compareTo("eval") == 0)&lt;br /&gt;              {&lt;br /&gt;                  eval = ms[i];&lt;br /&gt;              }&lt;br /&gt;          }&lt;br /&gt;    &lt;br /&gt;          Object a[] = new Object[1];&lt;br /&gt;          a[0] = this;               /* this is the applet */&lt;br /&gt;          jswin = getw.invoke(c, a); /* this yields the JSObject */&lt;br /&gt;          a[0] = jscmd;&lt;br /&gt;          Object result = eval.invoke(jswin, a);&lt;br /&gt;      &lt;br /&gt;          if (result instanceof String)&lt;br /&gt;          {&lt;br /&gt;              jsresult = (String)result;&lt;br /&gt;          }&lt;br /&gt;          else&lt;br /&gt;          {&lt;br /&gt;              jsresult = result.toString();&lt;br /&gt;              success = true;&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;      catch (InvocationTargetException e)&lt;br /&gt;      {&lt;br /&gt;          jsresult = e.getTargetException().getMessage();&lt;br /&gt;      }&lt;br /&gt;      catch (Exception e)&lt;br /&gt;      {&lt;br /&gt;          jsresult = e.getMessage();&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      if (success)&lt;br /&gt;      {&lt;br /&gt;          System.out.println("JS eval succeeded, result is " + jsresult);&lt;br /&gt;      }&lt;br /&gt;      else&lt;br /&gt;      {&lt;br /&gt;          System.out.println("JS eval failed with error " + jsresult);  &lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Debugging:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;1. Using the Java ControlPanel (on 'nix, it is &lt;java_home bin=""&gt; View Settings -&gt; Edit the Java Runtime settings.&lt;br /&gt;&lt;/java_home&gt;&lt;/p&gt;&lt;p style="font-family: courier new; font-weight: bold;"&gt;-agentlib:jdwp=transport=dt_socket,address=&lt;hostname&gt;:&lt;portno&gt;&lt;/portno&gt;&lt;/hostname&gt;&lt;/p&gt;&lt;p&gt;This makes the browser plug-in JRE open a debugging socket connection when launching the applet.&lt;/p&gt;&lt;p&gt;2. Open the Netneans project and attach the debugger in the SocketListen mode, using the same settings as above.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Resources:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://windyroad.org/2006/08/14/reintroducing-javascript-and-hidden-applets-jaha/"&gt;http://windyroad.org/2006/08/14/reintroducing-javascript-and-hidden-applets-jaha/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://java.sun.com/javase/6/docs/technotes/guides/plugin/developer_guide/java_js.html"&gt;http://java.sun.com/javase/6/docs/technotes/guides/plugin/developer_guide/java_js.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-4943541925734196154?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/4943541925734196154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=4943541925734196154' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4943541925734196154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4943541925734196154'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/11/applet-javascript-integration.html' title='Applet &lt;-&gt; Javascript integration'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-3213584927883243870</id><published>2008-11-16T08:29:00.000-08:00</published><updated>2008-12-07T12:44:10.793-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mod_jk'/><category scheme='http://www.blogger.com/atom/ns#' term='Http'/><category scheme='http://www.blogger.com/atom/ns#' term='connector'/><category scheme='http://www.blogger.com/atom/ns#' term='Glassfish'/><category scheme='http://www.blogger.com/atom/ns#' term='httpd'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache'/><title type='text'>Apache httpd 2.x -&gt; Glassfish 2.x mod_jk installation</title><content type='html'>&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Configure Apache Httpd to Glassfish using mod_jk.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;Note&lt;/span&gt;&lt;span&gt;, for Glassfish 3.x this process has been simplified, I'll probably add a blog entry about that sometime soon.&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;br /&gt;In this particular scenario, Apache 2.2.3 is running on Centos 5.2 x86_64 and Glassfish 2ur2 is running on OpenSolaris 10 b101, althought the process should be essentiually the same for any Operating system(s), the paths etc might change.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;Apache httpd setup:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Get the Apache mod_jk connector.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://tomcat.apache.org/connectors-doc/"&gt;http://tomcat.apache.org/connectors-doc/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Binary distribution:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/"&gt;http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Install into modules directory: e.g. &lt;span style="font-weight: bold;"&gt;/etc/httpd/modules&lt;/span&gt; (RH/Centos)&lt;br /&gt;&lt;br /&gt;Configure Apache httpd:&lt;br /&gt;&lt;br /&gt;e.g. for RH/Centos in - &lt;span style="font-weight: bold;"&gt;/etc/httpd/conf.d/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Add ajp worker mapping to httpd.conf (e.g. in /etc/httpd/conf/), in this example using virtual host entries, e.g.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# Virtual host chillipower.com&lt;br /&gt;[VirtualHost 192.168.0.200]&lt;br /&gt;&lt;br /&gt;DocumentRoot /var/www/mywebs/chillipower.com&lt;br /&gt;&lt;br /&gt;ServerName www.chillipower.com&lt;br /&gt;&lt;br /&gt;ServerAlias chillipower.com&lt;br /&gt;&lt;br /&gt;DirectoryIndex index.html index.php index.htm index.shtml&lt;br /&gt;&lt;br /&gt;JkMount /chillipower*/* worker1&lt;br /&gt;&lt;br /&gt;[/VirtualHost]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Note in the above, the url to the glassfish context would be reached using http://mydomain.com/chillipower/ where in this instance the trailing / is important.&lt;br /&gt;&lt;br /&gt;Load and configure the module (e.g. place this in /etc/httpd/conf.d/mod_jk.conf)&lt;br /&gt;&lt;br /&gt;(all *.conf files are loaded by httpd.conf (before any virtual hosts etc) from the /conf.d directory in typical setups, so we can add a new mod_jk.conf and it will be loaded automatically)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;LoadModule jk_module /etc/httpd/modules/mod_jk.so&lt;br /&gt;JkWorkersFile /etc/httpd/conf.d/worker.properties&lt;br /&gt;# Where to put jk logs&lt;br /&gt;JkLogFile /var/log/httpd/mod_jk.log&lt;br /&gt;# Set the jk log level [debug/error/info]&lt;br /&gt;JkLogLevel debug&lt;br /&gt;# Select the log format&lt;br /&gt;JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "&lt;br /&gt;# JkOptions indicate to send SSL KEY SIZE,&lt;br /&gt;JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories&lt;br /&gt;# JkRequestLogFormat set the request format&lt;br /&gt;JkRequestLogFormat "%w %V %T"&lt;br /&gt;# Send all jsp requests to GlassFish&lt;br /&gt;JkMount /*.jsp worker1&lt;br /&gt;# Send all glassfish-test requests to GlassFish&lt;br /&gt;JkMount /chillipower/* worker1&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Add worker.properties file to configure the ajp worker, /etc/httpd/conf.d/worker.properties&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# Define 1 real worker using ajp13&lt;br /&gt;worker.list=worker1&lt;br /&gt;# Set properties for worker1 (ajp13)&lt;br /&gt;worker.worker1.type=ajp13&lt;br /&gt;#worker.worker1.host=localhost.localdomain&lt;br /&gt;worker.worker1.host=192.168.3.101&lt;br /&gt;worker.worker1.port=8009&lt;br /&gt;worker.worker1.lbfactor=50&lt;br /&gt;worker.worker1.cachesize=10&lt;br /&gt;worker.worker1.cache_timeout=600&lt;br /&gt;worker.worker1.socket_keepalive=1&lt;br /&gt;worker.worker1.socket_timeout=300&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Glashfish setup:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Download Apace Tomcat 5.5.16 -&gt; &lt;a href="http://archive.apache.org/dist/tomcat/tomcat-5/"&gt;http://archive.apache.org/dist/tomcat/tomcat-5/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;copy the tomcat-ajp.jar to the glassfish lib folder. e.g.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;cp $CATALINA_HOME/server/lib/tomcat-ajp.jar&lt;br /&gt;$GLASSFISH_HOME/lib/.&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;Also, download and copy the commons logging and commons modeller jar files to $GLASSFISH_HOME/lib&lt;br /&gt;&lt;br /&gt;Commons logger -&gt; commons-logging-1.1.1.jar from &lt;a href="http://commons.apache.org/downloads/download_logging.cgi"&gt;http://commons.apache.org/downloads/download_logging.cgi&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Commons modeler -&gt; commons-modeler-2.0.1.jar from &lt;a href="http://commons.apache.org/downloads/download_modeler.cgi"&gt;http://commons.apache.org/downloads/download_modeler.cgi&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Restart Glassfish...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;References:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a href="http://weblogs.java.net/blog/jfarcand/archive/2006/03/running_glassfi_1.html"&gt;http://weblogs.java.net/blog/jfarcand/archive/2006/03/running_glassfi_1.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-3213584927883243870?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/3213584927883243870/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=3213584927883243870' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/3213584927883243870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/3213584927883243870'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/11/apache-httpd-2x-glassfish-2x-modjk.html' title='Apache httpd 2.x -&gt; Glassfish 2.x mod_jk installation'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-6503498383475872215</id><published>2008-11-09T10:17:00.001-08:00</published><updated>2008-11-22T02:30:45.512-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WADL'/><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='code gen'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><category scheme='http://www.blogger.com/atom/ns#' term='REST Describe'/><title type='text'>c# code generation added rest describe code gen</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Announcement: c# code generation added to google rest describe code gen api:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;At last, the google rest describe code gen api now has a c# code generator. Targeting c# .net 3.5 WCF.&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;This gives an easy route from existing services or WADL to c# client code/framework. I hope to be blogging about it soon, with some details of how it works and any limitations you shoud be aware of.&lt;span style="font-weight: bold;"&gt;.&lt;/span&gt;.&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-6503498383475872215?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/6503498383475872215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=6503498383475872215' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6503498383475872215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6503498383475872215'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/11/c-code-generation-added-rest-describe.html' title='c# code generation added rest describe code gen'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-6310899166829041211</id><published>2008-11-03T13:49:00.000-08:00</published><updated>2008-11-22T02:33:06.959-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Security context'/><category scheme='http://www.blogger.com/atom/ns#' term='CentOS'/><category scheme='http://www.blogger.com/atom/ns#' term='httpd'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache'/><category scheme='http://www.blogger.com/atom/ns#' term='SELinux'/><title type='text'>I'm back! Some notes on SELinux and Apache HTTPD</title><content type='html'>Finally! I took some time out, with a big road trip to America and various other activities going on, I'd not had the time to keep the blog going. Anyway, things are back to normal now and after a recent hard disk failure I unexpectedly found myself setting up a new secure web server using CentOS 5.2 x64 and Apache Httpd 2.2.3 and PHP5. Later I'll add in a Java EE application server for more dynamic/web app stuff.&lt;br /&gt;&lt;br /&gt;Thought that I'd type up some small notes on a problem I'd come across before, when trying to setup Mercurial HG-WEB in directories (or sym links) to directories outside of the usual /var/www&lt;br /&gt;&lt;br /&gt;One of the problems may come from &lt;span style="font-weight: bold;"&gt;SELinux&lt;/span&gt;. Whilst it's tempting to turn it off, for something facing the public on the web - this would be a real last resort!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Security Contexts: - a quick explanation&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Files and directories have security contexts. These can be seen using ls, e.g.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;ls -aZ&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;By default Apache Httpd cannot access all files, it can access those with &lt;span style="font-weight: bold;"&gt;httpd_sys_content_t&lt;/span&gt; context types.&lt;br /&gt;&lt;br /&gt;For example user home directories come with the context &lt;span style="font-weight: bold;"&gt;home_root_t&lt;/span&gt; which will give a permission denied type error if httpd tries to serve up files from there (or anywhere below!). Another common security context is  default_t which will be assigned as the default for new files and folders.&lt;br /&gt;&lt;br /&gt;An important difference between &lt;span style="font-weight: bold;"&gt;mv&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;cp&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;cp creates a new context (inherits), wheras mv actually moves it (unmodified). So a common gotcha is to create files in the user home directory and mv them to /var/www/... but this keeps the home context &lt;span style="font-weight: bold;"&gt;home_root_t&lt;/span&gt; - hence this creates the permission denied error.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Some handy commands:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-family:courier new;"&gt;chcon -R -h -t httpd_sys_content_t /test/&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;change the directory /test/ to httpd_sys_content security context type&lt;span style="font-weight: bold;"&gt;, &lt;/span&gt;recursively but not following sym-links.&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;i.e. the above would enable /test/ to be served by a documentroot in Httpd&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;If SELinux is suspected for the permissions problems (as opposed to httpd configuration), the SELinux restrictions will appear in the message log:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-family:courier new;"&gt;tail -f /var/log/messages&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;SELinux boolean flags:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;can be read with&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;getsebool httpd_enable_cgi&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;and set with&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;setsebool httpd_enable_cgi true&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Invoke the simple GUI configurator with: &lt;span style="font-weight: bold;"&gt; &lt;span style="font-family:courier new;"&gt;system-config-securitylevel&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Restore the file context&lt;/span&gt; (say after an mv command)&lt;span style="font-weight: bold;"&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;restorecon -R -v ./folderwithwrongcontext/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Additional SE Linux parameters:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;Enable&lt;/span&gt;&lt;span&gt; Samba &lt;/span&gt;&lt;span&gt;to access ho&lt;/span&gt;&lt;span&gt;me dirs&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;setsebool -P samba_enable_home_dirs=1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Additional Resources:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Good overview in this link: &lt;a href="http://docs.fedoraproject.org/selinux-apache-fc3/sn-simple-setup.html"&gt;http://docs.fedoraproject.org/selinux-apache-fc3/sn-simple-setup.html&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-6310899166829041211?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/6310899166829041211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=6310899166829041211' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6310899166829041211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6310899166829041211'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/11/im-back-some-notes-on-selinux-and.html' title='I&apos;m back! Some notes on SELinux and Apache HTTPD'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-9027401727558878093</id><published>2008-07-18T02:50:00.000-07:00</published><updated>2008-11-23T10:35:19.783-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>An interesting query for potential optimisation...?</title><content type='html'>Just wanted to capture a query I was working on yesterday which was slightly 'interesting' in that it consists of a couple of layers of left outer joins and the joining with a derived aggregation table - and time permitting I'd like to revisit it because I'm sure it can be improved / optimised (but it is functionally correct).&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;select&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  t1.tid,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  t1.alias as alias,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  t1.asset_label as asset_label,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  t1.terminal_id as terminal_id,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  t1.location_address as terminal_address,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  t1.last_updated as last_connection,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  t1.name as questionnaire_name,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  t1.questionnaire_id as questionnaire_id,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  t1.state as state,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  t1.value as publishing_state,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  response_stats.rcount as rcount,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  response_stats.last_response as last_response&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;from&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  (select &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     t.id as tid,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     t.alias,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     t.asset_label,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     t.terminal_id,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     t.location_address,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     t.last_updated,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     qnr.name,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     qnr.id as questionnaire_id,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     qnr.status as state,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     at.value&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   from terminal t&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     left outer join&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       (delivery_stats d,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        terminal_activity ta,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        questionnaire qnr,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        activity_type at)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     on &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       d.terminal_id = t.id&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       and d.terminal_activity_id = ta.id&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       and ta.questionnaire_id = qnr.id&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       and ta.activity_type = at.id&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       and qnr.status = "L"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     where&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       t.id in(1, 20, 21, 22, 23)) as t1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;left outer join&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  (select&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     tcq.terminal_id tid,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     tcq.questionnaire_id qid,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     count(*) rcount,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     max(uploaded_date) as last_response &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   from&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     tcquestionnaire tcq&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   group by&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     tcq.terminal_id, tcq.questionnaire_id) as response_stats&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;on &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  t1.tid = response_stats.tid&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  and t1.questionnaire_id = response_stats.qid;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Whilst technically correct - I'm not entirely satisfied of the need for the the top level left outer join which creates a full derived table rather than having a correlated sub-query / nested join that contains only the rows actually relevant to the result set. Something to think about perhaps, on a rainy (very rainy!?!) day :)&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-9027401727558878093?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/9027401727558878093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=9027401727558878093' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/9027401727558878093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/9027401727558878093'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/07/interesting-query-for-potential.html' title='An interesting query for potential optimisation...?'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-8345047585172416240</id><published>2008-07-16T12:03:00.000-07:00</published><updated>2008-11-22T02:35:12.152-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vmware'/><category scheme='http://www.blogger.com/atom/ns#' term='vmware server 2.0'/><title type='text'>Update vmware server 2.0 from beta 2 to rc1</title><content type='html'>Just some quick notes on this "upgrade" from beta 2 to rc1 - which is more of a reinstall!&lt;br /&gt;&lt;br /&gt;Note: pre-release versions forcefully expire (becomes rather apparent when starting a vmware instance) - but the error message is not that clear - "Failed to start, General error" may appear in the logs as the error but is preceded by a more subtle "version expired, there's a new version out" type message - which is the actual problem.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Basic steps:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Stop/suspend all vm's&lt;br /&gt;&lt;br /&gt;Stop services&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#service vmware stop&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;[Recommended - move VMs (for safety/paranoia!), simply mv the whole vmware directory]&lt;br /&gt;[Recommended - good time to check system is up-to-date]&lt;br /&gt;&lt;br /&gt;Remove/uninstall existing version (based on 2.0 beta2):&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#rpm -e VMware-server-e.x.p-84186.x86_64&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;install rc1&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#rpm -ivh VMware-server-2.0.0-101586.x86_64.rpm&lt;/span&gt;&lt;br /&gt;or&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#rpm -Uvh VMware-server-2.0.0-101586.x86_64.rpm&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;configure as per normal&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#vmware-config.pl&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;check running via web management console&lt;br /&gt;&lt;br /&gt;service vmware stop&lt;br /&gt;&lt;br /&gt;move vmware images back&lt;br /&gt;&lt;br /&gt;start services again&lt;br /&gt;&lt;br /&gt;Note, VM images have to be reloaded into the VM inventory - apart from that everything is entirely straightforward!&lt;br /&gt;&lt;br /&gt;Alternative approach from tarball:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#tar xvfz VMware-server-*.tar.gz&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#vmware-server-distrib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#vmware-install.pl&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Some relevant links:&lt;br /&gt;&lt;br /&gt;http://communities.vmware.com/thread/154503?tstart=0&lt;br /&gt;http://communities.vmware.com/thread/154668?tstart=0&lt;br /&gt;http://communities.vmware.com/message/901195;jsessionid=77A29EE9DF1ADEBF37027EB347D638F3&lt;br /&gt;http://www.cyberciti.biz/tips/vmware-on-centos5-rhel5-64-bit-version.html&lt;br /&gt;http://kirkpbm.wordpress.com/category/vmware-server/&lt;br /&gt;http://communities.vmware.com/docs/DOC-4111&lt;br /&gt;http://communities.vmware.com/thread/143674&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-8345047585172416240?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/8345047585172416240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=8345047585172416240' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8345047585172416240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8345047585172416240'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/07/update-vmware-server-20-from-beta-2-to.html' title='Update vmware server 2.0 from beta 2 to rc1'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-7465286937725559640</id><published>2008-07-12T14:03:00.000-07:00</published><updated>2009-02-06T16:35:53.689-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='image-update'/><category scheme='http://www.blogger.com/atom/ns#' term='b93'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenSolaris'/><title type='text'>OpenSolaris - upgrade to b93</title><content type='html'>More notes on OpenSolaris image-update, to b93 (in my case from b91)&lt;br /&gt;&lt;br /&gt;See this thread &lt;a href="http://opensolaris.org/jive/thread.jspa?messageID=258127&amp;amp;#258127"&gt;http://opensolaris.org/jive/thread.jspa?messageID=258127&amp;amp;#258127&lt;/a&gt; discussing the problem and it's solution.&lt;br /&gt;&lt;br /&gt;Performing the standard image-update failed with an error of the form:&lt;br /&gt;&lt;br /&gt;&gt; pkg: attempt to mount opensolaris-3 failed.&lt;br /&gt;&gt; pkg: image-update cannot be done on live image&lt;br /&gt;&lt;br /&gt;The problem is caused by:&lt;br /&gt;&lt;br /&gt;2387 libbe.so:beCopy() frees nvlist variables before using them&lt;br /&gt;&lt;a href="http://defect.opensolaris.org/bz/show_bug.cgi?id=2387"&gt;http://defect.opensolaris.org/bz/show_bug.cgi?id=2387&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So, time to find a work around. This wasn't as seamless as perhaps it should have been, this is how I did it:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#beadm list&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&gt; my active BE was opensolaris-3, which I was booted in&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#export PKG_CLIENT_TIMEOUT=2000&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#pfexec pkg refresh&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;create a temp BE&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#pfexec beadm create opensolaris-4&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;mount it as /mnt&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#pfexec mount -F zfs rpool/ROOT/opensolaris-4 /mnt&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;update it&lt;br /&gt;#pfexec pkg -R /mnt image-update&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#pfexec beadm unmount opensolaris-4&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#pfexec beadm activate opensolaris-4&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;reboot into BE opensolaris-4 build 93&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Note: &lt;/span&gt;b92 was skipped (not released)!&lt;br /&gt;&lt;br /&gt;Also, this failed _every time_ when attempting it from desktop terminal (graphical login) - but worked as soon as I did the same thing from an ssh terminal!&lt;br /&gt;&lt;br /&gt;Blog for installing / configuring mysql as service using gui &lt;a href="http://weblogs.java.net/blog/bleonard/archive/2008/06/opensolaris_200_3.html"&gt;http://weblogs.java.net/blog/bleonard/archive/2008/06/opensolaris_200_3.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Additional notes:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;BE_PRINT_ERR=true can be used to output diagnostic error logs from the be process,&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;&lt;br /&gt;BE_PRINT_ERR=true beadm create test&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-7465286937725559640?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/7465286937725559640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=7465286937725559640' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/7465286937725559640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/7465286937725559640'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/07/open-solaris-to-b93.html' title='OpenSolaris - upgrade to b93'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-2444736689978326260</id><published>2008-07-10T06:21:00.000-07:00</published><updated>2008-11-22T02:37:09.659-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delegates'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>C# delegates</title><content type='html'>&lt;span style="font-weight: bold;"&gt;A quick note on c# delegate functions:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I found the standard way to define delegates a little clumsy and verbose in some situations, for example when wanting to pass a function to a .Invoke method of a control to add it to its thread work queue. In this situation the delegate's purpose is really just to pass the method to the invoker, there is no other use of the delegate so declaring it at class level is a much wider scope that I would like. What I wanted is a more terse, compact and locally scoped way to achieve the same thing, here it is:&lt;br /&gt;&lt;br /&gt;The simple way:&lt;br /&gt;&lt;br /&gt;Declare delegate within class, e.g.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;font-family:courier new;" &gt;public delegate void updateStockView(Stock[] stocks);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;use to create a new delegate instance to pass to invoke on a  control, e.g.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;instrumentDgv1.Invoke(new updateStockView(this.&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;updateStockView&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;), new object[] {instrumentResponse.Stocks});&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This approach, whilst perfectly valid feels a little cumbersome. Firstly the delegate is at an uneccessarily high level of scope, secondly, the statment requires a new instance of the delegate to be created, passing the delegate's parameters down as an object array.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A more compact form:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;instrumentDgv1&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;.Invoke((MethodInvoker)delegate { this.&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;updateStockView&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;(&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;instrumentResponse.Stocks&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;); });&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here we see, no unnecessary declaration of the delegate type, no creation of the delegate instance, no passing of parameters as an object array - all round much tighter syntax for this type of use.&lt;br /&gt;&lt;br /&gt;The key thing to make this work is the &lt;span style="font-weight: bold;"&gt;MethodInvoker &lt;/span&gt;cast. MethodInvoker is from the System.Windows.Forms namespace and is used to cast the existing method to the delegate type without requiring the declaration/instantiation of a new delegate.&lt;br /&gt;&lt;br /&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-2444736689978326260?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/2444736689978326260/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=2444736689978326260' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2444736689978326260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2444736689978326260'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/07/c-delegates.html' title='C# delegates'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-2387157710593283928</id><published>2008-07-07T13:20:00.000-07:00</published><updated>2008-11-22T02:38:19.077-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Netbeans 6.1'/><category scheme='http://www.blogger.com/atom/ns#' term='library problems'/><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='JSR-311'/><title type='text'>Netbeans 6.1 Rest JSR-311 RI library problem</title><content type='html'>Found a minor problem with Netbeans 6.1 and Rest (Jersey RI) today, thought I'd capture the problem and solution.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Symptom:&lt;/span&gt; Can't launch a Rest application using Jersey (JSR-311 RI) libraries - error given is:&lt;br /&gt;&lt;br /&gt;HTTP status 500&lt;br /&gt;&lt;p&gt;&lt;b&gt;exception&lt;/b&gt; &lt;/p&gt;&lt;pre&gt;javax.servlet.ServletException: java.lang.NoSuchMethodError: javax.servlet.jsp.JspFactory.getJspApplicationContext(Ljavax/servlet/ServletContext;)Ljavax/servlet/jsp/JspApplicationContext;&lt;br /&gt; org.apache.jasper.servlet.JspServlet.service(JspServlet.java:274)&lt;br /&gt; javax.servlet.http.HttpServlet.service(HttpServlet.java:803)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Because the Jersey (JSR-311 RI) libraries include jsp 2.0 &lt;span style="font-weight: bold;"&gt;jsp-api-2.0-20040521.jar&lt;/span&gt; from &lt;span style="font-family: courier new;"&gt;Netbeans6.1\enterprise5\modules\ext\rest\&lt;/span&gt; which is an older version of the JSP API.&lt;br /&gt;&lt;br /&gt;Fix, copy a newer jsp in or remove the entry from the library definition and add a newer jsp library in.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example Solution:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Go to tools\libraries&lt;br /&gt;Select the Jersey libary&lt;br /&gt;In the Library classpath, remove the offending &lt;span style="font-weight: bold;"&gt;jsp-api-2.0-20040521.jar&lt;br /&gt;&lt;/span&gt;Now add the newer JSP libary, e.g. Netbeans 6.1 ships with servlet2.5-jsp2.1-api.jar one level up in the &lt;span style="font-family: courier new;"&gt;Netbeans6.1\enterprise5\modules\ext\&lt;/span&gt; directory.&lt;br /&gt;Remove the Jersey libraries from your project (if already added).&lt;br /&gt;Re-add the Jersey libraries to your project and recompile - problem solved.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-2387157710593283928?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/2387157710593283928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=2387157710593283928' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2387157710593283928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2387157710593283928'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/07/netbeans-61-rest-jsr-311-ri-library.html' title='Netbeans 6.1 Rest JSR-311 RI library problem'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-444220139396503794</id><published>2008-06-25T03:22:00.001-07:00</published><updated>2008-11-22T02:39:07.083-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Stunnel'/><category scheme='http://www.blogger.com/atom/ns#' term='SSL'/><category scheme='http://www.blogger.com/atom/ns#' term='HTTPS'/><title type='text'>Stunnel and wcf 3.5 https testing, an easy dev setup</title><content type='html'>Just some quick notes:&lt;br /&gt;&lt;br /&gt;Stunnel can act as an https proxy which is very convenient when you need to test / develop against https but don't want to set up or use a proper environment with real certificates etc in the short term.&lt;br /&gt;&lt;br /&gt;I wanted to capture some packet traces of WCF3.5 over an https keep alive channel to a Jboss app server serving normal http on the default 8080 - here's what I did:&lt;br /&gt;&lt;br /&gt;Download / install Stunnel. The installation process creates a default .pem self signed certificate (sufficient for dev purposes).&lt;br /&gt;&lt;br /&gt;Default Stunnel config is in stunnel.conf (or stunnel.cfg on Linux).&lt;br /&gt;&lt;br /&gt;For simple https proxying from the standard port 443 to port 8080, the basic condensed configuration in stunnel.conf looks like:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;cert = stunnel.pem&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;socket = l:TCP_NODELAY=1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;socket = r:TCP_NODELAY=1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;debug = 7&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;output = stunnel.log&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[https]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;accept  = 443&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;connect = 8080&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;where we can see the default certificate is being used and I've enabled logging. HTTPS listening on 443 and connecting through to HTTP on 8080 (happened to be Jboss in this instance).&lt;br /&gt;&lt;br /&gt;Simple enough, what next. Running the WCF client application - it will barf over the certificate not being trustworthy (an error of the form):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;login failed Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Overriding .NET WCF 3.5 default certificate policy to allow all certs for testing/dev purposes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;For test/dev purposes it's often handy to allow all certificates.&lt;br /&gt;&lt;br /&gt;What you can do is override the certificate checking policy to "say yes to everything" (Remember to take this out for product release!)&lt;br /&gt;&lt;br /&gt;The code looks something like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;using System.Net;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;using System.Security.Cryptography.X509Certificates;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;using System.Net.Security;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;// ***** WARNING - to be removed for release! *****&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ServicePointManager.ServerCertificateValidationCallback +=&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                        delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                    { return true; };&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Which is using an &lt;span style="font-weight: bold;"&gt;anonymous delegate callback&lt;/span&gt; to return true in all cases (true = accept) - which keeps the code nice and compact.&lt;br /&gt;&lt;br /&gt;If you're specifically testing keep alive then these additional parameters for stunnel.conf control how the proxy behaves in terms of connection persistence:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;session = 300&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;TIMEOUTclose = 0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;TIMEOUTidle = 180&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-444220139396503794?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/444220139396503794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=444220139396503794' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/444220139396503794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/444220139396503794'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/06/stunnel-and-wcf-35-https-testing-easy.html' title='Stunnel and wcf 3.5 https testing, an easy dev setup'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-6900733337696177690</id><published>2008-06-20T13:05:00.000-07:00</published><updated>2008-11-22T02:39:53.846-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Open Solaris'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenSolaris'/><title type='text'>OpenSolaris 2008.05 &amp; update to &gt;= b90</title><content type='html'>With the demise of SXDE I thought I'd prepare for life with OpenSolaris...&lt;br /&gt;&lt;br /&gt;Currently on build 90, 2008.05 represents build 86.&lt;br /&gt;&lt;br /&gt;Installation of OpenSolaris 2008.05 from the Live CD (1 CD) is a breeze, simply boot from the CD (this took some time under VMWare!), have a play then click the install link on the desktop - great!&lt;br /&gt;&lt;br /&gt;OS2008.05 uses ZFS and IPS - so this is a good starting point and upgradable using a package management system rather like we've all come to expect from the Linux world :)&lt;br /&gt;&lt;br /&gt;Once installed, you can use &lt;span style="font-weight: bold; font-style: italic;"&gt;pkg image-update&lt;/span&gt; to udate to the latest build of OpenSolaris, here are some quick notes:&lt;br /&gt;&lt;br /&gt;set a timeout to avoid disapointment during the udate process!&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;#export PKG_CLIENT_TIMEOUT=2000&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;#pkg refresh&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;#pfexec pkg image-update&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;# important - do this before reboot!&lt;/span&gt; (or your reboot won't [boot])&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mail.opensolaris.org/pipermail/indiana-discuss/attachments/20080606/94969481/attachment-0003.txt"&gt;http://mail.opensolaris.org/pipermail/indiana-discuss/attachments/20080606/94969481/attachment-0003.txt&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Which boils down to:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#beadm list&lt;/pre&gt;Check the active on reboot name, e.g. opensolaris-1&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#pfexec mount -F zfs rpool/ROOT/opensolaris-1 /mnt&lt;br /&gt;&lt;br /&gt;#pfexec /mnt/boot/solaris/bin/update_grub -R /mnt&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A guide for OpenSolaris installation under vmware:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.sun.com/souvik/entry/getting_started_with_opensolaris_2008"&gt;http://blogs.sun.com/souvik/entry/getting_started_with_opensolaris_2008&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Another good thread: &lt;a href="http://opensolaris.org/jive/thread.jspa?threadID=62982&amp;amp;tstart=0"&gt;http://opensolaris.org/jive/thread.jspa?threadID=62982&amp;amp;tstart=0&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Install Java JDK and Netbeans:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.blogger.com/%20http://blogs.sun.com/souvik/entry/getting_started_with_opensolaris_2008"&gt;&lt;br /&gt;http://blogs.sun.com/souvik/entry/getting_started_with_opensolaris_2008&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#zcat jdk-6u6-solaris-i586.tar.Z | tar -xf - &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;#pfexec pkgadd -d . SUNWj6dev SUNWj6cfg SUNWj6man SUNWj6dmo&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;NB: after installing the 32bit version the 64bit extensions can be installed but don't do this if you want to use applets or web start.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Install FireFox 3:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://opensolaris.org/jive/thread.jspa?messageID=250311&amp;amp;tstart=0"&gt;http://opensolaris.org/jive/thread.jspa?messageID=250311&amp;amp;tstart=0&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Installing mysql etc:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;#&lt;span style="font-family: courier new;"&gt;pfexec pkg install SUNWapch22 SUNWmysql5 SUNWapch22m-php5 SUNWphp524-mysql&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.sun.com/natarajan/entry/how_to_install_apache_php"&gt;http://blogs.sun.com/natarajan/entry/how_to_install_apache_php&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;Check platform 32/64 bit:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#isainfo -b&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-6900733337696177690?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/6900733337696177690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=6900733337696177690' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6900733337696177690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/6900733337696177690'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/06/opensolaris-200805.html' title='OpenSolaris 2008.05 &amp; update to &gt;= b90'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-7651999384537102528</id><published>2008-06-02T06:40:00.001-07:00</published><updated>2008-11-22T02:40:49.184-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='POX'/><category scheme='http://www.blogger.com/atom/ns#' term='Service model'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF3.5'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>Integrating REST POX web services and .NET WCF</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Notes:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;WCF 3.5 supports REST POX services using the web service model.&lt;br /&gt;&lt;br /&gt;WebHttpBinding supports cookies for session support etc, e.g:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WebHttpBinding webHttpBinding = new WebHttpBinding();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                webHttpBinding.AllowCookies = true;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                using (ChannelFactory&lt;iservice&gt; cf = new ChannelFactory&lt;iservice&gt;(webHttpBinding, hostPath))&lt;/iservice&gt;&lt;/iservice&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                { ...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Issues:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;WebInvoke method POST: post data sent only as JSON or XML - no support for simple form encoded parameters.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;General inflexibility when mixing types of data or overloading services make it harder to leverage existing services that support existing AJAX/rich Internet systems.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Blogs, articles and useful resources:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bitworking.org/news/125/REST-and-WS"&gt;http://bitworking.org/news/125/REST-and-WS&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;HTTP Programming with WCF and the .NET Framework 3.5 - &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc135976.aspx"&gt;http://msdn.microsoft.com/en-us/magazine/cc135976.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.aspx"&gt;http://msdn.microsoft.com/en-us/library/system.servicemodel.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://hyperthink.net/blog/2008/01/18/WCF+Web+Programming+Model+Documentation.aspx"&gt;http://hyperthink.net/blog/2008/01/18/WCF+Web+Programming+Model+Documentation.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb412176.aspx"&gt;http://msdn.microsoft.com/en-us/library/bb412176.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Rick Strahl's &lt;/span&gt;excellent articles:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; REST-Based Ajax Services with WCF in .NET 3.5 &lt;a href="http://www.code-magazine.com/Article.aspx?quickid=080014"&gt;http://www.code-magazine.com/Article.aspx?quickid=080014&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt; WCF REST Configuration for ASP.net AJAX and plain REST Services &lt;a href="http://www.west-wind.com/WebLog/posts/310747.aspx"&gt;http://www.west-wind.com/WebLog/posts/310747.aspx&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt; jQuery AJAX calls to a WCF REST Service &lt;a href="http://www.west-wind.com/weblog/posts/324917.aspx"&gt;http://www.west-wind.com/weblog/posts/324917.aspx&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;How to consume REST services with WCF - &lt;a href="http://blogs.msdn.com/pedram/archive/2008/04/21/how-to-consume-rest-services-with-wcf.aspx"&gt;http://blogs.msdn.com/pedram/archive/2008/04/21/how-to-consume-rest-services-with-wcf.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Simple example with DataContract: &lt;a href="http://dev.aol.com/node/595"&gt;http://dev.aol.com/node/595&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A set of WCF tutorials:&lt;br /&gt;&lt;a href="http://dotnet.org.za/hiltong/pages/Windows-Communication-Foundation-_2800_Indigo_2900_-Hello-World-Tutorial.aspx"&gt;&lt;br /&gt;http://dotnet.org.za/hiltong/pages/Windows-Communication-Foundation-_2800_Indigo_2900_-Hello-World-Tutorial.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Interesting problem with XML serialiser quota that you could run into at some point:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.timrayburn.net/2007/10/02/XmlSerializerFormat+Plus+Huge+Schema+Equals+Trouble.aspx"&gt;&lt;/a&gt;&lt;a&gt;http://www.timrayburn.net/2007/10/02/XmlSerializerFormat+Plus+Huge+Schema+Equals+Trouble.aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-7651999384537102528?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/7651999384537102528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=7651999384537102528' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/7651999384537102528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/7651999384537102528'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/06/integrating-rest-pox-web-services-and.html' title='Integrating REST POX web services and .NET WCF'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-1449318539893474714</id><published>2008-05-21T02:21:00.000-07:00</published><updated>2008-11-22T02:42:15.791-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WADL'/><category scheme='http://www.blogger.com/atom/ns#' term='REST code gen'/><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='REST Compile'/><category scheme='http://www.blogger.com/atom/ns#' term='REST Describe'/><title type='text'>REST WADL - tools and information</title><content type='html'>I'm interested to use REST or REST-like web services within a traditional thick client (as well as AJAX web apps) - using WADL to describe them (from existing services) and tools to automatically generate client API code (in a variety of languages).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Standards:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JAX-RS (JSR 311) &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Digging around, I come across some interesting articles and blogs, including:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;REST Describe and REST Compile:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Thomas Steiner's blog &lt;a href="http://blog.tomayac.de/index.php?date=2007-03-12&amp;amp;time=17:11:27&amp;amp;perma=Automatic+Multi+Lang.html%20describing%20two%20tools%20to%20be%20developed."&gt;http://blog.tomayac.de/index.php?date=2007-03-12&amp;amp;time=17:11:27&amp;amp;perma=Automatic+Multi+Lang.html describing two tools to be developed.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The REST describe and REST compile project report &lt;a href="http://docs.google.com/View?docid=dgdcn6h3_38fz2vn5"&gt;http://docs.google.com/View?docid=dgdcn6h3_38fz2vn5&lt;/a&gt;&lt;/li&gt;&lt;li&gt;A working on-line example of REST describe &lt;a href="http://tomayac.de/rest-describe/latest/RestDescribe.html"&gt;http://tomayac.de/rest-describe/latest/RestDescribe.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;REST compile/describe screen cast &lt;a href="http://youtube.com/user/tomayac"&gt;http://youtube.com/user/tomayac&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Tech talk video on the tools &lt;a href="http://www.youtube.com/watch?v=hZ2EtAEBpq0"&gt;http://www.youtube.com/watch?v=hZ2EtAEBpq0&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Java.Net resources:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Glassfish - Jersey&lt;/span&gt; - Java.Net WADL project &lt;a href="https://jersey.dev.java.net/what-is-jersey.html"&gt;https://jersey.dev.java.net/what-is-jersey.html&lt;/a&gt; &lt;/li&gt;&lt;li&gt;The &lt;span style="font-weight: bold;"&gt;wadl2java&lt;/span&gt; tool &lt;a href="https://wadl.dev.java.net/"&gt;https://wadl.dev.java.net/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Other resources and blogs:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a href="http://blogs.msdn.com/dotnetinterop/archive/2008/02/06/wadl-and-wsdl-and-rest-oh-my.aspx"&gt;http://blogs.msdn.com/dotnetinterop/archive/2008/02/06/wadl-and-wsdl-and-rest-oh-my.aspx&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;An article on REST WADL &lt;a href="http://searchsoa.techtarget.com/tip/0,289483,sid26_gci1265367,00.html"&gt;http://searchsoa.techtarget.com/tip/0,289483,sid26_gci1265367,00.html&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;Blog by William Martinez Pomares with interesting follow up discussion &lt;a href="http://acoscomp.com/wblog//index.php/a/2007/06/10/wadl_rest_and_wsdl"&gt;http://acoscomp.com/wblog//index.php/a/2007/06/10/wadl_rest_and_wsdl&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;REST Describe and REST Compile tools:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Trying the on-line REST Describe on an existing web service I'd published previously showed promising results.&lt;br /&gt;&lt;br /&gt;The current status of REST Compile is that is supports:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Java&lt;/li&gt;&lt;li&gt;PHP5&lt;/li&gt;&lt;li&gt;Ruby&lt;/li&gt;&lt;li&gt;Python &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;but .Net is not provided as yet.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-1449318539893474714?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/1449318539893474714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=1449318539893474714' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/1449318539893474714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/1449318539893474714'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/05/rest-wadl-tools-and-information.html' title='REST WADL - tools and information'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-742632086017448239</id><published>2008-05-07T01:37:00.000-07:00</published><updated>2008-11-22T02:42:56.325-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DNS'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenSolaris'/><title type='text'>DNS troubles on Solaris</title><content type='html'>After having a little DNS trouble on Solaris, here are some useful links for future reference:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.sun.com/bigadmin/content/selfheal/smf-quickstart.jsp"&gt;http://www.sun.com/bigadmin/content/selfheal/smf-quickstart.jsp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.learning-solaris.com/index.php/configuring-a-dns-server/"&gt;http://www.learning-solaris.com/index.php/configuring-a-dns-server/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.softpanorama.org/DNS/dns_clients.shtml"&gt;http://www.softpanorama.org/DNS/dns_clients.shtml&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-742632086017448239?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/742632086017448239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=742632086017448239' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/742632086017448239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/742632086017448239'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/05/dns-troubles-on-solaris.html' title='DNS troubles on Solaris'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-8219242547452068768</id><published>2008-05-02T05:11:00.000-07:00</published><updated>2008-11-22T02:44:52.299-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vmware tools'/><category scheme='http://www.blogger.com/atom/ns#' term='blank screen'/><category scheme='http://www.blogger.com/atom/ns#' term='upgrade'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenSolaris'/><category scheme='http://www.blogger.com/atom/ns#' term='vmware'/><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Solaris 10, X fails to start after installing VMWare tools</title><content type='html'>Note to self - if this happens restore the pre-installation &lt;span style="font-weight: bold;"&gt;vmware_drv.so&lt;/span&gt; as per this link:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://communities.vmware.com/thread/93366"&gt;http://communities.vmware.com/thread/93366&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;and this one too &lt;a href="http://knowledgefrontier.blogspot.com/2008/04/opensolaris-snv86-on-vmware-with.html"&gt;http://knowledgefrontier.blogspot.com/2008/04/opensolaris-snv86-on-vmware-with.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;which is essentially to do this:&lt;br /&gt;&lt;br /&gt;mv /usr/X11/lib/modules/drivers/vmware_drv.so.BeforeVMwareToolsInstall /usr/X11/lib/modules/drivers/vmware_drv.so&lt;br /&gt;&lt;br /&gt;luckily vmware keeps the old copy, which is handy....&lt;br /&gt;&lt;br /&gt;this is dead easy when you know it. When it only shows up as a problem after a reboot, and the time between installing the tools and rebooting is days or weeks with many other changes in-between - working out the cause and effect relationship is not always so obvious :)&lt;br /&gt;&lt;a href="http://www.sun.com/bigadmin/content/selfheal/smf-quickstart.jsp"&gt;&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-8219242547452068768?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/8219242547452068768/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=8219242547452068768' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8219242547452068768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8219242547452068768'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/05/solaris-10-x-fails-to-start-after.html' title='Solaris 10, X fails to start after installing VMWare tools'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-4358078274049804883</id><published>2008-05-01T13:02:00.001-07:00</published><updated>2008-11-22T02:46:27.605-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Blastwave'/><category scheme='http://www.blogger.com/atom/ns#' term='mod_jk'/><category scheme='http://www.blogger.com/atom/ns#' term='Open Solaris'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenSolaris'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache HTTPD 2.2.x'/><title type='text'>Blastwave for easy Apache http 2.2 and mod_jk, on Solaris SXDE 10</title><content type='html'>&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Goal: &lt;/span&gt;Install mod_jk for Apache http 2.2.x with &lt;span style="font-weight: bold;"&gt;minimal effort&lt;/span&gt;!&lt;br /&gt;&lt;br /&gt;Such that Apache http can be tested as a front for Glassfish 2ur2 (rather than the usual Tomcat) using the same mod_jk connector...&lt;br /&gt;&lt;br /&gt;A handy binary of mod_jk for Solaris and the right version of Apache http didn't seem readily available.&lt;br /&gt;&lt;br /&gt;Here are some quick notes on Solaris, Blastwave, Apache httpd and mod_jk&lt;br /&gt;&lt;br /&gt;Decided to try out the Blastwave software repository for CSW, site is here &lt;a href="http://www.blastwave.org/"&gt;http://www.blastwave.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Rough steps as follows:&lt;br /&gt;&lt;br /&gt;Follow &lt;a href="http://www.blastwave.org/howto.html"&gt;http://www.blastwave.org/howto.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;which is essentially:&lt;br /&gt;&lt;br /&gt;pkgadd -d http://www.blastwave.org/pkg_get.pkg&lt;br /&gt;/opt/csw/bin/pkg-get -i wget&lt;br /&gt;&lt;br /&gt;/opt/csw/bin/pkg-get -i apache2&lt;br /&gt;/opt/csw/bin/pkg-get -i ap2_mod_jk&lt;br /&gt;&lt;br /&gt;and optionally:&lt;br /&gt;&lt;br /&gt;cp -p /var/pkg-get/admin-fullauto /var/pkg-get/admin&lt;br /&gt;&lt;br /&gt;check the exact version installed:&lt;br /&gt;&lt;br /&gt;/opt/csw/apache2/sbin/httpd -v&lt;br /&gt;&lt;br /&gt;stop existing service installed as part of SXDE:&lt;br /&gt;&lt;br /&gt;svcadm disable apache22&lt;br /&gt;svcs apache22&lt;br /&gt;&lt;br /&gt;check lib dsos:&lt;br /&gt;&lt;br /&gt;/opt/csw/apache2/libexec&lt;br /&gt;&lt;br /&gt;start the server manually:&lt;br /&gt;&lt;br /&gt;/opt/csw/apache2/sbin/apachectl start&lt;br /&gt;/opt/csw/apache2/sbin/apachectl stop&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Todo:&lt;br /&gt;&lt;br /&gt;Configure Apache http and mod_jk&lt;br /&gt;Configure Glassfish with libs etc&lt;br /&gt;Test web applications including failure conditions&lt;br /&gt;Set Blastwave installed version as a service&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-4358078274049804883?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/4358078274049804883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=4358078274049804883' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4358078274049804883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4358078274049804883'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/05/blastwave-for-easy-apache-http-22-and.html' title='Blastwave for easy Apache http 2.2 and mod_jk, on Solaris SXDE 10'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-8179269680857792478</id><published>2008-04-23T01:22:00.000-07:00</published><updated>2008-11-22T02:50:53.512-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySQL'/><category scheme='http://www.blogger.com/atom/ns#' term='JNDI'/><category scheme='http://www.blogger.com/atom/ns#' term='JDBC'/><category scheme='http://www.blogger.com/atom/ns#' term='Connection pooling'/><category scheme='http://www.blogger.com/atom/ns#' term='Glassfish'/><title type='text'>Some quick notes on Db Connection pooling in Glassfish</title><content type='html'>To set up a Glassfish connection pooling and JNDI datasource, accessible in your web app, the following things need to be done (tried with Glassfish v2):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Db drivers:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Ensure the relevant JDBC driver is in the Glassfish classpath. I ensured the &amp;lt;glassfish_home&amp;gt;/lib directory contained the latest MySQL J connector. You may need  to restart Glassfish (you probably will if you change the classpath).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Configuration:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Connection Pool:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Set up a connection pool in the Glassfish admin interface (under Resources\JDBC\Connection Pools). In my case for MySQL I was happy to use the defaults initially, which includes:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Datasource classname:&lt;span style="font-family:courier new;"&gt; com.mysql.jdbc.jdbc2.optional.MysqlDataSource&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Resource Type:&lt;span style="font-family:courier new;"&gt; javax.sql.Datasource&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Give the pool a sensible name.&lt;br /&gt;&lt;br /&gt;Once you have set this and the connection details (host, username, password etc) you can use the Ping feature to check the connectivity. If you get errors regarding classes not found, check your classpath / location of the JDBC library jars - possibly restart Glassfish if you have not already.&lt;br /&gt;&lt;br /&gt;Once you have a successful ping, you can move on to configuring the JNDI resource:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;JNDI resource:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Under the Resources\JDBC\JDBC Resources set up a JNDI resource to the pool you just configured (by name), give the JNDI resource a name of the form:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;jdbc/myLovelyDbJNDIResourceName&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ensure the resource is enabled!&lt;br /&gt;&lt;br /&gt;Deployment descriptors, configuration:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;sun-web.xml&lt;/span&gt; - Map the container JNDI to a resource reference in sun-web.xml, e.g. something like:&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- Map container JNDI to resource reference --&amp;gt;&lt;br /&gt;&amp;lt;resource-ref&amp;gt;&lt;br /&gt;&amp;lt;res-ref-name&amp;gt;myDbResourceName&amp;lt;/res-ref-name&amp;gt;&lt;br /&gt;&amp;lt;jndi-name&amp;gt;jdbc/myLovelyDbJNDIResourceName&amp;lt;/jndi-name&amp;gt;&lt;br /&gt;&amp;lt;/resource-ref&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;web.xml&lt;/span&gt; - Map the resource as a datasource reference in web.xml&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- set up resource reference for the web app --&amp;gt;&lt;br /&gt;&amp;lt;resource-ref&amp;gt;&lt;br /&gt;&amp;lt;res-ref-name&amp;gt;myDbResourceName&amp;lt;/res-ref-name&amp;gt;&lt;br /&gt;&amp;lt;res-type&amp;gt;javax.sql.DataSource&amp;lt;/res-type&amp;gt;&lt;br /&gt;&amp;lt;res-auth&amp;gt;Container&amp;lt;/res-auth&amp;gt;&lt;br /&gt;&amp;lt;res-sharing-scope&amp;gt;Shareable&amp;lt;/res-sharing-scope&amp;gt;&lt;br /&gt;&amp;lt;/resource-ref&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Application Code:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In you application code, where you get a connection, you can then use something along the lines of:&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;Connection connection = null;&lt;br /&gt;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;Context env = (Context)new InitialContext().lookup("java:comp/env");&lt;br /&gt;&lt;br /&gt;DataSource pool = (DataSource)env.lookup("myDbResourceName");&lt;br /&gt;&lt;br /&gt;if (pool == null)&lt;br /&gt;{&lt;br /&gt; throw new RuntimeException("Unknown DataSource");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;connection = pool.getConnection();&lt;br /&gt;}&lt;br /&gt;catch(NamingException ne)&lt;br /&gt;{&lt;br /&gt;throw new RuntimeException(ne.getMessage());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return connection;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;br /&gt;Of course, modify the caught, declared to throw exceptions to suit the application design...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;References:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This article is a useful reference point, covering similar information in a slightly more verbose form:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://thestewscope.wordpress.com/2008/01/08/glassfish-v2-ur1-and-mysql-connection-pool/"&gt;http://thestewscope.wordpress.com/2008/01/08/glassfish-v2-ur1-and-mysql-connection-pool/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This forum post also details the deployment descriptor configuration well:&lt;br /&gt;&lt;a href="http://forums.java.net/jive/message.jspa?messageID=264629"&gt;http://forums.java.net/jive/message.jspa?messageID=264629&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-8179269680857792478?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/8179269680857792478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=8179269680857792478' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8179269680857792478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/8179269680857792478'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/04/some-quick-notes-on-db-connection.html' title='Some quick notes on Db Connection pooling in Glassfish'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-2695935115913394273</id><published>2008-04-22T12:47:00.000-07:00</published><updated>2008-11-22T02:52:07.481-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='J2ME'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET CF'/><category scheme='http://www.blogger.com/atom/ns#' term='Java ME'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><category scheme='http://www.blogger.com/atom/ns#' term='Compact framework'/><title type='text'>Mobile development with .NET CF</title><content type='html'>It's been a few days since the last posting, I've been meaning to jot down some notes from the workshop at Microsoft (Reading Uk, 16-April-2008) before anything gets forgotten:&lt;br /&gt;&lt;br /&gt;The aim of the workshop was to discuss the use of the Microsoft .Net Compact framework for mobile application development - including performance issues and technology features. This was in the context of both our existing Java mobile applications and choosing suitable technologies for new projects.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Java ME J9 6.1.1 performance evaluation:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To illustrate the performance we'd experienced with out Java ME applications, we demoed our existing Java ME application running on IBM J9 CDC ppro1.1 on an IPAQ. The response was actually very positive. It was suggested that re-implementing it in .Net would not yield any worth while performance gains but it would most likely create a different set of problems to solve.&lt;br /&gt;&lt;br /&gt;We ran our app with JIT enabled, noverify and nolinenumbers but it was not compiled as a JXE on this occasion. Focus was on running application performance as perceived through the GUI (user perceptions), we did not delve into profiling information. We did not look into start up times, which are roughly similar for both Java and .Net VM based technologies.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;.Net CF:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;.Net CF does provide some benefits, in terms of integration with the Windows operating system (integration with the Windows menu bars etc) that would be worth bearing in mind for future projects. Specifically, notification of docking events could prove very useful in some situations. Native code is supported, as external libraries (not within the assembly) but hooks into the OS API are possible by declaring them within the .Net assembly.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Versions / dependencies:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For .Net development some care regarding versions and dependencies should be considered, for example whilst versions of Windows Mobile from 5.0 onwards _should_ support any version of .Net CF, the same can not be guaranteed for the more variable CE, where platform vendors could load a CE image missing key components required for installing .Net CF. In this scenario it would be important to discover this and engage with the customer and platform vendor to negotiate shipment of hardware with the right image components installed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;.Net CF versions:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;1.0 -&gt; Old original version, no longer targeted by most development&lt;/li&gt;&lt;li&gt;2.0 -&gt; Good baseline with significant improvements (including performance) over 1.0 (required MS VS 2005 IDE to develop).&lt;/li&gt;&lt;li&gt;3.5 -&gt; Current latest version (required MS VS 2008 Pro IDE to develop).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Windows Mobile versions against their CE base:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;WM 2003 'Ozone' -&gt; CE 4.20&lt;/li&gt;&lt;li&gt;WM 5.0    'Magneto' -&gt; based on CE 5 (shipped with .NET v1.0 SP2)&lt;/li&gt;&lt;li&gt;WM 6 .0   'Crossbow' -&gt; based on CE 5.2 (shipped with .NET CF v2.0 SP2 )&lt;/li&gt;&lt;li&gt;WM 6.1 -&gt; CE 5.x ? TBA&lt;/li&gt;&lt;li&gt;WM 7.0 'Photon' -&gt; CE 6.0? TBD&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The next major version of Windows Mobile is anticipated in 2009, but no official details were given. General information suggests a planned release of Windows Mobile 7 in the 2nd half of 2009.&lt;br /&gt;&lt;br /&gt;CE 6.0 removes the 32 process and 32Mb  restrictions:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The 32 process limit raised to 32,768 processes.&lt;/li&gt;&lt;li&gt;The 32 megabyte VM limit raised up to 2GB of private VM is available per process.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Technologies:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Microsoft_SQL_Server" title="Microsoft SQL Server"&gt;&lt;/a&gt;Microsoft SQL Server 2005 Compact Edition is available (shipped with WM 6.0). This can be used stand alone, or connected to a server side SQL server. Can be synchronised with server DB over network. Async and synch operation is possible. Loads in process as a dll (therefore doesn't use any precious process slots, but of course it will consume RAM/processor). This is a very cut down DB, things such as triggers and  stored procedures are not supported.&lt;br /&gt;&lt;br /&gt;Ajax, DOM, Javascript is possible in the browser technology (from WM 6.0 onwards).&lt;br /&gt;&lt;br /&gt;XML is supported - recommended to use XML readers not full blown XML DOM for efficiency reasons.&lt;br /&gt;&lt;br /&gt;XSLT - it was not clear weather XSLT was supported on the platform, either in the browser or as .Net libraries.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Windows Mobile limitations (until WM 7.0):&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;32 process limit&lt;/li&gt;&lt;li&gt;32Mb memory limit&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Windows Mobile can close applications when it starts to run low on resources - so applications should be developed with this in mind. The OS will pick the lowest application in the Z-order that is inactive. Notification events are sent but if the application doesn't respond gracefully it could receive hard termination!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;.Net development tools:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Visual studio is the only supported option (no free express version for CF 3.5 available at this time).&lt;br /&gt;&lt;br /&gt;Optimisation tools were not generally recommended - they advocate letting it run 'as-is' but rather to concentrate efforts on getting the design right.&lt;br /&gt;&lt;br /&gt;It was admitted that profiling tools were somewhat weak at the moment - but this is an area they are actively addressing.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Code signing:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;We were warned that some platform vendors have removed the root CA from the device, which means that the only option for getting the application code signed would be to go through the device vendor (this is something that would need to be highlighted and planed in early in the project).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Testing:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The need for thorough and extended testing was highlighted. Mainly due to the additional use cases that can occur on a mobile platform that are less likely or non-existent on a traditional desktop pc system, for example:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Memory cards being removed&lt;/li&gt;&lt;li&gt;Wireless signal poor / dropped&lt;/li&gt;&lt;li&gt;Flat battery, battery removal&lt;/li&gt;&lt;li&gt;Unexpected key presses from special function keys on the device&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;.Net configuration:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It's possible to configure the platform .Net CF using a configuration file:&lt;span style="color: rgb(31, 73, 125);font-family:Calibri;font-size:85%;"  &gt;&lt;span style="color: rgb(31, 73, 125);font-family:Calibri;font-size:11;"  lang="EN-GB" &gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/bb629366.aspx"&gt;&lt;span&gt;&lt;span&gt;http://msdn2.microsoft.com/en-us/library/bb629366.aspx&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Software updates:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Whilst there is no application support for software updates (apart from the M  ) there are some software components that can be used as a basis for providing this, the Mobile Client Software Factory and the Mobile Updater.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=F9176708-9F57-4C0F-97FB-F9C65A9BBF22&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyID=F9176708-9F57-4C0F-97FB-F9C65A9BBF22&amp;amp;displaylang=en&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/bb629366.aspx"&gt;&lt;span&gt;&lt;span&gt;http://msdn2.microsoft.com/en-us/library/bb629366.aspx&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Additional links and info:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Mobile Dev centre &lt;a href="http://msdn2.microsoft.com/en-gb/windowsmobile/default.aspx"&gt;http://msdn2.microsoft.com/en-gb/windowsmobile/default.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Application developer consulting service &lt;a href="http://www.microsoft.com/uk/adc"&gt;http://www.microsoft.com/uk/adc&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Libraries and widgets:&lt;br /&gt;&lt;br /&gt;Mobility Marvels: &lt;a href="http://msdn2.microsoft.com/en-us/windowsmobile/bb250537.aspx"&gt;http://msdn2.microsoft.com/en-us/windowsmobile/bb250537.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Mobile Controls: &lt;a href="http://www.asp.net/mobile/"&gt;http://www.asp.net/mobile/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-2695935115913394273?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/2695935115913394273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=2695935115913394273' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2695935115913394273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2695935115913394273'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/04/mobile-development-with-net-cf.html' title='Mobile development with .NET CF'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-2490777846324323867</id><published>2008-04-15T13:00:00.001-07:00</published><updated>2008-11-22T02:52:57.761-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xephyr'/><category scheme='http://www.blogger.com/atom/ns#' term='XMing'/><category scheme='http://www.blogger.com/atom/ns#' term='Open Solaris'/><category scheme='http://www.blogger.com/atom/ns#' term='XNest'/><category scheme='http://www.blogger.com/atom/ns#' term='X11'/><title type='text'>Xephyr on Solaris</title><content type='html'>Searching for a better Xnest on Solaris, looking for Xephyr as a package or source to build, it turns out Xephyr is already included in SXDE.&lt;br /&gt;&lt;br /&gt;location: /usr/X11/bin&lt;br /&gt;&lt;br /&gt;simple usage example:&lt;br /&gt;&lt;br /&gt;Xephyr :1 -screen 1200x800 -query localhost&lt;br /&gt;&lt;br /&gt;This what's new in SXDE 10 guide is quite handy &lt;a href="http://dlc.sun.com/pdf/817-0547/817-0547.pdf"&gt;http://dlc.sun.com/pdf/817-0547/817-0547.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Early signs of Xephyr -&gt; ssh -&gt; Xming on Windows seem reasonable.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;ProGuard - new 4.2 version:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Evaluated the latest ProGuard 4.2 for our Java ME mobile client and it failed reporting a stack length had gone negative! Have reverted back to 4.1 for now, which seems to be working well. Will report the bug to the team.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Java ME, some J9 options worth remembering:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:Times;font-size:100%;"  &gt;&lt;span style=";font-family:Times;font-size:12;"  &gt;&lt;/span&gt;&lt;/span&gt;-Xint -&gt; disable AOT and JIT, interpreted mode only&lt;br /&gt;-noverify -&gt; disable class verification checks (faster loaded on pre-verified code)&lt;br /&gt;-Xnolinenumbers -&gt; turn off line number debug info&lt;br /&gt;&lt;span style=";font-family:Times;font-size:100%;"  &gt;&lt;span style=";font-family:Times;font-size:12;"  &gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-2490777846324323867?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/2490777846324323867/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=2490777846324323867' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2490777846324323867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/2490777846324323867'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/04/xephyr-on-solaris.html' title='Xephyr on Solaris'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-4760005861128836823</id><published>2008-04-14T12:24:00.001-07:00</published><updated>2008-11-22T02:53:51.899-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET CF'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><category scheme='http://www.blogger.com/atom/ns#' term='Compact framework'/><title type='text'>.NET CF</title><content type='html'>Some quick prep /initial prep / background reading for the workshop with Microsoft at their Reading Campus.&lt;br /&gt;&lt;br /&gt;Latest version is currently 3.5 (3.5 RTM 3.5.7283.0 - 2007-11-19)&lt;br /&gt;&lt;br /&gt;Overview of 3.5 features &lt;a href="http://searchwindevelopment.techtarget.com/news/article/0,289142,sid8_gci1285069,00.html"&gt;http://searchwindevelopment.techtarget.com/news/article/0,289142,sid8_gci1285069,00.html&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;You can determine the installed CF versions by running &lt;b&gt;/Windows/cgacutil&lt;/b&gt; on the device (several versions can be co-installed without issue).&lt;br /&gt;&lt;br /&gt;CF 3.5 goes hand in hand with Visual Studio 2008 (whereas the older 2.0 was paired with VS 2005).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/89287579799971239-4760005861128836823?l=louisbotterill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://louisbotterill.blogspot.com/feeds/4760005861128836823/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=89287579799971239&amp;postID=4760005861128836823' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4760005861128836823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/89287579799971239/posts/default/4760005861128836823'/><link rel='alternate' type='text/html' href='http://louisbotterill.blogspot.com/2008/04/net-cf.html' title='.NET CF'/><author><name>LouisB</name><uri>http://www.blogger.com/profile/02740188722372761051</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-89287579799971239.post-7892391132527226126</id><published>2008-04-14T03:54:00.000-07:00</published><updated>2008-11-22T02:54:57.043-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='Java ME JSR 216'/><category scheme='http://www.blogger.com/atom/ns#' term='J2ME'/><category scheme='http://www.blogger.com/atom/ns#' term='Java ME'/><title type='text'>Java ME JSR 216</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Progress! &lt;/span&gt;This morning I was able to make some small changes that made a massive difference to the GUI performance of the Java ME client version of one of our products. So, I thought I'd take a moment to write up some notes on it and Mobile development in general:&lt;br /&gt;&lt;br /&gt;Basically, in doing some testing and profiling previously, it had become evident that one of the main performance problems in JSR 216 GUI was the use of layout managers in GUI construction (especially the GridBagLayout!). I'd previously addressed all other obvious performance hot spots with optimization or re-implementation - and kne
