DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

The Latest Languages Topics

article thumbnail
Programming LDAP with Groovy
It all started with a task to do: Print all members of the group within Active Directory, including members of the nested groups. And a deadline: 15 minutes. Given the deadline, I had no chance to get it done in time. Having 15 minutes means you need to get it right from the first run. Googling for groovy ldap brought Gldapo. But after looking at it and seeing how much configuration has to be done, I searched for some alternatives. Groovy LDAP was beautifully simple and had no external dependencies. I downloaded the jar, dropped it into my GROOVY_HOME/lib directory and started to write the script: import org.apache.directory.groovyldap.LDAP ldap = LDAP.newInstance('ldap://ldap.mycompany.com:389/dc=mycompany,dc=com') After reading through the sample scripts, I already had the main part: ldap.eachEntry ('&(objectClass=person)(memberOf=cn=mygroup') { person -> println "${person.displayName} (${person.cn})" } I saved it as listGroup.groovy and ran it from the command line: groovy listGroup It worked out of the box, printing on the console all the members of the group: John Smith (smithj) Amanda McDonald (mcdonaa) Isabelle Dupre (duprei) Of course, the script was not printing members of the nested groups. In order to do that, I had to turn the snippet into the Groovy recurrent function and avoid hardcoding a group's name in favor of taking it as a command line parameter. Here is the entire script: import org.apache.directory.groovyldap.LDAP import org.apache.directory.groovyldap.SearchScope List getMembersOfAGroup(connection, groupName) { def members = [] def result = connection.searchUnique("cn=$groupName”); connection.eachEntry("memberOf=${result.dn}") { member -> if (member.objectclass.contains("group")) members.addAll(getMembersOfAGroup(connection, member.cn)) else members.add("${member.displayName} (${member.cn})") } return members } LDAP ldap = LDAP.newInstance("ldap://ldap.mycompany.com:389/dc=mycompany,dc=com") getMembersOfAGroup(ldap, args[0]).each { println it } If your directory contains circular group relations, the script has to be further adjusted. This detail has been omitted for simplicity reasons. Please note, that the examples in this article work only with Microsoft Active Directory, because they use vendor specific structure and schema elements. In other directory solutions for instance, group membership is often stored in group entries only, while in Active Directory it is stored in both group and member object. But the examples can easily be adjusted to fit another directory's solution, e.g. by modifying filter expressions. What is this LDAP thing you're talking about? LDAP 101: LDAP stands for Lightweight Directory Access Protocol. A directory is a storage organized as a tree of directory entries. The tree usually reflects political, geographical and/or organizational boundaries. Every directory entry consists of a set of attributes (name/value pairs). These attributes are defined in the LDAP schema. Each directory entry has a unique identifier named DN (Distinguished Name). For more information please read Apache Directory introductory article. Project background Groovy LDAP is a small library started by Stefan Zoerner from the Apache Directory project. Its goal was to create minimalistic LDAP API for Groovy, with metaphors understood by the LDAP community (e.g. members of the Apache Directory team). As such, the only two dependencies of Groovy LDAP are: Java SE (5 or later) Groovy 1.0 or later Under the hood, JNDI is used to perform LDAP queries, but fortunately Groovy LDAP hides it and lets you use a bunch of useful methods and objects, instead. It actually reminds me of the time when Netscape LDAP API was widely used. It defines a set of methods to perform basic LDAP operations: create, modify, delete, compare, search. Groovy LDAP is written in Java, not Groovy. The only Groovy dependency is a reference to a Closure class, which is used as a parameter in a couple of search methods. So with the exception of the method taking the closure, others can be also used in Java programs. How to get it The simplest way is to get the binaries from the Groovy LDAP download page. After downloading and expanding the zip file you need to look for groovy-ldap.jar in the dist directory. Drop it into your GROOVY_HOME/lib directory and you’re ready to write your first script. How to build it If you want to build the library on your own, you will need: Apache Ant 1.7.1 Ivy 1.4.1 or later After you download and install Ant, drop Ivy's jar (ivy-1.4.1.jar) into your ANT_HOME/lib directory. Now you can check out the source files from Apache Directory sandbox Subversion repository. Once the files are checked out, just type ant and wait until the distribution jar is built in the dist directory. Connecting to the directory The first thing you will want to do is to connect to the directory. Groovy LDAP offers here two types of connection: anonymous bind and simple bind. Anonymous bind happens when you connect to the directory without providing your credentials. Many directories allow anonymous bind if the client is only reading from the directory. In corporations anonymous bind is often disabled for security reasons. So, in order to connect you need to instantiate LDAP class using newInstance() method, with the following variants: public LDAP newInstance() public LDAP newInstance(url) A non-parameter method connects to the default address, which is localhost:389. It proves to be useful for various short proof-of-concept scripts. The second method takes the url of the directory as a second parameter. If anonymous bind is not allowed or not sufficient there is an equivalent method, taking additionally user credentials: public LDAP newInstance(url, user, password) Once the connection is established, you can perform any other actions. One tip is to always provide a baseDN as a part of the connection url e.g. ldap://ldap.mycompany.com:389/dc=mycompany,dc=com By doing so you define the default base, upon which searches will be performed, which in turn allows you to use convenient one parameter search methods, instead of specifying a search base and scope each time. Reading and searching directory entries You may want to start with checking if a specific directory entry exists: def found = ldap.exists('cn=smithj,dc=mycompany,dc=com') exists() method is searching the directory by DN (Distinguished Name) and returning a boolean result detailing whether an entry was found. As a companion there is read() method, that reads directory entry, specified by its DN: if (found) def entry = ldap.read('cn=smithj,dc=mycompany,dc=com') This method returns either a boolean value or a given entry, accordingly. But there might be cases when you do not want to search by DN, but by another attribute which is also unique. A good example of this is a userId attribute, which is usually unique within a company. def entry = ldap.searchUnique('userId=smithj') This method assumes uniqueness of an object. If more than one result is returned from the search, you will get an exception. When more results are expected, you can use search() method: and then iterate over a result set: results = ldap.search('(objectClass=user)') println 'Found: $results.size entries' results.each { entry -> println entry.dn } Searches can be also performed with more compact and more Groovy method eachEntry() taking a closure as the last parameter: ldap.eachEntry('(objectClass=user)') { entry -> println entry.dn } As you see, when you have the entry object, you can reference all its properties using native map syntax e.g. entry.dn. This is possible, because all result objects returned from Groovy LDAP search methods are Maps or Lists of Maps. But, how does Groovy LDAP know in which subtree you would like to perform your search? It doesn't, because you haven't specified anything else, but the basic query. So it assumed you want to search in baseDN (hopefully specified, when connecting to the directory). When you want to have more control over how the query is performed, there is a different version of search(), searchUnique() and eachEntry() methods that support it e.g. public List or Search class instance as parameters, but we'll leave them as for now. When you deal with LDAP directories as a part of your daily job, you may want to have a look at Apache Directory Studio, a full-fledged LDAP client tool, which allows you to connect, browse and modify any LDAP-compatible directory. It can also be used as diagnostic tool when your query in Groovy LDAP doesn't work as expected. Adding, modifying and deleting directory entries When you know how to search and read from the directory, it's time to do some modifications. Let's start from adding a new entry: def attributes = [ objectclass: ['top', 'person'], cn: 'smithc', displayName: 'John Smith' ] ldap.add('cn=smithc,dc=example,dc=com', attributes) add() method takes DN and a Map with attributes as parameters. You need to remember not to put DN in the attributes map, as it is not an attribute but rather the unique identifier of an entry. Removing a directory entry is even more straightforward: ldap.delete('cn=smithc,dc=example,dc=com') delete() method will throw an exception, if an object with the given DN does not exist. Modifying a directory entry is not very Groovyish for the time being. Adding single attributes is still relatively easy: def dn = 'cn=smithj,dc=mycompany,dc=com' def email = [ email: '[email protected]' ] ldap.modify(dn, 'ADD', email) Performing batch modifications could be more readable using Builder-like syntax.. The current way to do this is the following: def modifications = [ [ 'REPLACE', [email: '[email protected]'] ], [ 'ADD', [phone: '+48 99 999 99 99'] ] ] ldap.modify(dn, modifications) The same operation, using more expressive syntax, would potentially look like: ldap.modify ('cn=smithj,dc=mycompany,dc=com') { replace(email: '[email protected]') add(phone: '+48 99 999 99 99') } Summary As you can see, Groovy LDAP is a neat little library, delivering simple but convenient API to deal with LDAP directories, which makes it an ideal candidate to use in various administrator scripts and short programs. As a project it resides in Apache Directory sandbox, so when you have a chance, contribute and help Groovy LDAP to become an official subproject of the Apache Directory. Thanks I would like to thank Stefan Zoerner and Carolyn Harman for thorough review of the article. Resources Apache Directory Project Groovy LDAP Gldapo Apache Ant Apache Ivy Groovy
February 16, 2009
by Michal Szklanowski
· 52,881 Views · 5 Likes
article thumbnail
JBoss RichFaces with Spring
This article is going to show you how to build a RichFaces application with Spring.
February 16, 2009
by Max Katz
· 203,778 Views
article thumbnail
How to Create Modular Groovy Applications in 5 Steps!
let's create a modular groovy application! why?! modularity is an enabler of scaleability. as your groovy application increases in size, you increasingly need to manage code dependencies, structure your code in units that are larger than packages, and distribute pieces of your application to developers located in different locations and conflicting time zones. welcome to modularity. the netbeans platform already provides it (plus, osgi is coming to the netbeans platform ). beyond modularity, there are specific features that the netbeans platform provides that will remain unique, such as a shared filesystem for intermodular communication and the concept of "context" (i.e., netbeans lookup), which not only applications have (as with the jdk 6 serviceloader class), but netbeans platform objects such as windows themselves. welcome to loosely coupled modularity. now, let's get started. start up netbeans ide 6.5. go to this page and download the groovy console template and use the plugin manager (in the tools menu) to install it into the ide. now, in the new project dialog, you should see this new project template: click next, give your new application a name (such as "helloworld") and a location on disk, and then click finish. expand a few folders and you should now see this: briefly, the template gives you a groovy pojo, with this content: package org.my.app public class demopojo { def foo } the template also gives you a moduleinstall class, which handles the lifecycle of the module: package org.my.app import org.openide.modules.moduleinstall as mi public class installer extends mi { @override public void restored() { for(int i = 0; i < 10; i++) { demopojo dp = new demopojo() dp.setfoo(i) println("number: " + dp.getfoo()) } } } so, we have some standard groovy constructs here, simply to get you started in the ecosystem of the netbeans platform. the module also includes a properties file for internationalization purposes and a layer.xml file, for the module's contributions to the shared filesystem. run the application (i.e., without doing anything at all, no tweaking, no post processing, nothing at all, just run it). look in the output window of netbeans ide and you will see this: so, you can see that you only have the absolute minimum set of modules to start with. also you're using the groovy compiler (thanks to an additional target that's added to the demo module's build.xml file). that's how to get started with modular groovy applications. have fun with groovy on the netbeans platform!
February 14, 2009
by Geertjan Wielenga
· 21,837 Views
article thumbnail
Integrate OpenOffice with Java without Installing OpenOffice
Until a few days ago, I've always needed to work with the rather cumbersome Office Bean and UNO Runtime when integrating OpenOffice into a Java application. I also had to configure a whole bunch of things to force OpenOffice to play nicely with the Java integration. Two days ago, however, I found out about ODF Toolkit. It seems to be a relatively new project, independent since last year some time, though I could be wrong. What's especially interesting is the ODFDOM: ''ODFDOM is an OpenDocument (ODF) framework. It's purpose is to provide an easy common way to create, access and manipulate ODF files, without requiring detailed knowledge of the ODF specification. It is designed to provide the ODF developer community an easy lightwork programming API, portable to any object-oriented language.'' Here's a snippet of it in action: public static void main(String[] args) { try { OdfDocument odfDoc = OdfDocument.loadDocument(new File("/home/geertjan/test.ods")); OdfFileDom odfContent = odfDoc.getContentDom(); XPath xpath = odfDoc.getXPath(); DTMNodeList nodeList = (DTMNodeList) xpath.evaluate("//table:table-row/table:table-cell[1]", odfContent, XPathConstants.NODESET); for (int i = 0; i < nodeList.getLength(); i++) { Node cell = nodeList.item(i); if (!cell.getTextContent().isEmpty()) { System.out.println(cell.getTextContent()); } } } catch (Exception ex) { //Handle... } } Let's assume that the 'test.ods' file above has this content: From the above, the code listing would print the following: Cuthbert Algernon Wilbert And, as a second example, here's me reading the first paragraph of an OpenOffice Text document: public static void main(String[] args) { try { OdfDocument odfDoc = OdfDocument.loadDocument(new File("/home/geertjan/chapter2.odt")); OdfFileDom odfContent = odfDoc.getContentDom(); XPath xpath = odfDoc.getXPath(); OdfParagraphElement para = (OdfParagraphElement) xpath.evaluate("//text:p[1]", odfContent, XPathConstants.NODE); System.out.println(para.getFirstChild().getNodeValue()); } catch (Exception ex) { //Handle... } } On my classpath I have "odfdom.jar" and "xerces-2.8.0.jar". I don't necessarily have OpenOffice installed, which means I can very easily process a whole bunch of spreadsheets (or other OpenOffice output) without (a) installing OpenOffice and (b) faster than I would otherwise do, since OpenOffice doesn't need to be started up, via the Office Bean or otherwise. In fact, Aljoscha Rittner from Sepix, who told me about this project and who is using it in his commercial applications, reports that his processing has sped up to a fraction of the original, also because he doesn't need to handle the situation where OpenOffice would crash randomly in the middle of long running processes, such as during the night when there's no human interaction for restarting it.
February 7, 2009
by Geertjan Wielenga
· 50,453 Views
article thumbnail
An Overview of Servlet 3.0
JSR 315 (Servlet 3.0) is an update to the existing Servlet 2.5 specification. Servlet 3.0 is focussed on extensibility and web framework pluggability, aligning with the goals of Java EE 6. Ease of Development (EoD) will be supported using newer language features. A reference implementation is available in the GlassFish v3 nightly build. The public review contains: Pluggability EoD Async Support Security Enhancements Miscellaneous Changes In this article we will bring you up to speed with what's happening with the Servlet 3.0 specification and give more detail on what is included. Note: this article corresponds to the public review of the specification. As it is not yet final some things may change. The Expert Group Rajiv Mordani from Sun Microsystems is the specification lead with an expert group comprised of many of the most recognisable names in the Java community: Adobe Systems Inc. Apache Software Foundation BEA Systems Ericsson AB Google Inc. Hunter, Jason IBM Icesoft Technologies Inc NCsoft Corporation Oracle Pramati Technologies Prasanna, Dhanji R. SAP AG Ship, Howard M. Lewis Suleiman, Hani Sun Microsystems, Inc. Tmax Soft, Inc. Walker, Joe Wilkins, Gregory John Pluggability Due to the popularity of so many various web frameworks, Servlet 3.0 will make it easier to use and configure the developer's framework of choice. So if you want to add in Struts, or Spring Web Flow it will be easy to do so. Methods to add Servlets and Filters If a ServletContextListener is registered and wants to add a Servlet or Filter, then at the time of context initialization the event that is fired to the Listener can add Servlets and Filters to the context. The methods are addServlet and addFilter. For more details look for the javadocs at the JCP site at http://jcp.org/aboutJava/communityprocess/pr/jsr315/index.html. Web fragments Instead of having just one monolithic web.xml that is used by the developer to declare servlets, filters and other configuration for using the framework, the framework can now include a web-fragment.xml with all it's configuration. A web-fragment is almost identical to the web.xml and can contain all the configuration needed by the framework in the META-INF directory of the framework's jar file. The container will use the information to assembe the descriptor for the application and the application needn't have to use any of the boilerplate configuration in their app for the framework. There are rules that are defined int the specification for conflict resolution, overriding and disabling fragment scanning. Along with the annotations which also can be in libraries the feature is very compelling not only for the developers that use frameworks but also for framework authors to be self sufficient in defining the configuration needed. The great benefit to this is that library providers can supply their own web.xml fragment for use in your webapp. Ease of Development Several new annotations have been defined for ease of development in Servlet 3.0, allowing you to write a Servlet without requiring a descriptor. These annotations reside in the javax.servlet.annotation package. Thanks to the addition of annotations, it is now possible to have Servlet, Filter and ServletContextListener in a war file without a web.xml. It's important to point out that this makes the web.xml optional, rather than redundant. The web.xml may be user to override metadata specified via annotations. Following discussions in the expert group and the community, it was decided that method level annotations were not to be added, so you keep the doGet, doPost methods and need to extend HttpServlet to use them. Let's take a closer look at the annotations present in the Servlet 3.0 specification: Servlet Annotation In Servlet 3.0, servlet metadata can be specified using @WebServlet @WebServlet(name="mytest", urlPatterns={"/myurl"}, initParams={ @InitParam(name="n1", value="v1"), @InitParam(name="n2", value="v2") }) public class TestServlet extends javax.servlet.http.HttpServlet { .... } TestServlet extends HttpServlet, while the meta data provided corresponds with the web.xml as follows: Parameter Annotation Parameter web.xml Servlet name name= URL Pattern urlPatterns={ } Initialization parameters InitParams={ @InitParam{name=””, value=””} .. .. Servlet Filter Annotation ServletFilter meta data is specified using the @ServletFilter annotation public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { .... } public void destroy() { .... } } Parameter Annotation Parameter web.xml URL Pattern urlPatterns={ } Initialization parameters InitParams={ @InitParam{name=””, value=””} .. .. Servlet Context Listener Annotation A ServletContextListener is simply marked with the @WebServletContextListener rather than needing to list it the web.xml file. @WebServletContextListener public class TestServletContextListener implements javax.servlet.ServletContextListener { .... public void contextInitialized(ServletContextEvent sce) { .... } public void contextDestroyed(ServletContextEvent sce) { .... } } Async Support The biggest change made in the specification is the addition of asynchronous processing. The main cases to cover were: Waiting for a resource to become available, such as JDBC or a call to a Web Service. Generating response asynchronously Using exisiting frameworks to generate responses after waiting the for asychronous operation to complete. While the early draft had suspend and resume, the latest specification has two variations of the startAsync() method on ServletRequest. One (startAsync() ) takes no parameters and initialises an AsyncContext with the original request and response. The ( startAsync() ) other takes a request and response as a parameter to initialise the AsyncContext with. Servlets (@WebServlet) and Filters (@ServletFilter) that support asynchronous processing need to be annotated with the supportAsync attribute set. It is illegal to call startAsync if you have a Servlet or Filter that doesn't support asynchronous processing anywhere in the request processing chain. The is also an AsyncListener that can be registered to get notification on timeout and completion of asynchronous processing of the request. This listener can be used to clean up resources if the wrapped request and response were used to create it's AsyncContext. You can forward requests back to the container using the AsyncContext.forward(path) and AsyncContext.forward() methods so frameworks like JSP can create a response. Security Enhancements HTTPServletRequest will be enhanced with methods allowing programmatic login and logout, while ServletRequest will be able to force a login.The logout method will allow an application to reset the authentication state of a request without requiring the authentication to be bound to a HTTPSession. Conclusion The draft is just beginning to be implemented within Glassfish v3. The specification will be a required piece of Java EE 6 and hence all the features described above will be available in all Java EE 6 compatible containers. The presence of the various features described above will make developing Java web appications much easier. Thanks to Rajiv Mordani for his input into this article, and to Shing Wai and Jan Luehe for the code snippets.
January 21, 2009
by James Sugrue
· 77,633 Views · 2 Likes
article thumbnail
Which Java Version Is Used To Run Our NetBeans Installation?
Ever wondered which Java version is used to run your NetBeans instance? I have a lot of JDK's installed and everytime I install a new one it ones to be the default JDK for my computer. To know which JDK is used for running NetBeans we go to Help | About and the dialog box shows which Java version is used: To explicitly tell NetBeans which JDK to use we can use the command-line argument --jdkhome when we start NetBeans. Or we can set the property netbeans_jdkhome in the file netbeans-install-dir/etc/netbeans.conf.
December 23, 2008
by Hubert Klein Ikkink
· 16,966 Views
article thumbnail
A Farewell to Heavyweight/Lightweight Conflicts
Problems resulting from the mixing of Swing and AWT components have been a constant source of confusion to Java newbies. This quote explains the reason for the difference very well: Most of the issues related to mixing AWT and Swing components are related to the mixing of so-called heavyweight and lightweight components. A heavyweight component is one that is associated with its own native screen resource (commonly known as a peer). A lightweight component is one that "borrows" the screen resource of an ancestor (which means it has no native resource of its own -- so it's "lighter"). From: Mixing Heavy and Light Components The lightweight approach, taken by Swing, is the preferred, since it consumes less resources. However, there are cases where one might need to mix the two in the same application, which can result in undesired side effects. A case in point, from the same article and where all the code used below is found, goes as follows. The menu on the right behaves correctly, while the menu on the left does not: The reason for the difference is that the badly displayed menu in the second screenshot is Swing and lightweight, while the other menu is AWT, and therefore heavyweight. The Button is an AWT component too, therefore being heavyweight. Unless one forces a lightweight component, via setDefaultLightWeightPopupEnabled(false), to behave like a heavyweight component, unwanted side effects such as the above will result. But all that is old news, of course. The new news is that already with the early access release of JDK 6 Update 12 one can, without needing to do anything at all, obtain the desired effect, which is as follows: This is exactly what one would want: the rendering of a lightweight component over a heavyweight component. Though the major features of the EA release are slated as "Windows 2008 Support" and "Java Plug-In now supports 64-bit browsers", it is this heavyweight/lightweight fix that I find the most useful (since I am neither a Windows- nor a 64-bit browser-user). If one looks through the list of issues fixed in the current JDK 6 Update 12 build, one notices that a lot of fixing has been done in the Swing & AWT packages. The final screenshot above was taken on JDK 6 Update 12, using the code from the article referenced at the start. I.e., without doing anything special at all, no fiddling with z-order or the like, the behavior was exactly as an end user would expect it to be. Hurray!
December 16, 2008
by Geertjan Wielenga
· 20,826 Views
article thumbnail
Real-World Scala: Managing Cross-Cutting Concerns using Mixin Composition and AOP
In a previous post I showed you how you could use mixin composition and self type annotations to enable Dependency Injection (DI). Mixin composition is an extremely powerful tool that you can utilize in many different ways to enable modular and reusable code. In this post I’ll try to show you how you can use it to solve the problem of crosscutting concerns using AOP/interceptor-style composition. Crosscutting concerns and AOP OOP has given us tools to reduce software complexity by introducing concepts like inheritance, abstraction, and polymorphism. However, developers face daily problems in software design that can’t be solved easily using OOP. One of these problems is how to handle cross-cutting concerns in the application. So what is a cross-cutting concern? A concern is a particular concept or area of interest. For example, in an ordering system the core concerns could be order processing and manufacturing, while the system concerns could be transaction handling and security management. A cross-cutting concern is a concern that affects several classes or modules, a concern that is not well localized and modularized. Symptoms of a cross-cutting concern are: Code tangling - when a module or code section is managing several concerns simultaneously Code scattering - when a concern is spread over many modules and is not well localized and modularized These symptoms affect software in various ways; for example, they make it harder to maintain and reuse software as well as harder to write and understand. Aspect-Oriented Programming (AOP) tries to solve these problems by introducing the concept of separation of concerns, in which concerns can be implemented in a modular and well-localized way. AOP solves this by adding an extra dimension to the design space, and introduces constructs that allow us to define the cross-cutting concerns, to lift them out into a new dimension and package them in a modular way. We are currently using two different types of interceptors (aspects if you like): Mixin composition stacks — a limited but sometimes very useful approach Generic interceptors/aspects using a pointcut pattern language Mixin composition stacks Mixin composition stacks is a core language feature of Scala and is similar to Rickard Oberg’s idea on using the so-called Abstract Schema pattern for type-safe AOP in plain Java. (This is a very contrived example that probably shows that don’t know a zip about dogs, but please bare with me.) First let’s define a couple of interfaces; Dog and DogMood modeled as a mixins (in this case without an implementation so similar to Java’s interface): trait Dog { def greet(me: Human) } trait DogMood extends Dog { def greet(me: Human) { println(me.sayHello) } } Now let’s define two different mixin “interceptors” that implement these interfaces. The first one defining an angry dog and the other one a hungry dog: trait AngryDog extends DogMood { abstract override def greet(me: Human) { println("Dog: Barks @ " + me) super.doStuff(me) } } trait HungryDog extends DogMood { abstract override def greet(me: Human) { super.doStuff(me) println("Dog: Bites " + me) } } As we can see in this example they both override the Mood.greet method. If we look more closely we can see that they follow the same pattern: Enter method (greet) Do something Invoke the same method on super (super.greet) Do something else The trick here is in the semantics of the call to super. Here Scala will invoke the next mixin in a stack of mixins, e.g. the same method in the “next” mixin that have been mixed in. Exactly what f.e. AspectJ does in its proceed(..) method and what Spring does in its interceptors. Now let’s fire up the Scala REPL and create a component based on the Dog interface. Scala’s mixin composition can take place when we instantiate an instance, e.g. it allows us to mix in functionality into specific instances that object creation time for specific object instances. scala> val dog = new Dog with AngryDog with HungryDog stuff2: Dog with AngryDog with HungryDog = $anon$1@1082d45 scala> dog.greet(new Human("Me")) Dog: Barks @ Me Me: Hello doggiedoggie Dog: Bites Me As you can see the call to Dog.greet is intercepted by the different moods that are added to the dog at instantiation time. Interceptors like this are as you can see not generically reusable since they are tied to a specific interface, however if well designed can be a pretty powerful technique. It has the advantage that everything is statically compiled and type-checked by the Scala compiler Generic pointcut-based aspects The main usage of generic aspects is for implementing infrastructure concerns such as logging, transaction demarcation, security, clustering, persistence etc. In order to create a framework for implementing generic aspects, the first thing we need to do is to define an invocation context, holding arguments, method to be invoked as well as the target instance. case class Invocation(val method: Method, val args: Array[AnyRef], val target: AnyRef) { def invoke: AnyRef = method.invoke(target, args:_*) override def toString: String = "Invocation [method: " + method.getName + ", args: " + args + ", target: " + target + "]" override def hashCode(): Int = { ... } override def equals(that: Any): Boolean = { ... } } The second thing that we need to do is to create a base Interceptor trait. This interface defines two different pointcut matching methods. The first one matches a precompiled AspectJ pointcut expression using the PointcutParser in AspectJ. This allows defining interceptors matches AspectJ compatible (method) pointcut expressions. The second matcher matches methods or classes that is annotated with a specific annotation. trait Interceptor { protected val parser = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution protected def matches(pointcut: PointcutExpression, invocation: Invocation): Boolean = { pointcut.matchesMethodExecution(invocation.method).alwaysMatches || invocation.target.getClass.getDeclaredMethods.exists(pointcut.matchesMethodExecution(_).alwaysMatches) || false } protected def matches(annotationClass: Class[T] forSome {type T < : Annotation}, invocation: Invocation): Boolean = { invocation.method.isAnnotationPresent(annotationClass) || invocation.target.getClass.isAnnotationPresent(annotationClass) || false } def invoke(invocation: Invocation): AnyRef } The last thing we need to do is to create a factory method allows us to wire in our interceptors, declarative, in a seamless fashion. This factory is using the plain old Java Dynamic Proxy API to create a proxy for our base components. object ManagedComponentFactory { def createComponent[T](intf: Class[T] forSome {type T}, proxy: ManagedComponentProxy): T = Proxy.newProxyInstance( proxy.target.getClass.getClassLoader, Array(intf), proxy).asInstanceOf[T] } class ManagedComponentProxy(val target: AnyRef) extends InvocationHandler { def invoke(proxy: AnyRef, m: Method, args: Array[AnyRef]): AnyRef = invoke(Invocation(m, args, target)) def invoke(invocation: Invocation): AnyRef = invocation.invoke } Just using this factory pass is won’t do any wiring for us, which is actually good since if we would use the dynamic proxy the old-fashioned way and we would have it to invoke each interceptor explicitly using reflection. But we can do better than that. Instead we will let the Scala compiler statically compiled in an interceptor stack with all our interceptors. This is best explained with an example. In this example we will define a couple of simple services called Foo and Bar along with their implementations. We will then implement two different infrastructure in interceptors; logging and transaction demarcation. Let’s first define the service. import javax.ejb.{TransactionAttribute, TransactionAttributeType} trait Foo { @TransactionAttribute(TransactionAttributeType.REQUIRED) def foo(msg: String) def bar(msg: String) } class FooImpl extends Foo { val bar: Bar = new BarImpl def foo(msg: String) = println("msg: " + msg) def bar(msg: String) = bar.bar(msg) } trait Bar { def bar(msg: String) } class BarImpl extends Bar { def bar(msg: String) = println("msg: " + msg) } Now let’s define a logging interceptor. Both of these interceptors are just mockups, since the actual implementation is not really of interest. The logging interceptor is defined using a standard AspectJ pointcut while the transaction interceptor is wired to a specific annotation. trait LoggingInterceptor extends Interceptor { val loggingPointcut = parser.parsePointcutExpression("execution(* *.foo(..))") abstract override def invoke(invocation: Invocation): AnyRef = if (matches(loggingPointcut , invocation)) { println("=====> Enter: " + invocation.method.getName + " @ " + invocation.target.getClass.getName) val result = super.invoke(invocation) println("=====> Exit: " + invocation.method.getName + " @ " + invocation.target.getClass.getName) result } else super.invoke(invocation) } trait TransactionInterceptor extends Interceptor { val matchingJtaAnnotation = classOf[javax.ejb.TransactionAttribute] abstract override def invoke(invocation: Invocation): AnyRef = if (matches(matchingJtaAnnotation, invocation)) { println("=====> TX begin") try { val result = super.doStuff println("=====> TX commit") result } catch { case e: Exception => println("=====> TX rollback ") } } else super.invoke(invocation) } Now let’s do the wiring. Here we are using dynamic proxy-based factory that we implemented because you can see, the actual wiring on the interceptor stack is done using Scala mixing composition and therefore has all its benefits, like compiler type checking and enforcement, the speed of statically compiled code, refactoring safety etc. var foo = ManagedComponentFactory.createComponent[Foo]( classOf[Foo], new ManagedComponentProxy(new FooImpl) with LoggingInterceptor with TransactionInterceptor) foo.foo("foo") foo.bar("bar") } This will produce the following output: =====> TX begin =====> Enter: foo @ FooImpl msg: foo =====> Exit: foo @ FooImpl =====> TX commit =====> TX begin =====> Enter: bar @ FooImpl msg: bar =====> Exit: bar @ FooImpl =====> TX commit So this wraps it up. I hope that you have learned a little bit about how powerful mixin composition in Scala is and how it can be used to write modular and reusable components with little effort. This is working fine for us, but there is definitely room for improvement. For example, runtime matcher in the interceptor is fast enough for the annotation matching (only a boolean check) but the AspectJ pointcut matcher is a bit slower since it has to do some more work. This might turn out be a problem or not, most infrastructure services (like persistence and security) performs quite a lot to work and in these cases the overhead over the interceptor of matching will not affect the overall performance much, but in other cases (such as logging or auditing) it might. We are so far only use the annotation matching, so it has not turned out to be a problem so far. However, if it turns out to be a performance bottleneck then we will most likely switch to using my old AspectWerkz AWProxy to get rid of all the Java reflection code and runtime matching. For those that are interested, here is the actual JTA transaction demarcation interceptor that we are using in production (implementing all the EJB transaction semantics). trait EjbTransactionInterceptor extends Interceptor with TransactionProtocol { val matchingJtaAnnotation = classOf[javax.ejb.TransactionAttribute] abstract override def invoke(invocation: Invocation): AnyRef = if (matches(matchingJtaAnnotation, invocation)) { val txType = getTransactionAttributeTypeFor(invocation.target.getClass, invocation.method) if (txType == TransactionAttributeType.REQUIRED) withTxRequired { super.invoke(invocation) } else if (txType == TransactionAttributeType.REQUIRES_NEW) withTxRequiresNew { super.invoke(invocation) } else if (txType == TransactionAttributeType.MANDATORY) withTxMandatory { super.invoke(invocation) } else if (txType == TransactionAttributeType.NEVER) withTxNever { super.invoke(invocation) } else if (txType == TransactionAttributeType.SUPPORTS) withTxSupports { super.invoke(invocation) } else if (txType == TransactionAttributeType.NOT_SUPPORTED) withTxNotSupported { super.invoke(invocation) } else super.invoke(invocation) } else super.invoke(invocation) } About this entry You’re currently reading “Real-World Scala: Managing Cross-Cutting Concerns using Mixin Composition and AOP,” an entry on Jonas Bonér Published: 12.09.08 / 5am Category: AOP, Scala
December 10, 2008
by Jonas Bonér
· 19,857 Views
article thumbnail
Computing 95 Percentile In MySQL
When doing performance analyzes you often would want to see 95 percentile, 99 percentile and similar values. The "average" is the evil of performance optimization and often as helpful as "average patient temperature in the hospital". Lets set you have 10000 page views or queries and have average response time of 1 second. What does it mean ? Really nothing - may be one page view was 10000 seconds and the rest was in low milliseconds or may be you had every single page view taking 1 second, which are completely different. You also do not really care about average performance - the goal of good user experience is majority of users to have good experience and average is not a good fit here. Defining your response time goal in 95 or 99 percentile is much better. Say you say 99 percentile response time should be one second, this means only 1 percent of queries/page views are allowed to take more than that. For larger systems defining (increasing) response times for 99.9 or even 99.99 percentile numbers often make sense. It also often makes sense to define response time goals separately for different transactions - the AJAX widget response time requirements may be very different from the slow search page. So you have defined your response time in terms of 95/99 percentile and get your logs in the table, so how to get the data if MySQL only provides you the avg: mysql> SELECT count(*),avg(wtime) FROM performance_log_081128 WHERE page_type='search'; +----------+-----------------+ | count(*) | avg(wtime) +----------+-----------------+ | 106859 | 1.4469140766532 +----------+-----------------+ 1 row IN SET (2.08 sec) The average response time here is for example; the real data what we need is number of rows which matches for given query type. Dividing the count by 100 we get our 1% of values and dividing by 20 5% of values, now we can get the response time we concerned about simply by running following order-by queries: mysql> SELECT wtime FROM performance_log_081128 WHERE page_type='search' ORDER BY wtime DESC LIMIT 1068,1; +---------+ | wtime +---------+ | 10.1007 +---------+ 1 row IN SET (2.06 sec) mysql> SELECT wtime FROM performance_log_081128 WHERE page_type='search' ORDER BY wtime DESC LIMIT 5342,1; +---------+ | wtime +---------+ | 5.09297 +---------+ 1 row IN SET (2.06 sec) So for this system the 95 percentile is just over 5 sec (some 3 times more than the average) and 99% percentile is just a bit over 10 seconds (6 times more than average). The both numbers are horrible and system surely needs to be fixed. These numbers are to illustrate - the percentile numbers can be quite different from average numbers (it is not rare to see 99 percentile to be order of magnitude different from the average) and this is what you really need to focus on. Looking at the numbers from the business standpoint try to understand what these really are. In some cases I see rather bad percentile on the backend which are not really the problem for the business because there is a cache up front anyway. If 99% of requests are coming from the cache and you observe certain 99 percentile response time on the backend it is often 99.99 percentile response time which is a lot different - you often can afford 1/10000 requests to stall for few seconds, because things outside of your control (like packet loss at client side) would be responsible for larger amount of delays. Be careful though - the "random" delays, for example if system was busy and delayed servicing request is one thing, "systematic" delays, when response time is always bad in given conditions can be much worse problems. You do not want your best client to suffer for example, even if he is the only one.
December 3, 2008
by Peter Zaitsev
· 15,388 Views
article thumbnail
Getting Groovy With "with"
Strange enough title.Let's start with a hypothetical conversation between a geeky developer and his much less geeky wife: Jeff: Betsy, how are you? Betsy: I am fine thanks. How are you? Jeff: Betsy, I am fine thank you. Betsy: Great. Jeff: Betsy, you know my birthday is the day after tomorrow right? Betsy: Yes, I haven't forgotten. You mention it about 9 times a day you know. Jeff: Betsy, yes I know. Are we going to have an ice cream cake? Betsy: Yes, I think that would be good. Jeff: Betsy, are you going to buy me the new Opeth DVD? Betsy: I will get it for you but that music sucks big time. Jeff: Betsy, that is awesome. Thank you. Betsy: Why do you keep saying "Betsy" at the beginning of every sentence? Jeff: Betsy, I guess I am used to inflexible languages which aren't very expressive. Um, what does any of that have to do with Groovy? Well, lets talk about the problem with this conversation (aside from the lady's lack of appreciation for Swedish heavy metal). What is wrong is Jeff begins each sentence with "Betsy". Why might he do that? One reason is so Betsy knows that he is talking to her. Clearly this isn't necessary. It isn't necessary because she already knows he is talking to her. A context has been established which makes the addressing unnecessary. Jeff began the conversation by addressing Betsy, they probably made eye contact and were in close proximity. Once the conversation started, there isn't much question about who each sentence is being directed to. Again, what does any of that have to do with Groovy? Lets press on... Consider the following Java code which prints out a specific date. // PrintIndependenceDay.java import java.util.Calendar; import java.util.Date; public class PrintIndependenceDay { public static void main(String[] args) { Calendar calendar = Calendar.getInstance(); calendar.clear(); calendar.set(Calendar.MONTH, Calendar.JULY); calendar.set(Calendar.DATE, 4); calendar.set(Calendar.YEAR, 1776); Date time = calendar.getTime(); System.out.println(time); } } Groovy developers can look at that and find quite a bit of noise that doesn't really have anything to do with what the code is trying to do but I want to focus on one specific thing. That one thing is all of the interaction with the calendar variable. Notice that we call clear() on the calendar, then call set() several times and later call getTime() on that same variable. All of those calls are prefixed with "calendar." so the compiler knows what we want to do. If we called "clear()" instead of "calendar.clear()", what would that mean? Are we calling the clear() method in this class? If that was our intent, it would not work because there is no clear() method. We have to prefix the call with an object reference so the compiler knows where to send the request. That seems to make sense. However, if we are going to do a bunch of things "with" the same object, wouldn't it be kind of nice if we could somehow do all of those things without all the repetition. Specifically, it might be nice if we could get rid of all of those "calendar." prefixes. On to Groovy... The following Groovy code does the same thing that the Java code above does. // PrintIndependenceDay.groovy def calendar = Calendar.instance calendar.with { clear() set MONTH, JULY set DATE, 4 set YEAR, 1776 println time } Wow. That is a good bit cleaner than what we started with. Part of the reason for that is we were able to get rid of all of those "calendar." prefixes. What allowed us to do that is calling the "with" method on the calendar object and passing a closure as an argument. What we have done there is establish a context that says "do all of this stuff with this calendar object". When the closure executes, the calendar is given an opportunity to respond to method calls like clear() and set() and the implicit call to getTime() when referring to the "time" property which is being passed to println. Likewise, the references to MONTH, JULY, DATE and YEAR properties are also being handled by the calendar object. That is pretty slick. Lets dig just a little deeper to get a little better understanding of what is really going on. Groovy closures have a delegate associated with them. The delegate is given an opportunity to respond to method calls which happen inside of the closure. Here is a simple example: // define a closure def myClosure = { // call a method that does not exist append 'Jeff' append ' was here.' } // assign a delegate to the closure def sb = new StringBuffer() myClosure.delegate = sb // execute the closure myClosure() assert 'Jeff was here.' == sb.toString() When the closure is executed, those calls to append() in the closure end up being sent to the delegate, the StringBuffer in this case. Something similar is happening in the Groovy calendar code above. A closure is being passed to the with() method. That closure is calling methods like set() and getTime() which don't really exist in that context. The reason those calls don't fail is the with() method is assigning a delegate to the closure before it is executed. The delegate being assigned is the object that the with() method was invoked on. In the calendar example, the delegate is the calendar object. Something like this is happening... def closure = { clear() set MONTH, JULY set DATE, 4 set YEAR, 1776 println time } def calendar = Calendar.instance closure.delegate = calendar closure() This code does the same thing as the first Groovy example. Obviously the first one is cleaner. I sort of lied a bit, or at least left out a detail that may be significant. The closure that is being passed to the with() method is really being cloned and it is the clone that is assigned the delegate and executed. This is a safer approach than monkeying with the original closure. If the reasons for that aren't clear, the explanation is another story. Another bit of info that is missing here is the strategy that a closure uses to decide when to send method calls to the delegate. Each Groovy closure has a resolveStrategy associated with it. This property determines how/if the delegate comes in to play. The 4 possible values for the resolveStrategy are OWNER_FIRST, DELEGATE_FIRST, OWNER_ONLY and DELEGATE_ONLY (all constants defined in groovy.lang.Closure). The default is OWNER_FIRST. Consider the owner to be the "this" wherever the closure is defined. Here is a simple example... class ResolutionTest { def append(arg) { println "you called the append method and passed ${arg}" } def doIt() { def closure = { append 'Jeff was here.' } def buffer = new StringBuffer() closure.delegate = buffer // the append method in this ResolutionTest // will be called because resolveStrategy is // OWNER_FIRST (the default) closure() // give the delegate first crack at method // calls made inside the closure closure.resolveStrategy = Closure.DELEGATE_FIRST // the append method on buffer will // be called because the delegate gets // first crack at the call to append() closure() } static void main(String[] a) { new ResolutionTest().doIt() } } So you see how the with() method helps establish a context where a bunch of things may happen "with" a specific object without having to refer to that object over and over. This can help clean up code like the Java code we started with. This approach can also be really useful when building a domain specific language in Groovy, a topic for another time. From http://javajeff.blogspot.com/
November 14, 2008
by Jeff Brown
· 37,077 Views · 1 Like
article thumbnail
Delphi Left Pad Function
Left pad function function LeftPad(PadString : string ; HowMany : integer ; PadValue : string): string; var Counter : integer; x : integer; NewString : string; begin Counter := HowMany - Length(PadString); for x := 1 to Counter do begin NewString := NewString + PadValue; end; Result := NewString + PadString; end;
November 12, 2008
by Stephen Provis
· 9,472 Views · 1 Like
article thumbnail
Delphi - Remove Extra Quotes From Fields
Remove extra quotes (') from entered fields function FixQuote(FixString : string) : string; begin Result := AnsiReplaceStr(FixString, '''' , '''''' ); end;
November 12, 2008
by Stephen Provis
· 6,432 Views
article thumbnail
Merge Sort In Java
// A simple (i.e., not particularly optimized) implementation of merge sort in Java. // I tested the sorting capacities on several documents of increasing size: // Lincoln's Emancipation Proclamation, Mark Twain's _Innocents Abroad_, // George Eliot's _Middlemarch_, and Leo Tolstoy's _War and Peace_. // The sort operation itself is very fast -- under 2 seconds for War and Peace. import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; /** * A few factoids about MergeSort: * 1) while it gets better performance on the modern PC (because it takes advantage of caching * better than, say, HeapSort) * 2) It requires more space than HeapSort -- HeapSort runs in place, while MergeSort requires * extra memory space to hold the recursive calls. So if you're short on memory, * go for HeapSort * 3) MergeSort is stable -- the order of the list never changes once it's set. * 4) MergeSort is very easy to run in parallel, for obvious reasons. * 5) If you need to chew through very large files, you can use MergeSort to write out * temporary results to a file and it will work fine. HeapSort, by comparison, * relies strongly on random access and so doesn't operate as well on disk storage media. * @author Roger * */ public class MergeTest { /** * @param args */ public static void main(String[] args) throws IOException { String[] files = { "lincoln2.txt", "lincoln.txt", "twain2.txt", "twain3.txt", "twain.txt", "eliot.txt", "tolstoy.txt" }; SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss-SSS zzz yyyy"); /* String[] testCase = {"aa", "baa", "quickly", "monitor", "frontage", "beast", "feast", "obsequious", "obstetrics", "feast", "alphabet", "gnomic", "triumph" }; */ System.out.println("---------TEST MERGE W ARRAY ------------"); for (int x = 0; x < files.length; x++) { String[] testCase = readFile(files[x]); long start = System.currentTimeMillis(); Date now = new Date(start); System.out.println("File: " + files[x]); System.out.println("Total words: " + testCase.length); System.out.println("begin test: " + format.format(now)); MergeTest merge = new MergeTest(); String[] sortTest = merge.mergeSort(testCase); long end = System.currentTimeMillis(); now = new Date(end); System.out.println("end test: " + format.format(now)); System.out.println("total time: " + (end - start)); System.out.println("--------------------------\n\n"); } /* System.out.print("\nbefore: {"); for (int x = 0; x < testCase.length; x++) { System.out.println(testCase[x] + " "); } System.out.println("} "); System.out.print("after: {"); for (int x = 0; x < sortTest.length; x++) { System.out.println(sortTest[x] + " "); } System.out.println("} "); */ System.exit(0); } public String[] mergeSort(String[] list) { String [] sorted = new String[list.length]; if (list.length == 1) { sorted = list; } else { int mid = list.length/2; String[] left = null; String[] right = null; if ((list.length % 2) == 0) { left = new String[list.length/2]; right = new String[list.length/2]; } else { // left = new String[list.length/2]; right = new String[(list.length/2)+1]; } int x=0; int y=0; for ( ; x < mid; x++) { left[x] = list[x]; } for ( ; x < list.length; x++) { right[y++] = list[x]; } left = mergeSort(left); right = mergeSort(right); //sorted = merge(left,right); sorted = mergeArray(left,right); } return sorted; } private String[] merge(String[] left, String[] right) { List merged = new ArrayList(); List lstLeft = new ArrayList(Arrays.asList(left)); List lstRight = new ArrayList(Arrays.asList(right)); int comp = 0; while (!lstLeft.isEmpty() || !lstRight.isEmpty()) { if (lstLeft.isEmpty()) { merged.add(lstRight.remove(0)); } else if (lstRight.isEmpty()) { merged.add(lstLeft.remove(0)); } else { // they both have elements, compare them comp = lstLeft.get(0).compareTo(lstRight.get(0)); if (comp > 0) { merged.add(lstRight.remove(0)); } else if (comp < 0) { merged.add(lstLeft.remove(0)); } else { // they're equal -- just put one in merged.add(lstLeft.remove(0)); } } } return merged.toArray(new String[merged.size()]); } private String[] mergeArray(String[] left, String[] right) { String[] merged = new String[left.length+right.length]; int lIndex = 0; int rIndex = 0; int mIndex = 0; int comp = 0; while (lIndex < left.length || rIndex < right.length) { if (lIndex == left.length) { merged[mIndex++] = right[rIndex++]; } else if (rIndex == right.length) { merged[mIndex++] = left[lIndex++]; } else { // they both have elements. Compare them comp = left[lIndex].compareTo(right[rIndex]); if (comp > 0) { merged[mIndex++] = right[rIndex++]; } else if (comp < 0) { merged[mIndex++] = left[lIndex++]; } else { // they're equal merged[mIndex++] = left[lIndex++]; } } } return merged; } public static String[] readFile(String filename) throws IOException { BufferedReader inputStream = new BufferedReader(new FileReader(filename)); List testList = new ArrayList(); String[] sample = null; String l; while ((l = inputStream.readLine()) != null) { sample = l.split(" "); for (int x=0; x < sample.length; x++) { testList.add(sample[x]); } } inputStream.close(); return testList.toArray(new String[testList.size()]); } }
November 5, 2008
by Roger Turnau
· 2,650 Views
article thumbnail
What is Wrong with JDK Logger?
I used to use log4j because it was most popular, but recently decided to try JDK logger in my current project. I like that it is built into the JDK so there are no .jar dependencies, version conflicts, etc. All I need it to do is write to a disk file using a format String I specify, rotate logs after x KB, and to keep only y archived files. I'm just as satisfied with it as I was with log4j. A while ago I did some reading about the history of logging frameworks to try and understand the hostility many developers still have towards JDK logger. From what I can tell log4j was the first widely popular logging framework in Java. Later, its ideas and general API design were standardized in JDK 1.4. The names of some things were changed, but the concepts are the same. There were many developers who did not want to require "the new" Java 1.4 so they continued with log4j. Later the commons-logging wrapper was created to provide libraries and applications the ability to use either log4j or JDK logger depending on what is present in the environment. Even today with the pending release of Java 1.7 many developers use log4j or commons-logging instead of the built in JDK logger. My question to you is what is wrong with the JDK logger? Why do some people say it was disaster? Why don't you use it? I am not trying to start a flamewar, I am genuinely interested. Is it because log4j comes with many more built-in appenders such as NTEventLogAppender, JMSAppender, and SMTPAppender? I figure the JDK logger has only basic core handlers/appenders for the same reason JSF comes only with basic HTML UI components. From http://www.ryandelaplante.com
October 29, 2008
by Ryan Developer
· 27,739 Views
article thumbnail
Create And Run A "scheduled" Task Using Python Win32com
// description of your code here Uses the new COM Task Scheduler Interface to create a new disabled scheduled task, then run it once as part of a script. Use this to launch interactive tasks, even remotely. import win32com.client computer_name = "" #leave all blank for current computer, current user computer_username = "" computer_userdomain = "" computer_password = "" action_id = "Test Task" #arbitrary action ID action_path = r"c:\windows\system32\calc.exe" #executable path (could be python.exe) action_arguments = r'' #arguments (could be something.py) action_workdir = r"c:\windows\system32" #working directory for action executable author = "Someone" #so that end users know who you are description = "testing task" #so that end users can identify the task task_id = "Test Task" task_hidden = False #set this to True to hide the task in the interface username = "" password = "" run_flags = "TASK_RUN_NO_FLAGS" #see dict below, use in combo with username/password #define constants TASK_TRIGGER_DAILY = 2 TASK_CREATE = 2 TASK_CREATE_OR_UPDATE = 6 TASK_ACTION_EXEC = 0 IID_ITask = "{148BD524-A2AB-11CE-B11F-00AA00530503}" RUNFLAGSENUM = { "TASK_RUN_NO_FLAGS" : 0, "TASK_RUN_AS_SELF" : 1, "TASK_RUN_IGNORE_CONSTRAINTS" : 2, "TASK_RUN_USE_SESSION_ID" : 4, "TASK_RUN_USER_SID" : 8 } #connect to the scheduler (Vista/Server 2008 and above only) scheduler = win32com.client.Dispatch("Schedule.Service") scheduler.Connect(computer_name or None, computer_username or None, computer_userdomain or None, computer_password or None) rootFolder = scheduler.GetFolder("\\") #(re)define the task taskDef = scheduler.NewTask(0) colTriggers = taskDef.Triggers trigger = colTriggers.Create(TASK_TRIGGER_DAILY) trigger.DaysInterval = 100 trigger.StartBoundary = "2100-01-01T08:00:00-00:00" #never start trigger.Enabled = False colActions = taskDef.Actions action = colActions.Create(TASK_ACTION_EXEC) action.ID = action_id action.Path = action_path action.WorkingDirectory = action_workdir action.Arguments = action_arguments info = taskDef.RegistrationInfo info.Author = author info.Description = description settings = taskDef.Settings settings.Enabled = False settings.Hidden = task_hidden #register the task (create or update, just keep the task name the same) result = rootFolder.RegisterTaskDefinition(task_id, taskDef, TASK_CREATE_OR_UPDATE, "", "", RUNFLAGSENUM[run_flags] ) #username, password #run the task once task = rootFolder.GetTask(task_id) task.Enabled = True runningTask = task.Run("") task.Enabled = False
October 23, 2008
by Snippets Manager
· 14,344 Views
article thumbnail
Seven Forms of Business Process Management With JBoss jBPM
This article will explain Business Process Management (BPM) in terms of 7 distinct use cases for JBoss jBPM. By giving more insight in those use cases, you'll get a better understanding of the different forms of BPM and workflow and when a BPM engine like jBPM makes sense in your project. We'll also highlight the specific jPDL process language features related to those use cases. The term BPM is highly overloaded and used for many different things resulting in a lot of confusion. These use cases give concrete descriptions for the different interpretations of the term BPM. The individual nature of these use cases is important. BPM software vendors often take a mix of different aspects and concerns into account when developing their products. That often results into BPM products that are suitable only for a specific purpose in a specific environment. This is in my opinion the reason why there are so many different BPM products which only serve a small niche market. It also explains why new products and standards in this space keep appearing, don't get enough momentum and then get pushed aside by yet another new product or standard. When evaluating a BPM products, it should be done with specific use cases in mind. What is JBoss jBPM JBoss jBPM is a flexible and powerful BPM engine. In essence, BPM systems allow for execution flows to be specified graphically. As an example, here is a process diagram for a business trip: [img_assist|nid=5583|title=|desc=|link=none|align=undefined|width=623|height=487] A key capability of BPM systems is that processes steps can be wait states. For example in the business trip process above, nodes 'manager evaluation' and 'ticket purchase' are human tasks. When the execution of the process arrives in those nodes, the system executing the process should wait till the assigned user completes the task. From a software technical point of view that capability is a big deal. As the alternative is a bunch of methods that are linked by HTTP requests, Message Driven Beans (MDB), database triggers, task forms, etc. Even when using the most applicable architectural components available in Java today, it is still very easy to end up in a bunch of unmaintainable hooks and eyes. Using an overall business process makes it a lot easier to see and maintain the overall execution flow, even from a software technical perspective. JBoss jBPM does exactly that and it differentiates itself from other BPM projects in the following topics: Easily embeddable into a Java project. Traditional BPM Systems typically require a separate server to be installed which makes it hard to integrate into the Java software development cycle. One of the deployments that JBoss jBPM supports is just adding the jBPM library to the classpath. The jBPM tables can be hosted in any database next to the application's tables. Using JBoss jBPM really fits with the normal way of developing Java software. Support for multiple process languages. The view on what BPM actually is has not yet been stabilized. There are currently many different interpretations of what BPM is, resulting in big fragmentation in the market. In fact, the body of this article tries to identify 6 distinct concepts that all are associated to BPM. Very flexible transaction management. If your application just uses a JDBC connection in a standard Java environment, then jBPM can use that very JDBC connection to perform its work. If your application uses hibernate in a standard environment, then jBPM can use the same hibernate session factory. If your application runs in an enterprise environment, then jBPM can bind to the surrounding JTA transaction. Readable jPDL process language. For developers it is very convenient if the process language is compact and readable. Not all developers want to keep using the graphical editor. Most hard core programmers start to hand code the processes after a while. Then jBPM's jPDL process language is the most readable, compact and complete. Standards BPEL and BPMN Todays most known standards in the space of BPM are BPEL and BPMN. Those two standards have a completely different background. That is a clear indication of the diverse type of problems that is currently associated to BPM. BPEL is defined with an Enterprise Service Bus (ESB) in mind. It's all based on WSDL, which binds naturally to web services. The result of deploying a BPEL process is that a new service is being published. A BPEL process can hence be seen as a scripting language for services on the bus. A more elaborate conceptual explanation of BPEL can be found in Process Component Models: The Next Generation In Workflow ? So BPEL is an executable process language, which implies that a it is human to computer communication, just like a programming language. On the other hand, the first target of BPMN is modeling process diagrams by non-technical business analysts. It defines the shapes, types and meaning of the boxes and arrows. This type of modeling should be seen in the context of 'BPM as a discipline' (see below). By definition, non technical business analyst do not think in terms of web services or other technology aspects. BPMN processes are primarily intended for communication between humans. So far, so good. But now comes the hard and confusing reality: BPEL has been presented as a solution for 'BPM as a discipline' and BPMN 2.0 plans to add concrete executable semantics. These days, most IT people already realized that BPEL is not a convenient solution for 'BPM as a discipline'. On the other hand adding concrete executable semantics to a business analyst modeling notation means that non-technical analysts will be implicitly writing a piece of executable software. Would you put software into production written by a non-technical person ? Use Case 1 : BPM as a discipline BPM as a discipline refers to the analysis, documentation and improvement of the procedures that describe how people and systems work together in an organization. Realize that most BPM is done in this way, not even resulting into any form of software or IT support. MS Visio is one the most used tools to document business processes. Of course, once the business process is documented, it might make sense to develop software support for it. Suppose that a business analyst modeled and documented a 'business trip' process, then one usage might be to find optimizations in that process. And another usage might be the development of software support for business trips. Please be aware that an automatic translation between pure analysis models and executable process models are not feasible in general. Initially BPM products tried to make this translation automagically transparent. In the context of BPM as a discipline, we believe that a process model from a non technical business analyst can never be translated into an executable process model by just adding technical details to it. The next attempt was to acknowledge existence of an analysis model and an executable process model and then try to keep them in sync. Especially because of the big differences between BPMN and BPEL this approach got a lot of attention. But then the problem of maintaining the links between analysis and executable process model appears. Who is going to spend the time to link the analysis blocks to the executable blocks and then keep that mapping up to date. This is illustrated in the following picture: [img_assist|nid=5584|title=|desc=|link=none|align=undefined|width=539|height=295] For mainstream software development resulting from 'BPM as a discipline', we believe that the original analysis diagram should serve as input with the rest of the software requirements. Developers should then construct an executable process that looks as close as possible to the original analysis diagram. After that, the analysis diagram is discarded and replaced by the executable process diagram. That way, the developer is in full control of the software technical aspects, while the analyst will still recognize the diagram. jBPM's jPDL language is designed to facilitate this approach. First of all, it's based on free graph modeling. Secondly, it has so called actions, which can be seen as event listeners. These event listeners are pieces of Java code that are called when process execution produces the event, but they are hidden from the process diagram. This allows the developer to add programming logic without changing the diagram structure. Also super-states are often used in the context of creating better communication between business analyst and developer. Use Case 2 : Combining template based and ad hoc task management Orchestrating human tasks can be found in most process engines in one form or another. But what is often overlooked is that template based task orchestration only suits for a limited number of scenarios. First the process must be relatively stable. And secondly, enough executions of this process have to happen so that the gain that can be achieved with software support is worth the development effort. A lot of work being done in organizations does not meet those two requirements. For example, organizing a one-time team building event, a restyling of the office space or cleaning up after the sprinkler system went off unexpectedly. For that type of work, people in charge will invent the process on the spot and it will only be executed once. Human Interaction Management (HIM) focuses on this type of work. A story in HIM reflects a task that person creates for which an ad-hoc process will be created. People can get involved in different roles. There are big benefits of tracing such work with a task management system. First, people that get involved with such a task after a while will get instant visibility into the history of the whole story. And secondly, an audit trail is logged automatically. In jBPM 4, the task management component will support this ad hoc human tasks. The combination will be awsome. Human tasks in processes can be specified at a course grained level. When such a process task is created for a person, the assignee can involve other people by creating subtasks and assigning people in different roles to these tasks. Only when the owner decides that the overall task is finished, then the process will continue. Use case 3 : Transactional asynchronous architectures Gregor Hohpe's Entperprise Integration Patterns describes building blocks for asynchronous architectures. These patterns are based on the notion of Message Oriented Middleware (MOM) aka message brokers. MOM's are good at asynchronous transactional communication between two systems and JMS is the Java standard to work with it. Of course point-to-point communication can be set up easily with existing Java infrastructure like Message Driven Beans. But in many cases many of these point-to-point communications are related. For example, to process one order, a message might come from a client into the order processing system. As part of that transaction, a notification might be sent to the warehouse and stock planning team. Eventually after many more steps, a message might be sent back to the client as a confirmation of the order. If all these transactional communications are build linearly, it will be very hard to manage the overall state of order processing. BPEL also focuses on asynchronous architectures, but then in a (web) services environment, rather then a Java environment. In BPEL only (web) services can be invoked and XML based technologies like XPath are integrated. So for more complex calculations, a piece of programming logic needs to be included. To include programming logic in BPEL, it needs t be wrapped and exposed as a service. That can be quite cumbersome in certain situations. In contrast, jPDL is embedded in a Java environment. Such a central dispatching functionality is really suited to be implemented by a process language like jPDL. An incoming message can start a new jPDL process execution or provide a trigger for an existing execution. jPDL allows to include programming logic straight into the process transaction. Cause jPDL is based on a Java architecture, that results into much more flexibility and convenience. Using the central dispatching approach creates immediately more insight into the overall state of a process. In terms of our order processing example, it will be very easy to keep track of the state of each order. Further more, process engines like jPDL collect the history information. This is an extra feature that you get for free when using a process engine in this way. From the history information it is very easy to collect valuable statistical information like the average time in each step of the process. The difference with the use case 'BPM as a discipline' is that in this case, the goal is software technical in nature. The process is looked at from an implementation perspective. There doesn't have to be a relation to a business level analysis process. Use case 4 : Service orchestration Service orchestration is actually a variant of the previous use case 'transactional asynchronous architectures'. Interactions between services on an Enterprise Service Bus (ESB) are usually asynchronous. This time, the communication is not done through sending messages over a MOM, but instead by calling services over an ESB. BPEL is a process language specifically designed for this use case. Apart from a construct to invoke WSDL services, it has a whole infrastructure for supporting conversations. Conversations are so called long running processes. The clue here is that a BPEL process specifies a number of service operations that are being published when a BPEL process is deployed. A BPEL process can then contain receive activities, which mean that the process execution will wait until a service operation invocation is received. In jBPM we have implemented the BPEL process language as on of the languages that we support on top of our Process Virtual Machine. Use Case 5 : Visual programming With visual programming, we will target developers that do not yet have the full skillset to develop in Java. They can graphically specify the activities and draw transitions to indicate the control flow. Instead of typing Java code, just put blocks like 'perform hql query', 'generate pdf', 'send email', 'read file', 'parse xml', 'send msg to esb'. Instead of writing Java, they will be composing software programs by linking activity boxes in the diagram and filling in the configuration details. This will, of course, not have the same kind of flexibility as Java programming itself. Visual programming as we describe it here will not replace programming as we know it today. Today's programmers can be considered the power users and that kind will always be needed. But visual programming can lower the treshold to build applications for developers that have no or limited Java knowledge. The Process Virtual Machine (PVM) is the foundation of jBPM. In the PVM infrastructure it is really easy to add a new activity type. Think of it as a kind of command pattern, where the commands are configurable. So it will be very easy for us to develop new activity types. This way, we can expose the bulk part of the Java programming functionalities as activity types in the jPDL process language. In jPDL, these visual programs will be executable transactionally or without persisting the state of the execution. Use Case 6 : Thread Control Language This is a specific aspect of visual programming that also can be used by experienced developers. Coding multi-threaded Java programs is not easy. In fact, it is at least tedious and mostly pretty hard to code. Starting new threads, passing data into them, joining and making them stop properly can be a challenge. We'll develop a Thread Control Language which lets you specify a multithreaded Java concurrency by drawing forks, joins and method activities. A method activity invokes a methods on your Java object. And the concurrency control is handled by the forks and join in the process. These processes will be executed without any persistence. Use Case 7 : Easy creation of DSLs General purpose process languages are different from domain specific process languages. For example, think of a process language to specify approvals in an Enterprise Content Management (ECM) system. This gives a scoped functionality and a fixed environment. In such cases, a specific process language could be developed for this purpose. One of the advantages of such dedicated languages is that they can be made simple enough so that non technical business users can actually create fully executable processes. Another example of a domain specific process language is SEAM's Pageflow. It allows developers of a JSF based web site to specify the pages and navigations between the pages graphically. There is even an easier way. Instead of creating a full process language for a specific purpose, it is also possible to leverage jPDL's capabilities and just add new node types to it. That is already possible in jBPM 3 and will be peanuts in jBPM 4, even adding graphical support in the process designer for these new node types will be made simple. Conclusion The typical understanding of BPM is that non technical business people create diagrams that then automagically get executed on a BPM system. The first use case 'BPM as a discipline' describes that point of view. The value lies in the fact that non technical business people can communicate with the developers around a diagram. That diagram facilitates the communication between business analysts and developers. But even in that use case, the traditional understanding needs fine tuning. An analysis diagram at some point has to be converted into an executable process. At that moment, the responsibility over the process is transferred from the analyst to the developer. Many vendors have created the tools and illusion that this can be done automagically. But in practice, this black box approach creates more problems then it solves. The description of the 7 individual use cases shows distinct aspects of BPM. Knowing the difference between service orchestration and 'BPM as a discipline' will be key for organizations to select the most appropriate technology. All of the use cases have at least a technical side. That is understandable as all the use cases here target some form of software automation at some point. And other use cases target solely technical aspects. That is why the embeddability of jBPM is so important. Monolithic BPM engines have a high treshold to be incorporated into a typical software development project. jBPM has a big focus on delivering solutions for these distinct use cases to developers in a way that is easy for them to consume and integrate into their own software development project. Tom Baeyens is the founder and lead of JBoss jBPM, the leading open source BPM system. Tom mission is to bring the power of BPM technology into the hands of the developers. He's a frequent speaker at international conferences and maintains a blog at http://processdevelopments.blogspot.com
October 21, 2008
by Tom Baeyens
· 57,150 Views · 1 Like
article thumbnail
Enabling the Hover-Over-Help Feature Using JSP Custom Tags
This article introduces a presentation-tier JEE framework designed to enable the hover-over-help feature without hard coding JavaScript modules in the JSPs in your web or portal applications. The framework is packaged as a jar file for distribution and includes a server-side RESTful web service component and a set of JSP tag handlers which inserts JavaScript and Cascading Style Sheet (CSS) code into HTML files at the page rendering phrase. The targeted users are java developers who only have preliminary experience on writing JavaScript code. 1. Introduction Mouseover is a standard JavaScript event that is raised when the user hovers the cursor over a particular HTML element on a web page. This event has been widely used in web applications for navigation or causing an image or text to change. Hover-over-help, also called hover-over bubble, refers to the process of showing a small popup window when a mouseover event occurs in the browser. The window contains a message to either help the user to use the application or provide additional explanation and data. It is a useful feature which can make your web pages more intuitive and user-friendly and can carry more information on a single page in rich internet applications (RIAs). There are some tips and samples to enable the feature on the internet. However, they are not effective in developing large-scale web applications. Some of caveats include the following: The message contents are directly hard-coded in JavaScript. They are tied-coupled with graphic user interface components, such as text labels in web pages. The re-usability is low. If the same message needs to appear on several pages, the message and the pertaining JavaScript code have to be copied and pasted to each of these pages. It is hard to maintain these duplications in multiple places. The messages are designed to be static and are typically created when the page is designed. It is difficult to insert runtime data into messages on the fly. Portal applications are not completely supported. The framework introduced in this article is designed to address these issues and provides a comprehensive but easy-to-use solution to java developers who don’t have extensive JavaScript experiences. It leverages the JSP taglibary technology, the Dojo framework, and RESTful web services. Reusability in both web and portal environments, performance, and reliability are the factors that have been taken into consideration. 2. Message bubbles and messages 2.1 Message bubbles A message bubble is a rectangle information window containing a message. Each bubble has one color-coded title compartment and one content compartment. The window is decorated by CSS definitions. The image below illustrates a sample message bubble. Figure 1 – a hover-over-help message bubble Bubbles are not viewable in the webpage until the user moves his/her mouse over action labels or images. In this case, the mouse cursor will turn into a finger-pointing hand and the pertaining bubble window will pop up near the hand. 2.2 Data structure The message contents vary from static to dynamic considerably. However, all messages can share a common data structure, which typically consists of four parts: • Message ID: This is the primary key in each message, which is represented as a unique number. Given any single message ID, the framework is able to identify one and only one message. • Message title: This is a character string displayed in the title compartment in a bubble window. • Message content: This is character string that refers to the detail of a help message. The message content can contain HTML elements. • Color code: This is a character string representing the background color scheme of a bubble window. The value must be one of the following strings: “infor”, “data”, “warning”, or “link”. 2.3 Message types Based on the dynamicity of the contents, we categorized all messages into three types. Each of the types is described in this section, with samples provided. 2.3.1 Static Messages This type of message is considered static because its contents always retain the same. A static message can be the definition of a concept, the explanation of a field, or the instruction of a user action. The same messages will appear to any user on the same page when the page is visited. Valid examples include: • This is a example of a static message. • Click on the button below to submit your request. 2.3.2 Variable Messages These messages contain replaceable variables which are represented by tokens. A token is a non-whitespace character string surrounded by “${” and “}”. The token will be completely replaced by its actual value at the page rendering time on the server. The value is based on user data, and normally will not change for a longer-than-user-session period. From users’ perspectives, the same user will see the same message with his customized values when browsing the same page, but different users may see different messages. The following are examples of valid messages in this category: • Your first name ${firstname}. • Your annual goal is to sell ${yourgoalnumber} cars. 2.3.3 Dynamic Messages The messages in this category are the most dynamic ones and contain variables represented by tokens, as well. However, the actual values are populated based on the data associated to the user session. If it happens that a user session is shared by multiple applications, these values may be changed even without a page refresh. This situation typically occurs in portal applications where multiple portlets can access the same user session. It is possible that the same user will read different messages at a different time on the same page. The examples are – • You have talked to ${anumber} clients today. • It is ${servertimestamp} now. 3. Design and implementation In the design, messages are cached at server-side to gain the maximum performance. Two strategies have been implemented to support the hover-over-help feature for each of the message types described in the previous section. 3.1 Message caching Messages can be persisted in a database or flat text file, but regardless of where they are physically stored, they will be loaded and cached at the web container when it starts. The framework includes a class – CacheIntializer which implements the ServerContextListener interface to perform the job. All you need to develop is your own message loader class to retrieve your messages from storage. Your class must implement the com.myuan.tags.bubblemsg.serverside.MessageLoader interface in the framework, and its name must be added as a ContextParameter in the web descriptor. Please refer to the installation section for more details. 3.2 Dojo and CSS Strategy This strategy is designed to support static and variable messages. It can be referred as the push strategy, since help messages are embedded as html elements and pushed to users’ browsers along with the whole web page. No client-server communication is needed once the page download is done. The values will be kept the same until the page is re-loaded again. This strategy relies on a Dojo module to recognize particular “span” elements (listed in list 1) in html files. For each individual message bubble, two span elements are required. The first one represents a visible graphical component in a page, while the second one is the message bubble which isn’t visible for most of the time. When you move the mouse over the first “span” area, an action will be triggered by the browser, and a Dojo method will make the message bubble popped up (illustrated in Figure 1). The “id” attribute in the first “span” element and the “connectid” attribute in the second one are the keys to tie the pair together. These two attributes must have the same value. The value is randomly generated by the custom tags in the framework, which guarantees that the strategy can support both web and portal applications. Households Household A household includes all the persons who occupy a housing unit. Four tag handlers have been developed to support static message and variable message scenarios, respectively. At page-rendering time, the handlers can retrieve help messages from the cache, replace variable tokens in the messages if any, and create and insert value-matched “span” html elements into the web pages. The complete process is detailed in the sequence diagram in figure 2. Figure 2 – sequence diagram for the Dojo and CSS strategy 3.2.1 hohcsstag This tag inserts CSS definitions in JSP pages at the rendering time. It should be placed in the page head element. In the WebSphere Portal environment, this tag should be added in the Default.jsp file. 3.2.2 hohstatictag hohstatictag is a custom tag built for the static message scenario. It has five attributes: msgid: This is the primary key used to identify a message from the cache. This attribute is mandatory. label: This is the text which will be associated with a mouse-over action to display the message. style: This is the style definition that will be used to decorate the label above. This is the place where the user could overwrite CSS arributes for the label. bubblestyle: This is the place where the user could overwrite CSS attributes for the message bubble. img: If you need to enable the hover-over on an image instead of a text label, you can use this attribute and pass the path to your image. If this attribute appears in the tag, the value in the “label” and the “style” attributes will be ignored. A static message example -- Msg_id Msg_title Msg_content Color_cd 1 Household A household includes all the persons who occupy a housing unit. Infor JSP Fragment where the hohstatictag is used – //text //image 3.2.3 hohvariabletag and hohparamtag hohvariabletag and hohparamtag work together to support variable messages. The “hohvariabletag” has the same four attributes as the “hohstatictag” tag. One “hohparamtag” tag holds one name-value pair. The tokens in the message will be replaced with the values passed in from the hohparamtag when html elements are generated. The following is an example of how to use the custom tag. A variable message example-- Msg_id Msg_title Msg_content Color_cd 2 Recognition My retention rate is ${rate} and my goal is ${goal}. data JSP Fragment where the hohvariabletag and hohparamtag are used together – 3.2.4 hohgenerictag This tag has been created to provide a unified API for both static and variable messages. This tag can replace the “hohstatictag” or “hohvariabletag” without any syntax change. But there will be a minor performance cost if you use this tag on the static-message scenario instead of the hohstatictag. 3.3 AJAX strategy AJAX (Asynchronous JavaScript and XML) is a powerful web development technique in creating interactive web applications. The AJAX strategy was developed for the dynamic message scenario. It is a pull-based model, since messages are retrieved by an AJAX module at runtime from the server. This approach can guarantee that the message contains the latest data. When a mouseover event is triggered from a web page, the AJAX module invokes the server-side RESTful web service endpoint. The server-side component picks up the correct message from the message cache, replaces all variable tokens in it with the most current user-session data, and sends the final message back to your browser in the XML format. Upon receiving the response, the AJAX module populates the pertaining information window and pops it up. The complete process is illustrated in the sequence diagram in figure 3. Figure 3 – Sequence diagram for the AJAX strategy One servlet class and three custom tags have been created to support this strategy, and they must be used together in the same page. 3.3.1 HelpMessagesServiceServlet This is an extension of the HTTPSerlvet class. It serves as the RESTful web service endpoint at the server-side. It processes the HTTP request from the client-side AJAX module, constructs the message with the latest data in user’s session, and sends the response in XML format back to the browser. A sample response is listed below. Household infor Household A household includes all the persons who occupy a housing unit. 3.3.2 hohajaxtag This tag inserts AJAX methods in a JSP which will be invoked by the hohdynatag below. It has two attributes. The namespace can be used to pass a portlet’s namespace into the tag in the portal environment. In a web application the value of the attribute can be left blank. The serviceurl attribute must be the valid URL for the HelpMessagesServiceServlet. In the WebSphere Portal environment, this tag should be added in the Default.jsp file. // Portal environment // Web environment 3.3.3 hohdynatag and hohdynaparamtag The hohdynatag has four attributes as same as the “hohstatictag” tag, and it will generate a “span” element. Each hohdynaparamtag establishes a mapping between one token in the message and one key used in user’s session to refer to the actual value. These mappings will be sent to the RESTful endpoint as HTTP parameters. When a user’s mouse moves over the area in a page represented by the span tag, the following events will occur sequentially at the client’s browser: • OnMouseOver events will be fired by the browser. • The Ajax method generated by the hohajaxtag will be invoked. The method will make an HTTP request to the RESTful service endpoint and will be waiting for the response. • Upon receiving the response, the AJAX method will parse it to get the actual help message. • The AJAX method will display the message bubble in the browser. Below is a valid utilization of these tags. 4. Installation The installation procedure is fairly straight forward. After adding the jar file – MYTagLib.jar -- into the /WEB-INF/lib directory in your web project, you can use the deployment descriptor editor in RAD/RSA to complete the installation: Develop your own message loader class and add a context parameter with the name “BubbleMsgLoaderClass” and the value as the fully qualified name of your class. Figure 4 – adding your class name as a Server Context Parameter Create a listener. The class name is: com.myuan.tags.bubblemsg.serverside.CacheInitializer, and the class is shipped in the TagLib.jar file. Figure 5 – creating the listener with the shipped class Add the servlet class in the framework into the deployment descriptor in your web project. The servlet class is also shipped in the MYTagLib.jar. Figure 6 – creating a servlet with the shipped class Define the taglib element in the /WEB-INF/web.xml file. Figure 7 – adding the tag lib references Define the tag extension in your JSP pages. The and the uri directive must match. The prefix identifies the tags in the tag library within the jsp page. For example: 5 Conclusion The framework packaged in the MYTagLib.jar can enable the hover-over-help feature in a web or portal application without adding any JavaScript/CSS code into JSP pages during the development phrase. This approach can make it simpler to create and maintain these pages. The framework has been tested in web applications running on WebSphere Application Server (WAS) 6.0 and 6.1, as well as in portal applications running on WebSphere Portal 5.1 and 6.0.
October 21, 2008
by Ming Yuan
· 39,574 Views · 1 Like
article thumbnail
Adding Color and Font preferences
You had that nice looking editors and views. You loved the button color and the geeky font. But your boss didn't. Solution? Put a preference so that the user can choose which ever he likes ;-) Ok. That may not be the real rationale, but for a valid reason, you wanted to have Color and Font preferences in the PreferencePage. The obvious answer for us (the plugin develoepers) would be to add ColorFieldEditor & FontFieldEditor in our existing PreferencePage. But its not obvious for the user to look into your plugins Preference Page for changing them. Eclipse already provides a PreferencePage for these customizations: Colors and Fonts page ( General->Appearance->Colors and Fonts ) Users might be looking into this place to change the colors & fonts. As you can see in the above image it categorizes the available preferences; gives a filter to search; provides space for description and preview; and a tool tip for the current value of the preference. This is much more than the *FieldEditor right? In this tip let us see how to add our preferences into that and access them. You need to extend the org.eclipse.ui.themes extension point for adding your content into this page. I would like to provide one category with one color preference and one font preference. The extension is: An example theme category Your description goes here Description for this font Guess all the elements are self explanatory - except for the value element. For colorDefinition the value element will be the COLOR_* constants defined in the SWT class. You can specify your custom colors thru comma separated RGB values like 125,245,96. For fontDefinition it would be fontname-style-height. Now our UI will look like: To get the values stored in the preferences, you need to use the IThemeManager: IThemeManager themeManager = PlatformUI.getWorkbench().getThemeManager(); ITheme currentTheme = themeManager.getCurrentTheme(); ColorRegistry colorRegistry = currentTheme.getColorRegistry(); Color color = colorRegistry.get("com.eclipse-tips.blog.preferences.colorDefinition"); FontRegistry fontRegistry = currentTheme.getFontRegistry(); Font font = fontRegistry.get("com.eclipse-tips.blog.preferences.fontDefinition"); Once you get the current theme, you can get the preferences stored by giving the appropriate ids defined in the plugin.xml What you have seen is just the tip of the iceberg. The themes extension point has much more functionalities (The Preview is one such example). I'll explain them later, but you can see the Extension Point description here. This is an extract from http://blog.eclipse-tips.com/2008/08/adding-color-and-font-preferences.html
October 15, 2008
by Prakash
· 13,849 Views
article thumbnail
A Simple Manual Mock Example
Creating and using a mock object is semantically very much like using a stub, except that a mock will do a little more than a stub - it will save the history of communication so that it can later be verified. Let's add a new requirement to our LogAnalyzer class. It will have to interact with an external web service that will receive an error message whenever the LogAnalyzer encounters a filename whose length is not too long. [img_assist|nid=5444|title=|desc=|link=url|url=http://www.manning.com/osherove/|align=left|width=142|height=178]Unfortunately, the web service we'd like to test against is still not fully functional, and even if it were, it would have taken too long to use it as part of our tests. Because of that, we'll refactor our design and create a new interface that we can use to later create a mock object of. The interface will have the methods we will need to call on our web service, and nothing else. Figure 1 shows how the test will work with our MockWebService. [img_assist|nid=5443|title=|desc=|link=none|align=none|width=485|height=350] First off, let's extract a simple interface that we can use in our code under test, instead of talking directly to the web service. public interface IWebService { void LogError(string message); } This interface will serve us when we want to create stubs as well as mocks, without needing to have an external dependency on a project we have no control of. Next, we'll create the mock object itself. It may look like a stub, but it contains one little bit of extra code that makes it a mock object. public class MockService:IWebService { public string LastError; public void LogError(string message) { LastError = message; } } Our mock implements an interface just like a stub, but saves some state for later, so that our test can then assert and verify that our mock was called correctly. Listing 1 shows what the test might look like: Listing 1: The log analyzer under test actually calls our mock object, which holds on to the string that is passed into the implemented method, and later asserted in the test. [Test] public void Analyze_TooShortFileName_CallsWebService() { MockService mockService = new MockService(); LogAnalyzer log = new LogAnalyzer(mockService); string tooShortFileName="abc.ext"; log.Analyze(tooShortFileName); Assert.AreEqual("Filename too short:abc.ext", |#1 mockService.LastError); |#1 } public class LogAnalyzer { private IWebService service; public LogAnalyzer(IWebService service) { this.service = service; } public void Analyze(string fileName) { if(fileName.Length<8) { service.LogError("Filename too short:" |#2 + fileName); |#2 } } } Annotation #1: The assert is done against the mock service, and not against the class under test Annotation #2: The method part we're going to test Notice how the assert is performed against the mock object, and not against the LogAnalyzer class. That's because we are testing the interaction between LogAnalyzer and the web service. We still use the same dependency injection techniques, but this time the stub also makes or breaks the test. That's why it's a mock object. Also notice that we are not writing the tests directly inside the mock object code. There are several reasons for this. We'd like to be able to re-use the mock object in other test cases, with other asserts on the message. If the assert is found inside the mock object, whoever is reading the test will have no idea what we are asserting. We will be hiding essential information from the test code, which hinders the readability and maintainability aspect of the test. In many scenarios in your tests, you might find that you need to replace more than one object for the test to be able to work, which involves combining mocks and stubs. This article is taken from the book The Art of Unit Testing. As part of a chapter on interactive testing using mock objects, this segment shows how to create and use a mock object and helps differentiate mock objects from stubs.
October 13, 2008
by Schalk Neethling
· 31,518 Views
article thumbnail
How to Parse and view Outlook .msg Files programmatically
This article shows that how can you parse and view Outlook .msg files using your own code in C# applications where Microsoft Office Outlook is not required for it. A separate Outlook msg Viewer Demo (attached with this article) is also available to guide you for parsing and reading Outlook .msg files using Aspose.Network library. How to Parse and View Msg File contents Programmatically In this section, we will present the code that we used in the demo to show the msg file contents. Loading an Msg File Aspose.Network library provides MapiMessage class for loading and parsing msg files. You can load the msg file using a single line of code by calling FromFile() static method and passing the path of the msg file. [C#]MapiMessage msg = MapiMessage.FromFile(“C:\\SomeFolder\\SomeMsgFile.msg”); [VB.NET]Dim msg As MapiMessage = MapiMessage.FromFile(“C:\\SomeFolder\\SomeMsgFile.msg”) Getting the From, To, Cc and Subject from Msg File MapiMessage class exposes properties and collections for getting subject, to, cc and from. Following is the sample code for getting these properties. [C#]// subjectif (msg.Subject != null)Console.WriteLine(msg.Subject);elseConsole.WriteLine("no subject");// senderif (msg.SenderEmailAddress != null)Console.WriteLine(msg.SenderEmailAddress);elseConsole.WriteLine("No sender");// toif (msg.DisplayTo != null)Console.WriteLine(msg.DisplayTo);elseConsole.WriteLine("No one in To");// ccif (msg.DisplayCc != null)Console.WriteLine(msg.DisplayCc);elseConsole.WriteLine("No one in cc"); [VB.NET]' subjectIf Not msg.Subject Is Nothing ThenConsole.WriteLine(msg.Subject)ElseConsole.WriteLine("no subject")End If' senderIf Not msg.SenderEmailAddress Is Nothing ThenConsole.WriteLine(msg.SenderEmailAddress)ElseConsole.WriteLine("No sender")End If' toIf Not msg.DisplayTo Is Nothing ThenConsole.WriteLine(msg.DisplayTo)ElseConsole.WriteLine("No one in To")End If' ccIf Not msg.DisplayCc Is Nothing ThenConsole.WriteLine(msg.DisplayCc)ElseConsole.WriteLine("No one in cc")End If Getting the Text Body and Rtf Body of the Message We can get Text and Rtf body of the message by using properties of MapiMessage class. Following the sample code to get these. [C#]// text bodyif (msg.Body != null)Console.WriteLine(msg.Body);elseConsole.WriteLine("no text body.");// rtf bodyif (msg.BodyRtf != null)Console.WriteLine(msg.BodyRtf);elseConsole.WriteLine("No Rtf body."); [VB.NET]' text bodyIf Not msg.Body Is Nothing ThenConsole.WriteLine(msg.Body)ElseConsole.WriteLine("no text body.")End If' rtf bodyIf Not msg.BodyRtf Is Nothing ThenConsole.WriteLine(msg.BodyRtf)ElseConsole.WriteLine("No Rtf body.")End If Getting the Attachments From Msg File and Saving to Disk MapiMessage class provides the Attachments collection for getting all the attachments in the message (msg) file. MapiMessage.Attachments property returns the object of type MapiAttachmentCollection. You can use a foreach loop to iterate through the attachments collection and list the attachments. Attachment class contains the Save() method for saving the individual attachment to the disk. Following is the sample code to get the list of attachments and saving to disk. [C#] // iterate through the Attachments collection foreach (MapiAttachment att in msg.Attachments) { try { // show attachment name on screen Console.WriteLine(att.LongFileName); // save in local drive/folder att.Save(att.LongFileName); } catch (Exception ex) { Console.WriteLine(ex.Message;) } } [VB.NET]' iterate through the Attachments collectionFor Each att As MapiAttachment In msg.AttachmentsTry' show attachment name on screenConsole.WriteLine(att.LongFileName)' save in local drive/folderatt.Save(att.LongFileName)Catch ex As ExceptionConsole.WriteLine(ex.Message;)End TryNext att Getting the MAPI Properties of the Msg File You can get the MAPI Properties from the Msg file using the “Properties” collection of the MapiMessage class. Following is the sample code to get all the MAPI properties present in the message file. [C#]try{Aspose.Network.Outlook.MapiProperty mapi = Aspose.Network.Outlook.MapiProperty)dictionaryEntry.Value;if (mapi.Name.Trim().Length > 0){// display name of MAPI propertyConsole.WriteLine(mapi.Name);// display value of the MAPI propertyConsole.WriteLine(mapi.ToString());}catch (Exception e){Console.WriteLine(e.Message);} [VB.NET]TryDim mapi As Aspose.Network.Outlook.MapiProperty = Aspose.Network.Outlook.MapiProperty)dictionaryEntry.ValueIf mapi.Name.Trim().Length > 0 Then' display name of MAPI propertyConsole.WriteLine(mapi.Name)' display value of the MAPI propertyConsole.WriteLine(mapi.ToString())End IfCatch e As ExceptionConsole.WriteLine(e.Message)End Try More about Aspose.Network for .NET Aspose.Network is a suite of .NET components for network programming with support for .NET logging framework, Microsoft Exchange Server and allows parsing an Outlook document with drag & drop features. It provides new iCalendar engine and SSL support for SMTP, POP3 & IMAP protocols with other mail merge features. You can import & export emails in MHT & EML formats. It supports all the features of SMTP, MIME, S/MIME, POP3, FTP, WhoIs, DNS, ICMP, IMAP, HTTP, SOCKS 4/4A & SOCKS 5 components.
October 8, 2008
by rouletteroulette rouletteroulette
· 67,481 Views
  • Previous
  • ...
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • ...
  • Next
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook
×