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 Java Topics

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,848 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,504 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,729 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,993 Views
article thumbnail
Getting Javadoc from Maven Repositories
In my previous tip on NetBeans Zone we learned how to get available sources for a Maven dependency. We can also get Javadoc for the library. The Javadoc must be available of course otherwise NetBeans is not able to download anything. We right-click on Libraries in our project and select Download All Library Javadoc. NetBeans downloads the Javadoc for the libraries if it is available. The icon will change for the library if Javadoc is downloaded. To view the Javadoc we must right-click on the library and select View Javadoc. NetBeans opens a web browser with the Javadoc for the specific library.
December 21, 2008
by Hubert Klein Ikkink
· 12,080 Views · 2 Likes
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,895 Views
article thumbnail
Configuring Logging in JBoss
Learn how to properly configure logs in JBoss.
November 19, 2008
by Meera Subbarao
· 223,172 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,665 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,809 Views
article thumbnail
Clearing Hibernate Second-Level Caches
Recently, I wanted to be able to clear out all of the Hibernate caches via JBoss's JMX console. I could have taken the easy way out; we're using EHCache, so it could have been as simple as calling CacheManager.clearAll(). However, that would have tied me to a specific cache provider. We're still evaluating switching to other cache providers. Ideally, my solution would not be dependent on a specific cache implementation. Hibernate's API does provide a simple way to clear specific caches, but does not provide any method for clearing out all of them. Writing your own is fairly straightforward. First, you obtain all of the entity and collection metadata from the session factory. Next you iterate over the entities, and if the object is cached, you clear out all of the caches associated with the persisted class or collection. Here's the code: @PersistenceContext private EntityManager em; public void clearHibernateCache() { Session s = (Session)em.getDelegate(); SessionFactory sf = s.getSessionFactory(); Map classMetadata = sf.getAllClassMetadata(); for (EntityPersister ep : classMetadata.values()) { if (ep.hasCache()) { sf.evictEntity(ep.getCache().getRegionName()); } } Map collMetadata = sf.getAllCollectionMetadata(); for (AbstractCollectionPersister acp : collMetadata.values()) { if (acp.hasCache()) { sf.evictCollection(acp.getCache().getRegionName()); } } return; } Now, if we decide to switch to a different cache provider, this code will not need to be re-written. Hopefully we won't ever change to a different JPA implementaion. :) From http://mikedesjardins.us/blog/
October 24, 2008
by Mike Desjardins
· 65,030 Views · 1 Like
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,224 Views · 1 Like
article thumbnail
A Look Inside the JBoss Microcontainer, Part I -- Component Models
Looking at the current state of Java, we can see that POJOs (Plain Old Java Objects) rule the land yet again. Their dominance stretches from enterprise applications to middleware services. At JBoss we were known for our modular JMX-based kernel. The application server was nothing more than a bunch of flexible MBeans and a powerful MicroKernel in the middle. But, as you could feel the change is coming, we still wanted to be ahead of the pack. We could see different POJO based component models popping up all over the place (EJB3, JPA, Spring, Guice, … to name a few), yet nothing was out there that would bind them all, flattening out the differences on a single component model. Hence the Microcontainer project was born. The JBoss Microcontainer project is about many things. The Microcontainer's features range from reflection abstraction, a virtual file system, a simple state machine to transparent AOP integration, a new classloading layer, a deployment framework and an OSGi framework implementation. I'll try to address them all over a short series of articles that will be published here on DZone. This article will examine the Microcontainer's component models. Read the other parts in DZone's exclusive JBoss Microcontainer Series: Part 1 -- Component Models Part 2 –- Advanced Dependency Injection and IoC Part 3 -- the Virtual File System Part 4 -- ClassLoading Layer Part 5 - the Virtual Deployment Framework Part 6 - The Scanning Library What is a component model? What do we consider a component model? First of all, what do we consider being a component? One abstract way to express this would be that “components are reusable software programs that you can develop and assemble easily to create sophisticated applications.” To consider a bunch of components as an actual model, we also need to declare what kind of interactions we allow. JMX MBeans are one example of a component model. Their interactions include executing MBean operations, referencing attributes, setting attributes and declaring explicit dependencies between named MBeans. As mentioned, we had advanced JMX handling already with the MicroKernel. And as expected, the Microcontainer brought extensive POJO support. The default behavior and interactions in the Microcontainer are what you also normally get from any other IoC container and are similar to the functionality that MBeans provided: plain method invocations for operations, setters/getters for attributes and explicit dependencies. However, having only this functionality would mean we didn't get much further than just relieving the pain of declaring MBeans, hence it was only logical for us to do something more. I'll leave the discussion of these new IoC features for the next article in the series. There are many existing POJO component models out there, Guice and Spring being amongst the most popular. Effective integration with these frameworks was an important goal for us. Demo environment setup Before we begin, I'd like to first describe the various parts that constitute the demo. All the source code can be found at this location of our Subversion repository: • http://anonsvn.jboss.org/repos/jbossas/projects/demos/microcontainer/branches/DZone_1_0/ The project is fully mavenized, so it should be easy to adjust it to your IDE. I will first go over the sub-projects within the demo and describe their usage. At the end of my article series, I will provide a more detailed look at what certain sub-projects do. Below are the JBoss Microcontainer demos and sub-projects that are relevant for this article: • bootstrap (as the name suggests, it bootstraps the Microcontainer with demo code) • jmx (adds the JMX notion to demo's bootstrap) • models (source code of our components / services) The demo has only one variable you need to set - demos home - but even this one can be optional if you checked-out your project into the \projects\demos directory. Otherwise, you need to set the system property demos.home (e.g. -Ddemos.home=). You should now be able to run JMXMain as a main class. Make sure you include the models sub-project in the classpath, since some of the services require additional classes in the classpath, several more then what the jmx sub-project expects. Once the Microcontainer is booted it starts to scan the ${demos.home}/sandbox directory for any changes. Now all we need to do is provide a deployable unit and drop it in there. Models Let’s now turn our attention to the models sub-project. This is where the previously mentioned deployable unit should come from. You can see if everything is in place by building the models sub-project (mvn package) and dropping it into the sandbox. You should get a bunch of debug and info messages on the console log, showing how the Microcontainer got booted. Any error message indicates some problems. Let’s go over exactly what the models sub-project does, its integration code and try to redeploy it. If we look at the models src/main/resources/META-INF directory, we'll see plenty of -beans.xml resource files and one -service.xml. You’ll notice that each has a meaningful name that matches the source code package from models's src/main/java/org/jboss/demos/models directory. Let's dissect them one by one, starting with the ones that have no dependencies. org.jboss.demos.models.plain.PojoFactory This is a simple Micrcocontainer beans descriptor file. Anyone who crossed paths with some other IoC’s configuration file should be familiar with it. And, as I already mentioned, I'll follow up on more advanced usage in the next article. The next file shows what we have done to support Spring integration: Note that this file's namespace is different from the previous Microcontainer bean’s plain-beans.xml file. The urn:jboss:spring-beans:2.0 namespace points to our version of the Spring schema port, meaning you can describe your beans Spring style, but it's the Microcontainer that's going deploy then, not Spring's bean factory notion. public class Pojo extends AbstractPojo implements BeanNameAware { private String beanName; public void setBeanName(String name) { beanName = name; } public String getBeanName() { return beanName; } public void start() { if ("SpringPojo".equals(getBeanName()) == false) throw new IllegalArgumentException("Name doesn't match: " + getBeanName()); } } Although the SpringPojo bean has a dependency on Spring lib via implementing BeanNameAware interface, this dependency is only there to expose and mock some of the Spring's callback behavior (see SpringBeanAnnotationPlugin for more details). Since we introduced Spring integration, let's have a look at Guice integration. As Guice users know, Guice is all about type matching. Configuration of Guice beans is done via Modules which means that in order to generate beans, one must implement a Module. Two important parts to watch from this file are PojoModule and GuiceKernelRegistryEntryPlugin. The first one is where we configure our beans: public class PojoModule extends AbstractModule { private Controller controller; @Constructor public PojoModule(@Inject(bean = KernelConstants.KERNEL_CONTROLLER_NAME) Controller controller) { this.controller = controller; } protected void configure() { bind(Controller.class).toInstance(controller); bind(IPojo.class).to(Pojo.class).in(Scopes.SINGLETON); bind(IPojo.class).annotatedWith(FromMC.class).toProvider(GuiceIntegration.fromMicrocontainer(IPojo.class, "PlainPojo")); } } The second class provides integration with the Microcontainer: public class GuiceKernelRegistryEntryPlugin implements KernelRegistryPlugin { private Injector injector; public GuiceKernelRegistryEntryPlugin(Module... modules) { injector = Guice.createInjector(modules); } public void destroy() { injector = null; } public KernelRegistryEntry getEntry(Object name) { KernelRegistryEntry entry = null; try { if (name instanceof Class) { Class clazz = (Class)name; entry = new AbstractKernelRegistryEntry(name, injector.getInstance(clazz)); } else if (name instanceof Key) { Key key = (Key)name; entry = new AbstractKernelRegistryEntry(name, injector.getInstance(key)); } } catch (Exception ignored) { } return entry; } } Notice how we created an Injector from the Modules and then did a lookup on it for matching beans. In mbeans-service.xml we declare our legacy usage of MBeans: What’s interesting to note here is how we injected a POJO into an MBean. The preceding demonstrated our first interactions between different component models. In order to allow for MBean deployment via the Microcontainer, we had to write entirely new component model handling code. See the system-jmx-beans.xml for more details. The code from this file lives in the JBossAS source code: system-jmx sub-project. One note here, this is currently only possible with JBoss's JMX implementation, since the system-jmx code uses some implementation details. Now what if we wanted to expose our existing POJOs as MBeans, registering them into an Mbean server? @org.jboss.aop.microcontainer.aspects.jmx.JMX(exposedInterface=org.jboss.demos.models.mbeans.PojoMBean.class, registerDirectly=true) As you can see from looking at any of the beans in this file, in order to expose your POJOs as MBeans, it’s simply a matter of annotating them with an @JMX annotation. You can either expose the bean directly or its property: Here we see how you can use any of the injection lookup types by either looking up a plain POJO or getting a handle to an MBean from the MBean server. One of the injection options is to use type injection, which is also sometimes called autowiring: The FromGuice bean injects the Guice bean via type matching, where PlainPojo is injected with a common name injection. We then test if Guice binding works as expected: public class FromGuice { private IPojo plainPojo; private org.jboss.demos.models.guice.Pojo guicePojo; public FromGuice(IPojo plainPojo) { this.plainPojo = plainPojo; } public void setGuicePojo(org.jboss.demos.models.guice.Pojo guicePojo) { this.guicePojo = guicePojo; } public void start() { f (plainPojo != guicePojo.getMcPojo()) throw new IllegalArgumentException("Pojos are not the same: " + plainPojo + "!=" + guicePojo.getMcPojo()); } } This only leaves us with an alias component model. Even though the alias is quite a trivial feature, in order to implement it as a true dependency, it has to be introduced as a new component model inside the Microcontainer. The implementation details for this is part of the AbstractController source code: springPojo Here we’ve mapped the SpringPojo name to the springPojo alias. The beauty of having aliases as true component models is that it doesn't matter when the real bean gets deployed. This means that the alias will wait in a non-installed state until the real bean triggers it. Conclusion We've seen how we can deploy simple Microcontainer beans, legacy MBeans, Guice POJOs, Spring beans and aliases. And since all of this is controlled by the Microcontainer, we saw how easily we can mix and match the different component models. I can easily say, with the level of abstraction we put in our component model design, the sky is the limit on what we can handle. An example of this is the upcoming OSGi services, but that's another story, another article. Stayed tuned for my next article which will provide a detailed look at the Microcontainer's IoC functionality. About the Author Ales Justin was born in Ljubljana, Slovenia and graduated with a degree in mathematics from the University of Ljubljana. He fell in love with Java seven years ago and has spent most of his time developing information systems, ranging from customer service to energy management. He joined JBoss in 2006 to work full time on the Microcontainer project, currently serving as its lead. He also contributes to JBoss AS and is Seam and Spring integration specialist. He represent JBoss on 'JSR-291 Dynamic Component Support for Java SE' and 'OSGi' expert groups.
October 1, 2008
by Ales Justin
· 57,386 Views
article thumbnail
Javadoc or Doxygen?
In the last two articles, "Reverse-engineer Source Code into UML Diagrams" and "Visual Documentation of Ant Dependencies in 3 Simple Steps" we saw how easy and valuable it was to automate technical documentation. By using open source tools, we were easily able to provide good technical documentation within a few minutes, and at no cost at all. We were also able to keep this up-to date by adding additional tasks to our Ant build files, and run them from our CI Server(Hudson in our case) on commit and nightly builds, and also publish the results. In this article, I will be showing you how to use yet another tool called Doxygen for generating technical documentation based on your source code. We all have used Javadoc and have been using it for a long time, right? So, you may ask what's the need to have another tool which produces the same HTML documentation? Doxygen has a slight edge over Javadoc and here are a few reasons why you should consider using the same: With Javadoc you have to remember all the HTML tags, you need to embed within your code comments. However, with Doxygen code comments are much more concise and polished, without the need for any HTML. Doxygen can also generate a variety of diagrams, we will take a look at some of them later. Doxygen also provides a structured view on the source code. As I mentioned in 2 above in the form of various diagrams, cross-referenced and syntax highlighted code. You get all the above benefits even if the code does not have any comments at all. Last but not the least, Doxygen is a documentation system not for just Java but also for various other languages like C++, C, Java, Objective-C, Python, IDL (Corba and Microsoft flavors), Fortran, VHDL, PHP, C#. So, without wasting further time, lets see what we need to get started with Doxygen. Step 1. Download, Install Doxygen. Download the binary distribution for Doxygen for the operating system you are using. I downloaded the binary distribution for Mac OS X called Doxygen-1.5.6.dmg. Installation is very simple, just drag the doxygen icon from this folder to the Applications folder, or wherever you want to keep it; as shown. I dropped it within my Applications folder. Just be sure to remember where you dragged it. To uninstall, just delete the file. It is completely self-contained. Step 2: Configure Doxygen. To generate documentation using Doxygen, you will need a configuration file called the Doxyfile. You can generate this file in two ways; either by using the Doxygen wizard or by using the command line option. Lets see how to use both these options to generate the configuration file: a. Command line. Open a command window and type the following as shown below: You should be able to locate the configuration file created within your default user folder. The file looks like this: # Doxyfile 1.5.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = b. Wizard Option. Launch the Doxygen application, and you should be able to create the configuration file using the wizard approach as shown below. The user interface is quite intuitive so I am going to skip explaining this in detail. The wizard approach was the one I used to get the initial settings for the configuration file. which you can always modify later. A few options in my Doxygen configuration file are as follows: # Doxyfile 1.5.6 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = PetStore PROJECT_NUMBER = 1.0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = YES #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html GENERATE_TREEVIEW = YES Step 3. Doxygen and Ant. In order to use Doxygen, we need an Ant task. There is already an Ant task written for Doxygen which you can download from here. As always, since using Mac, when I downloaded the binaries and tried to use them, I got the ever famous error message : java.lang.UnsupportedClassVersionError: Bad version number in .class file So, had to do download the source, compile, and jar it up. Copy this library to your projects folder. Next, lets start making changes to our build file. 3.a: Lets define the Doxygen task. 3.b: To generate HTML documentation: 3.c: Lets combine them in target and run: [doxygen] Exec: /Applications/Doxygen.app reports/Doxyfile BUILD FAILED /CodeMetricsProject/build.xml:91: Doxygen not found on the PATH. Total time: 7 seconds 3.d: So, to launch Doxygen not in the path. we make change to the doxygen task as shown below: Lets run the target again and see if it fixed things.Yes indeed. generate-doxygen-docs: [doxygen] Exec: /Applications/Doxygen.app/Contents/Resources/doxygen reports/Doxyfile BUILD SUCCESSFUL Total time: 8 seconds 4. Integrate with Hudson. 4.a Modify Hudson Job. Once you have an Ant target working, calling this from your CI server is trivial. Within Hudson, select your Job, click on configure and add this new target to be called when running the build. 4.b Publish the reports. 4. c: Sample Reports. Force a build, and take a detailed look at the reports generated by Doxygen as shown below: I have given you a brief overview of Doxygen in this article, how to configure the same, and use it effectively to generate technical documentation on a continuous basis; either on commit builds or nightly builds. The Doxygen web site has lots of information on how to use it with other programming languages and also has tutorials in languages other than English as well. As always, if you are having trouble getting Doxygen to work, leave a comment or check out the Doxygen web site.
September 10, 2008
by Meera Subbarao
· 49,791 Views · 1 Like
article thumbnail
32 bit JDK on a 64 bit Ubuntu System
If you have more than 3GB on your machine and you’re running Ubuntu you’ve probably had to figure out how to access that additional memory – the default Ubuntu desktop kernel will only allow access to the first 3GB. You can install the server kernel, but that’s been tuned for a server with different latency settings, etc. You can recompile the desktop kernel with HIGHMEM64 set, but then you’re stuck building the video drivers yourself. My latest strategy has been to use the 64 bit kernel. 64 bit support is not bad now and most apps run normally. Of course they use about double the memory. If you’re running a lot of Java processes this 64 bit tax is very noticeable. For my needs, 32 bit Java is fine, even with a 64 bit kernel. Ubuntu/Debian ship a 32 bit JRE (ia32-sun-java6-bin). This package provides only the runtime environment (no javac) and the client VM so it has limited usefulness for a developer. To install the 32 bit JDK from Sun on a 64 bit system you can use java-package. I’ve been running Eclipse and all my development applications and finally have some free memory again. Installation First, download the latest 32 bit JDK (not JRE) from Sun. At the time this was jdk-6u7-linux-i586.bin for me. Install java-package: sudo apt-get install java-package Now use java-package to build a .deb package from the binary you downloaded. You have to trick it into building the 32 bit package: DEB_BUILD_GNU_TYPE=i486-linux-gnu DEB_BUILD_ARCH=i386 fakeroot make-jpkg jdk-6u7-linux-i586.bin This should generate a .deb package. For some reason the package name has the _amd64 suffix. Install the package: sudo dpkg -i sun-j2sdk1.6_1.6.0+update7_amd64.deb Use update-alternatives to select the new JDK. It was installed at /usr/lib/j2sdk1.6-sun for me. sudo update-alternatives --config java If you run java -version you should see the correct version: java version "1.6.0_07" Java(TM) SE Runtime Environment (build 1.6.0_07-b06) Java HotSpot(TM) Server VM (build 10.0-b23, mixed mode) 32 bit Eclipse I had to reinstall the 32 bit version of Eclipse (since SWT contains native code). I also had to delete my ~/.eclipse directory or Eclipse wouldn’t start (this requires reinstalling new versions of any plugins). Finally, add the new JRE in Java->Installed JREs using the install location (/usr/lib/j2sdk1.6-sun) and select it as the default. From http://dmy999.com/
September 9, 2008
by Derek Young
· 100,349 Views
article thumbnail
An Introduction to Aspect-Oriented programming with JBoss AOP
JBoss Application Server ships with support for aspect-oriented programming, so you can use AOP in your applications deployed in JBoss AS. JBoss AS 5, which is currently available as a community release, has AOP built into its core. However, JBoss AOP is also available as a standalone framework for use in your other applications. This article will take a simple example, and use JBoss AOP to add to its behaviour, while explaining some of the core functionality of JBoss AOP. We will look at encapsulating cross-cutting concerns into aspects, have a look at around advices vs the new lightweight advices in the upcoming JBoss AOP 2.0 release, and also look at using interface-introductions and mixins to add interfaces to your classes. Table of Contents Our Core Application Our Core Application The application we will look at is is a simple banking application. It has a BankAccount class: package bank; public class BankAccount { int accountNumber; int balance; public BankAccount(int accountNumber) { System.out.println("*** Bank Account constructor"); this.accountNumber = accountNumber; } public int getAccountNumber() { return accountNumber; } public int getBalance() { return balance; } public void debit(int amount) { System.out.println("*** BankAccount.debit()"); balance -= amount; } public void credit(int amount) { System.out.println("*** BankAccount.credit()"); balance += amount; } } In addition it has a main Bank class: package bank; import java.util.HashMap; import java.util.Map; public class Bank { static Map bankAccounts = new HashMap(); public static void transfer(BankAccount from, BankAccount to, int amount) { from.debit(amount); to.credit(amount); } public static void main(String[] args) { System.out.println("*** Creating account 1"); BankAccount acc1 = new BankAccount(1); acc1.credit(150); bankAccounts.put(acc1.getAccountNumber(), acc1); System.out.println("*** Creating account 2"); BankAccount acc2 = new BankAccount(2); acc2.credit(230); bankAccounts.put(acc2.getAccountNumber(), acc2); System.out.println("*** Balance acount 1: " + acc1.getBalance()); System.out.println("*** Balance acount 2: " + acc2.getBalance()); //Transfer some money System.out.println("*** Transfer 50 from account 1 to account 2"); transfer(acc1, acc2, 50); System.out.println("*** Balance acount 1: " + acc1.getBalance()); System.out.println("*** Balance acount 2: " + acc2.getBalance()); } } As you can see, we create two bank accounts with their account numbers, set the initial balances, and then transfer 50 from account1 to account 2. Running this simple example we get the following expected output: *** Creating account 1 *** Bank Account constructor *** BankAccount.credit() *** Creating account 2 *** Bank Account constructor *** BankAccount.credit() *** Balance acount 1: 150 *** Balance acount 2: 230 *** Transfer 50 from account 1 to account 2 *** BankAccount.debit() *** BankAccount.credit() *** Balance acount 1: 100 *** Balance acount 2: 280 The code for this example can be found in the listing1/ folder of . Logging as a Cross-Cutting Concern One of the main uses of AOP is to extract out cross-cutting concerns. Say we wanted to add some logging whenever an object is created, when its fields are set, and when its methods are called. The “obvious” way to do that in our example would be to go in and add logging statements to various points of our application. The problem with this approach is that there might be lots of places to edit, scattered around our system, so we would need to identify those places, make our changes, and recompile our application. To turn this behaviour off, we would need to remove our logging statements again and recompile our code again. So the “obvious” way both leads to bloat, and is difficult to turn on and off. Using AOP we can encapsulate this cross-cutting code in an aspect. The aspect itself is just a normal class, which can hold state, extend other classes, everything you can do in a normal Java class. package bank; import org.jboss.aop.joinpoint.ConstructorInvocation; import org.jboss.aop.joinpoint.FieldWriteInvocation; import org.jboss.aop.joinpoint.MethodInvocation; public class LoggingAspect { public Object log(ConstructorInvocation invocation) throws Throwable { try { System.out.println("C: Creating BankAccount using constructor " + invocation.getConstructor()); System.out.println("C: Account number: " + invocation.getArguments()[0]); return invocation.invokeNext(); } finally { System.out.println("C: Done"); } } public Object log(MethodInvocation invocation) throws Throwable { try { System.out.println("M: Calling method " + invocation.getMethod().getName()); System.out.println("M: Amount " + invocation.getArguments()[0]); return invocation.invokeNext(); } finally { System.out.println("M: Done"); } } public Object log(FieldWriteInvocation invocation) throws Throwable { BankAccount account = (BankAccount)invocation.getTargetObject(); System.out.println("F: setting field " + invocation.getField().getName() + " for BankAccount " + account.getAccountNumber()); System.out.println("F: Field old value " + account.getBalance()); System.out.println("F: New value will be " + invocation.getValue()); try { return invocation.invokeNext(); } finally { System.out.println("F: Field new value " + account.getBalance()); System.out.println("F: Done"); } } } The actual code implementing the cross-cutting concerns is encapsulated in methods called advice methods. For the type of advice methods that we are looking at now, around advice, the signature and format of the advice method is as shown here: public Object (org.jboss.aop.joinpoint.Invocation invocation) throws Throwable { //Do something before try { return invocation.invokeNext(); } finally { //Do something after } } The invocation parameter can be of type org.jboss.aop.joinpoint.Invocation, or one of its subclasses. Some of these are shown in the LoggingAspect, and which of the overloaded log methods gets called depends on what is being called once we apply our aspect. In the LoggingAspect we are able to handle calls to an object's constructor (the first log() method, starting on line 9), calls to an object's methods (the second log() method, starting on line 23) and calls to set a field (the third log() method, starting on line 37). These “events” are called joinpoints in AOP terminology. The invocation contains information about what field/method/constructor is being called. It also allows access to any arguments, and the object on which we are making the call. The around advice methods also contain a call to Invocation.invokeNext(), which propogates the call chain. If there are several advice methods applied to the target joinpoint, this call invokes the next advice in the chain. If this is the last advice in the chain, or as in our example, we are the only advice in the chain, the target joinpoint is called when we call Invocation.invokeNext(). To apply our aspects, we need some configuration to declare our aspects, and to select the joinpoints in our application where the advice methods should be applied. In JBoss AOP the easiest way to do this is with an xml configuration file, typically called jboss-aop.xml. First we declare our aspect: A binding has a pointcut to choose which methods we should apply the advice to. In this case we have a constructor expression that selects the constructor of the bank.BankAccount class that has an int parameter. Note that all class names used in pointcut expressions must be fully qualified. The word new is a special identifier within the pointcut language to pick out a constructor. Next, the around part of the binding says that we should apply the log advice from the bank.LoggingAspect to the joinpoints matched by its pointcut. In other words, when we call BankAccount's constructor, the first LoggingAspect.log() method, which takes a ConstructorInvocation, is invoked. The previous binding's pointcut only captures one joinpoint. The next one uses a wildcard in place of the method name, so we pick out all methods returning void that take an int parameter, regardless of their name. It looks a lot like the constructor expression in the previous binding, but also contains the return type of the methods we are interested in. This pointcut picks out BankAccount.debit() and BankAccount.credit(), and invokes the second LoggingAspect.log() method, which takes a MethodInvocation, when these methods are called. Finally, we have a binding capturing writes to the balance field of the BankAccount class. In this case we are using a wildcard in place of the type's name, and the third LoggingAspect.log method, which takes a FieldWriteInvocation, will be invoked when the field's value is set: In addition to wildcards, you can also capture whole inheritance hierarchies of classes, use typedefs for complex class expressions, all classes belonging to a package, and as we will see use annotations to capture a wide range of jonpoints. To run this application with aop enabled, you need to pass in a few extra parameters into the jvm when starting it up, as we can see in the example's build.xml The jboss.aop.path parameter contains the path to the jboss-aop.xml that declares our aspects and binds advice methods to joinpoints. The -javaagent switch points to the JBoss AOP library, which in turn turns on load-time weaving. When a class is first loaded, JBoss AOP will intercept that event and modify the bytecode of the class to add the hooks required to trigger the aspects for our selected joinpoints. In addition to weaving at load-time, you can weave the classes using our aopc post-processor. An example of this is shown in the example's build.xml. Running the example with load-time weaving yields the following output, now with quite a lot of extra information coming from our logging aspect: *** Creating account 1 C: Creating BankAccount using constructor public bank.BankAccount(int) C: Account number: 1 *** Bank Account constructor C: Done M: Calling method credit M: Amount 150 *** BankAccount.credit() F: setting field balance for BankAccount 1 F: Field old value 0 F: New value will be 150 F: Field new value 150 F: Done M: Done *** Creating account 2 C: Creating BankAccount using constructor public bank.BankAccount(int) C: Account number: 2 *** Bank Account constructor C: Done M: Calling method credit M: Amount 230 *** BankAccount.credit() F: setting field balance for BankAccount 2 F: Field old value 0 F: New value will be 230 F: Field new value 230 F: Done M: Done *** Balance acount 1: 150 *** Balance acount 2: 230 *** Transfer 50 from account 1 to account 2 M: Calling method debit M: Amount 50 *** BankAccount.debit() F: setting field balance for BankAccount 1 F: Field old value 150 F: New value will be 100 F: Field new value 100 F: Done M: Done M: Calling method credit M: Amount 50 *** BankAccount.credit() F: setting field balance for BankAccount 2 F: Field old value 230 F: New value will be 280 F: Field new value 280 F: Done M: Done *** Balance acount 1: 100 *** Balance acount 2: 280 The code for this example can be found in the listing2/ folder of . Externalising Security Checks Logging is the common example used for introductions to AOP, so let's try doing something more interesting. Say we want to make sure that only users with the correct permissions can call a method. We could annotate our methods from BankAccount as follows: package bank; public class BankAccount { int accountNumber; int balance; @Roles(roles= {"admin"}) public BankAccount(int accountNumber) { System.out.println("*** Bank Account constructor"); this.accountNumber = accountNumber; } ... @Roles(roles= {"admin"}) public void debit(int amount) { System.out.println("*** BankAccount.debit()"); balance -= amount; } @Roles(roles= {"admin", "user"}) public void credit(int amount) { System.out.println("*** BankAccount.credit()"); balance += amount; } } So only users with the role “admin” can create BankAccount instances and debit accounts, while users with the role “admin” or “user” can credit accounts. We have created a security.properties file to configure users and their roles: admin=password;admin,user guest=password;user There is a user called 'admin' whose password is 'password' who has the roles 'admin' and 'user', and a user called 'guest' whose password is 'password' who only has the role 'user'. We can then apply a SecurityAspect to the methods annotated with the @Roles annotation. Note that like everything else in the pointcut language the annotations need to be fully qualified. The “..” in place of the parameters in the pointcut expressions means we want this aspect to be applied to all constructors and methods annotated with @Roles regardless of the parameters it takes. The SecurityAspect then checks that the correct user is used: package bank; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.util.Arrays; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import org.jboss.aop.joinpoint.Invocation; public class SecurityAspect { Map usernamePassword = new HashMap(); Map> userRoles = new HashMap>(); public SecurityAspect() throws FileNotFoundException, IOException, URISyntaxException { //Initialise the usernamePassword and userRoles maps //with information from security.properties } public Object checkSecurity(Invocation invocation) throws Throwable { String username = LoginInfo.getUsername(); String password = usernamePassword.get(username); if (password == null) { throw new SecurityException("Unknown user"); } if (!password.equals(LoginInfo.getPassword())) { throw new SecurityException("Wrong password"); } Roles rolesAnnotaton = (Roles)invocation.resolveAnnotation(Roles.class); List hasRoles = userRoles.get(username); boolean hasRole = false; if (hasRoles != null) { for (String role : rolesAnnotaton.roles()) { if (hasRoles.contains(role)) { hasRole = true; break; } } } if (!hasRole) { throw new SecurityException("Wrong roles for user"); } return invocation.invokeNext(); } } The roles needed to invoke the target joinpoint are got from the invocation using this call: Roles rolesAnnotaton = (Roles)invocation.resolveAnnotation(Roles.class); This does the same as calling java.lang.reflect.Method.getAnnotation() or java.lang.reflect.Constructor.getAnnotation() for the called method or constructor, but also allows for annotation overrides as part of the aop configuration, which are beyond the scope of this article. Although the type of invocation used in this example is Invocation, the specific type created by JBoss AOP will be ConstructorInvocation or MethodInvocation depending on what we are calling. The referenced LoginInfo class is just a wrapper around some static fields containing the username and password. package bank; public class LoginInfo { private static String username; private static String password; public static void setUsernameAndPassword(String username, String password) { LoginInfo.username = username; LoginInfo.password = password; } public static String getUsername() { return username; } public static String getPassword() { return password; } } Now let us modify the Bank.main() method to populate the LoginInfo fields: public static void main(String[] args) { System.out.println("*** Log in as 'guest' - it does not have the correct roles to create an account"); LoginInfo.setUsernameAndPassword("guest", "password"); System.out.println("*** Attempting to create account 1"); try { BankAccount acc1 = new BankAccount(1); acc1.credit(150); bankAccounts.put(acc1.getAccountNumber(), acc1); } catch(SecurityException e) { System.out.println("!!! Expected SecurityException " + e.getMessage()); } System.out.println("*** Log in as 'admin' - the roles are fine for the rest now"); LoginInfo.setUsernameAndPassword("admin", "password"); System.out.println("*** Creating account 1"); BankAccount acc1 = new BankAccount(1); acc1.credit(150); bankAccounts.put(acc1.getAccountNumber(), acc1); System.out.println("*** Creating account 2"); BankAccount acc2 = new BankAccount(2); acc2.credit(230); bankAccounts.put(acc2.getAccountNumber(), acc2); System.out.println("*** Balance acount 1: " + acc1.getBalance()); System.out.println("*** Balance acount 2: " + acc2.getBalance()); //Transfer some money System.out.println("*** Transfer 50 from account 1 to account 2"); transfer(acc1, acc2, 50); System.out.println("*** Balance acount 1: " + acc1.getBalance()); System.out.println("*** Balance acount 2: " + acc2.getBalance()); } We first try to create a BankAccount with a user who does not have the required admin role, and then we do the rest, as before, with an user with the required roles. The output of running this application is: *** Log in as 'guest' - it does not have the correct roles to create an account *** Attempting to create account 1 !!! Expected SecurityException Wrong roles for user *** Log in as 'admin' - the roles are fine for the rest now *** Creating account 1 *** Bank Account constructor *** BankAccount.credit() *** Creating account 2 *** Bank Account constructor *** BankAccount.credit() *** Balance acount 1: 150 *** Balance acount 2: 230 *** Transfer 50 from account 1 to account 2 *** BankAccount.debit() *** BankAccount.credit() *** Balance acount 1: 100 *** Balance acount 2: 280 By using AOP to apply security, we have extracted the security checks into one place in our application, and used annotations to configure that. If we wanted to use a different mechanism of configuring the users we could leave the core application the same, write another aspect and easily change how we use security everywhere by modifying the jboss-aop.xml file. The code for this example can be found in the listing3/ folder of . Observer with Introductions and Mixins Say we want to be able to be notified somehow when BankAccount.balance is changed. An option would be to implement the Observer pattern, but we don't want to include all the Observable plumbing code in our BankAccount class. First of all let's add an annotation to the field we want to monitor. package bank; public class BankAccount { int accountNumber; @Observed int balance; ... } Next we can write an implementation of Observable: package bank; import java.util.ArrayList; import java.util.List; public class ObservableMixin implements Observable { List observers = new ArrayList(); public void addObserver(Observer listener) { observers.add(listener); } public void removeObserver(Observer listener) { observers.remove(listener); } public void notifyObservers(Object event) { for (Observer observer : observers) { observer.update(event); } } } This is a mixin class, which implements the Observable interface. It contains all the plumbing code needed for the Observable part of the pattern. It can be introduced into other POJOs using the following xml bank.Observable bank.ObservableMixin ... This does two things. It makes all classes that have a field annotated with @Observed implement the @Observable interface and implement those methods. Second, when anybody attempts to call the methods from the Observable interface, it delegates all the calls to an instance of the ObservableMixin. Next we have an aspect to trap when the annotated fields change their values bound using the following xml. ... The aspect is an around advice that captures the values before and after modifying the field. package bank; import java.lang.reflect.Field; import org.jboss.aop.joinpoint.FieldWriteInvocation; public class ObserverAspect { public Object fieldChanged(FieldWriteInvocation invocation) throws Throwable { Observable tgt = (Observable)invocation.getTargetObject(); Field fld = invocation.getField(); String fieldName = fld.getName(); fld.setAccessible(true); Object oldVal = invocation.getField().get(tgt); Object result = invocation.invokeNext(); Object newVal = invocation.getField().get(tgt); tgt.notifyObservers("Changed " + fieldName + " from " + oldVal + " to " + newVal); return result; } } Since the classes captured by the pointcut to select which classes should have the ObserverAspect applied are in the set of classes captured by the class expression to pick out classes that should have the Observable introduction and mixin, we can safely cast the target of the invocation to Observable. We then get the values before and after writing the field, and then use the Observable target object to notify the observers. As mentioned the call to Observable.notifyObservers() will end up inside BankAccount's ObservableMixin. Finally, let us modify the Bank.main() method to register an Observer with a BankAccount instance public static void main(String[] args) { System.out.println("*** Creating account 1"); BankAccount acc1 = new BankAccount(1); acc1.credit(150); bankAccounts.put(acc1.getAccountNumber(), acc1); System.out.println("*** Creating account 2"); BankAccount acc2 = new BankAccount(2); acc2.credit(230); bankAccounts.put(acc2.getAccountNumber(), acc2); System.out.println("Installing observer"); ((Observable)acc2).addObserver(new Observer(){ public void update(Object evt) { System.out.println("!!! Observer: " + evt); } }); System.out.println("*** Balance acount 1: " + acc1.getBalance()); System.out.println("*** Balance acount 2: " + acc2.getBalance()); //Transfer some money System.out.println("*** Transfer 50 from account 1 to account 2"); transfer(acc1, acc2, 50); System.out.println("*** Balance acount 1: " + acc1.getBalance()); System.out.println("*** Balance acount 2: " + acc2.getBalance()); } Although until woven the BankAccount class does not implement the Observable interface, the Java compiler does not perform any checks when casting to an interface (only to a superclass), so the cast from BankAccount to Observable will compile. (If the example is run without weaving you would get a ClassCastException since then BankAccount would not implement the Observable interface). When we run this example we can see the registered Observer gets triggered: *** Creating account 1 *** Bank Account constructor *** BankAccount.credit() *** Creating account 2 *** Bank Account constructor *** BankAccount.credit() Installing observer *** Balance acount 1: 150 *** Balance acount 2: 230 *** Transfer 50 from account 1 to account 2 *** BankAccount.debit() *** BankAccount.credit() !!! Observer: Changed balance from 230 to 280 *** Balance acount 1: 100 *** Balance acount 2: 280 The code for this example can be found in the listing5/ folder of . Conclusion We have taken a simple application, added extra behaviour to it using JBoss AOP, and explored a few of the features offered. Apart from adding a few annotations to help with our pointcut expressions (and there are even less intrusive, although more incovenient ways to achieve the similar effect), we have left the core application as is, and added extra cross-cutting behaviour such as logging and security by applying aspects, as well as using a combination of aspects, interface introductions and mixins to implement the Observer pattern. JBoss AOP can be downloaded from http://www.jboss.org/jbossaop/ and comes with a tutorial to get you started.
August 28, 2008
by Kabir Khan
· 85,057 Views · 2 Likes
article thumbnail
Using a Hibernate Interceptor To Set Audit Trail Properties
In almost every application I've done, the database tables have some kind of audit trail fields. Sometimes this is a separate "audit log" table where all inserts, updates, deletes, and possibly even queries are logged. Other times there are the four typical audit trail fields in each table, for example you might have created_by, created_on, updated_by, and updated_on fields in each table. The goal in the latter case is to update those four fields with the appropriate information as to who created or updated a record and when they did it. Using a simple Hibernate Interceptor this can be accomplished with no changes to your application code (with several assumptions which I'll detail next). In other words, you won't need to and definitely should not be manually setting those audit properties littered around your application code. The basic assumptions I'll make for this simple audit interceptor are that: (1) model objects contain the four audit properties mentioned above, and (2) there is an easy way to obtain the current user's information from anywhere in the code. The first assumption is needed since you need some way to identify which properties constitute the audit trail properties. The second assumption is required because you need some way to obtain the credentials of the person making the change in order to set the createdBy or updatedBy property in your Hibernate Interceptor class. So, for reference purposes, assume you have a (Groovy) base entity like this with the four audit properties: @MappedSuperclassclass BaseEntity implements Serializable { String createdBy Date createdOn String updatedBy Date updatedOn} I'm using the Hibernate ImprovedNamingStrategy so that camel case names are translated to underscored names, e.g. "createdBy" becomes "created_by". Next assume there is a BlogEntry entity class that extends BaseEntity and inherits the audit trail properties: @Entityclass BlogEntry extends BaseEntity { @Id @GeneratedValue (strategy = GenerationType.IDENTITY) Long id @Version Long version String title @Column (name = "entry_text") String text @Temporal (TemporalType.TIMESTAMP) Date publishedOn} To implement the interceptor, we need to implement the aforementioned Interceptor interface. We could do this directly, but it is better to extend EmptyInterceptor so we need only implement the methods we actually care about. Without further ado, here's the implementation (excluding package declaration and imports): class AuditTrailInterceptor extends EmptyInterceptor { boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) { setValue(currentState, propertyNames, "updatedBy", UserUtils.getCurrentUsername()) setValue(currentState, propertyNames, "updatedOn", new Date()) true } boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { setValue(state, propertyNames, "createdBy", UserUtils.getCurrentUsername()) setValue(state, propertyNames, "createdOn", new Date()) true } private void setValue(Object[] currentState, String[] propertyNames, String propertyToSet, Object value) { def index = propertyNames.toList().indexOf(propertyToSet) if (index >= 0) { currentState[index] = value } } So what did we do? First, we implemented the onFlushDirty and onSave methods because they are called for SQL updates and inserts, respectively. For example, when a new entity is first saved, the onSave method is called, at which point we want to set the createdBy and properties. And if an existing entity is updated, onFlushDirty is called and we set the updatedBy and updatedOn. Second, we are using the setValue helper method to do the real work. Specfically, the only way to modify the state in a Hibernate Interceptor (that I am aware of anyway) is to dig into the currentState array and change the appropriate value. In order to do that, you first need to trawl through the propertyNames array to find the index of the property you are trying to set. For example, if you are updating a blog entry you need to set the updatedBy and updatedOn properties within the currentState array. For a BlogEntry object, the currentState array might look like this before the update (the updated by and on propertes are both null in this case because the entity was created by Bob but has not been updated yet): { "Bob", 2008-08-27 10:57:19.0, null, null, 2008-08-27 10:57:19.0, "Lorem ipsum...", "My First Blog Entry", 0} You then need to look at the propertyNames array to provide context for what the above data represents: { "createdBy", "createdOn", "updatedBy", "updatedOn", "publishedOn", "text", "title", "version"} So in the above updatedBy is at index 2 and updatedOn is located at index 3. setValue() works by finding the index of the property it needs to set, e.g. "updatedBy," and if the property was found, it changes the value at that index in the currentState array. So for updatedBy at index 2, the following is the equivalent code if we had actually hardcoded the implementation to always expect the audit fields as the first four properties (which is obviously not a great idea): // Equivalent hard-coded code to change "updatedBy" in above example// Don't use in production!currentState[2] = UserUtils.getCurrentUsername() To actually make your interceptor do something, you need to enable it on the Hibernate Session. You can do this in one of several ways. If you are using plain Hibernate (i.e. not with Spring or another framework) you can set the interceptor globally on the SessionFactory, or you can enable it for each Session as in the following example code: // Configure interceptor globally (applies to all Sessions)sessionFactory = new AnnotationConfiguration() .configure() .setNamingStrategy(ImprovedNamingStrategy.INSTANCE) .setInterceptor(new AuditTrailInterceptor()) .buildSessionFactory()// Enable per SessionSession session = getSessionFactory().openSession(new AuditTrailInterceptor()) If you enable the interceptor globally, it must be thread-safe. If you are using Spring you can easily configure a global interceptor on your session factory bean: On the other hand, if you would rather enable the interceptor per session, you either need to use the openSession(Interceptor) method to open your sessions or alternatively implement your own version of CurrentSessionContext to use the getCurrentSession() method in order to set the interceptor. Using getCurrentSession() is preferable anyway since it allows several different classes (e.g. DAOs) to use the same session without needing to explicitly pass the Session object around to each object that needs it. At this point we're done. But, if you know about the Hibernate eventing system (e.g. you can listen for events such as inserts and updates and define event listener classes to respond to those events), you might be wondering why I didn't use that mechanism rather than the Interceptor. The reason is that, to the best of my current knowledge, you cannot alter state of objects in event listeners. So for example you would not be able to change an entity's state in a PreInsertEventListener implementation class. If anyone knows this is incorrect or has implemented it, I'd love to hear about it. Until next time, happy auditing! Originally posted on Scott Leberknight's blog
August 27, 2008
by Scott Leberknight
· 103,486 Views · 2 Likes
article thumbnail
Execute Shell Command From Java
String cmd = "ls -al"; Runtime run = Runtime.getRuntime(); Process pr = run.exec(cmd); pr.waitFor(); BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream())); String line = ""; while ((line=buf.readLine())!=null) { System.out.println(line); }
August 14, 2008
by Snippets Manager
· 105,985 Views · 2 Likes
article thumbnail
Creating SOAP Message Handlers in 3 Simple Steps - Part 1
This tutorial takes a look at SOAP Message handlers and how easy it is to write handlers using JAX-WS 2.0. JAX-WS 2.0 allows both regular Java classes and stateless EJBs(Session beans) to be exposed as web services. The JAX-WS 2.0 is the core specification that defines the web services standard for Java EE 5 specification. JAX-WS 2.0 is an extension of the Java API for XML-RPC (JAX-RPC) 1.0. SOAP message handlers are used to intercept the SOAP message as they make their way from the client to the end-point service and vice-versa. These handlers intercept the SOAP message for both the request and response of the Web Service. If you are familiar with EJB interceptors, handlers are similar to EJB interceptors and are defined in an XML file. A few typical scenarios where you would be using SOAP Message handlers are: to encrypt and decrypt messages, to support logging, caching and in some cases auditing, and in rare cases to provide transaction management as well. So much for the theory. Lets see the three basic steps to use a simple log handler to intercept and print our SOAP messages (request and response). In this tutorial, we are going to expose an EJB 3 stateless session bean as a web service which is simple and can be done by adding the @WebService annotation. So, here comes the source code for the interface as well as the implementation class which is self explanatory: Listing 1: Remote Interface package com.ws;import javax.ejb.Remote;/** * * @author meerasubbarao */@Remotepublic interface HelloWebServiceRemote { String sayHello(String name); } Listing 2: Bean Implementation package com.ws;import javax.ejb.Stateless;import javax.jws.WebMethod;import javax.jws.WebParam;import javax.jws.WebService;/** * * @author meerasubbarao */@WebService@Statelesspublic class HelloWebServiceBean implements HelloWebServiceRemote { @WebMethod(operationName = "sayHello") public String sayHello(@WebParam(name = "name") String name) { return "Hello " + name; } } You can package the two source files in a jar, deploy to your application server, and test it. Quite simple, right? For this tutorial, I am using GlassFish V2 application server and SoapUI to test my web services. Shown below are the request and response from SoapUI: Now that we know our web services work, lets start writing the message handler, which as I said earlier is just 3 steps. So, what are these SOAP message handlers? They are simple Java classes that can used to modify SOAP messages; both request as well as response. These handlers have access to both the SOAP header as well as the body of the message. Lets move on to create SOAP message handlers: Step 1. Implement the SOAPHandler interface. package com.ws;import java.io.IOException;import java.util.Collections;import java.util.Set;import java.util.logging.Level;import java.util.logging.Logger;import javax.xml.namespace.QName;import javax.xml.soap.SOAPException;import javax.xml.soap.SOAPMessage;import javax.xml.ws.handler.MessageContext;import javax.xml.ws.handler.soap.SOAPHandler;import javax.xml.ws.handler.soap.SOAPMessageContext;/** * * @author meerasubbarao */public class LogMessageHandler implements SOAPHandler { public boolean handleMessage(SOAPMessageContext messageContext) { return true; } public Set getHeaders() { return Collections.EMPTY_SET; } public boolean handleFault(SOAPMessageContext messageContext) { return true; } public void close(MessageContext context) { } The handleMessage() method is invoked for both incoming as well as outgoing messages. Lets add a new method called log() and invoke this method from the handleMessage method. Shown below are both the methods: private void log(SOAPMessageContext messageContext) { SOAPMessage msg = messageContext.getMessage(); //Line 1 try { msg.writeTo(System.out); //Line 3 } catch (SOAPException ex) { Logger.getLogger(LogMessageHandler.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(LogMessageHandler.class.getName()).log(Level.SEVERE, null, ex); } } In line 1, we are retrieving the SOAPMessage from the message context. Line 3 will print the incoming and outgoing messages in our GlassFish console. Invoke this method from within the handleMessage() as shown: public boolean handleMessage(SOAPMessageContext messageContext) { log(messageContext); return true; } Step 2: Create the XML file for the Handler Chain. Create this XML file in the same package as the web service with the name LogMessage_handler.xml. com.ws.LogMessageHandler com.ws.LogMessageHandler Lets take a close look at the various elements used above: 1. is the root element that will contain a list of all handler chains that are defined for the Web Service. 2. The child element of the element lists all the handlers in the handler chain. 3. Within the element is defined the , each handler element must in turn specify the name and also the fully qualified name of the Java class that implements the handler. If you have more than one handler, specify each one of them within the handler-chain element. Step 3: Invoking the Handler The @HandlerChain annotation is used to define a set of handlers that are invoked in response to a SOAP message. So, within our HelloWebServiceBean implementaion, you need to make a simple change to invoke the Log Handler as shown below in Line 1: package com.ws;import javax.ejb.Stateless;import javax.jws.HandlerChain;import javax.jws.WebMethod;import javax.jws.WebParam;import javax.jws.WebService;/** * * @author meerasubbarao */@WebService@Stateless@HandlerChain(file = "LogMessage_handler.xml") // Line 1public class HelloWebServiceBean implements HelloWebServiceRemote { @WebMethod(operationName = "sayHello") public String sayHello(@WebParam(name = "name") String name) { return "Hello " + name; } } We added the annotation for the handlers; lets recompile, repackage and redeploy the application. Now invoke the web service from SoapUI and see if it works. If it does, we should be able to see the request and response logged in our GlassFish console window. Here is the final output: **RemoteBusinessJndiName: com.ws.CustomerManagerRemote; remoteBusIntf: com.ws.CustomerManagerRemote LDR5010: All ejb(s) of [EJBWebServices] loaded successfully! Javalobby Hello Javalobby In this article, we saw how simple and easy it was to create and use SOAP Handlers to intercept request and response of SOAP messages. We implemented the SOAPHandler interface, wrote minimal XML to define the handler chain, and finally added one simple annotation to the web service implementation class. We were also able to test these web service using SoapUI. In Part 2 of this series, we will see how to actually parse the SOAP Headers, and also use multiple handlers. Stay tuned for more..
August 13, 2008
by Meera Subbarao
· 86,037 Views
article thumbnail
OFX4J: Java Web Service APIs for Interfacing with Financial Institutions
OFX4J has been released! OFX4J is a Java implementation of Open Financial Exchange, which defines web service APIs for interfacing with financial institutions. The OFX4J library includes support for both client-side and server-side implementations of both version 1 and version 2 of the OFX specification. As an example, let's consider the OFX4J client-side interface, which can be used, for example, to download your financial transactions from your bank or credit card institution. OFX4J comes with an initial set of financial institution data, but you can load your own if your financial institution isn't included. Consider the following code for downloading your bank statement: //the financial institution data is loaded or created //the FinancialInstitutionData interface defines //what is required to interface with a financial institution. FinancialInstitutionData data = ...; FinancialInstitutionService service = new FinancialInstitutionServiceImpl(); FinancialInstitution fi = service.getFinancialInstitution(data); //get a reference to a specific bank account at the FI BankAccountDetails bankAccountDetails = new BankAccountDetails(); //routing number to the bank. bankAccountDetails.setRoutingNumber("11111111"); //bank account number. bankAccountDetails.setAccountNumber("1234-5678"); //it's a checking account bankAccountDetails.setAccountType(AccountType.CHECKING); BankAccount bankAccount = fi.loadBankAccount(bankAccountDetails, "username", "password"); //read the statement (transaction details, etc.) // for a given time period. Date startDate = ...; Date endDate = ...; AccountStatement statement = bankAccount.readStatement(startDate, endDate); // get a reference to a specific credit card // account at your FI CreditCardAccountDetails ccDetails = new CreditCardAccountDetails(); ccDetails.setAccountNumber("1234-567890-1111"); CreditCardAccount ccAccount = fi.loadCreditCardAccount(ccDetails, "username", "password"); // read the statement (transaction details, etc.) // for a given time period. Date startDate = ...; Date endDate = ...; AccountStatement statement = ccAccount.readStatement(startDate, endDate); Server-side development is just straightforward, consisting of implementing a simple interface and publishing it with a simple Servlet implementation: /** * Basic interface for an OFX server. * * @author Ryan Heaton */ public interface OFXServer { /** * Get a response for the given request. * * @param request The request. * @return The response. */ ResponseEnvelope getResponse(RequestEnvelope request); }
July 22, 2008
by Ryan Heaton
· 3,882 Views
article thumbnail
Introducing Caching for Java Applications (Part 1)
Caching may address new challenges when developing performing applications.
July 17, 2008
by Slava Imeshev
· 141,212 Views · 7 Likes
  • Previous
  • ...
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 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
×