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
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Latest Articles - DZone

article thumbnail
Spring Integration Gateways - Null Handling & Timeouts
Spring Integration (SI) Gateways Spring Integration Gateways () provide a semantically rich interface to message sub-systems. Gateways are specified using namespace constructs, these reference a specific Java interface () that is backed by an object dynamically implemented at run-time by the Spring Integration framework. Furthermore, these Java interfaces can, if you so wish, be defined entirely independent of any Spring artefacts - that's both code and configuration. One of the primary advantages of using the SI gateway as an interface to message sub-systems is that it's possible to automatically adopt the benefit of rich, default and customisable, gateway configuration. One such configuration attribute deserves further scrutiny and discussion primarily because it's easy to misunderstand and misconfigure around - default-reply-timeout. Primary Motivator for Gateway Analysis During recent consulting engagements, I've encountered a number of deployments that use Spring Integration Gateway specifications that may, in some circumstances, lead to production operational instability. This has often been in high-pressure environments or those where technology support is not backed by adequate training, testing, review or technology mentoring. How do gateways behave in Spring Integration (R2.0.5) One of the key sections, regarding gateways, in the Spring Integration manual clearly explains gateway semantics. Below is a 2-dimensional table of possible non-standard gateway returns for each of the scenarios that the SI Manual (r2.0.5) refers to. Gateway Non-standard Responses Runtime Events default-reply-timeout=x Single-threaded default-reply-timeout=x Multi-threaded default-reply-timeout=null Single-threaded default-reply-timeout=null Multi-threaded 1. Long Running Process Thread Parked null returned Thread Parked Thread Parked 2. Null Returned Downstream null returned null returned Thread Parked Thread Parked 3. void method Downstream null returned null returned Thread Parked Thread Parked 4. Runtime Exception Error handler invoked or exception thrown. Error handler invoked or exception thrown. Error handler invoked or exception thrown. Error handler invoked or exception thrown. The key parts of this table are the conditions that lead to invoking threads being parked (noted in red), nulls returned (noted in orange) and exceptions (noted in green). Each contributor consists of configuration that is under the developers control, deployed code that is under developers control and conditions that are usually not under developers control. Clearly, the column headings in the table above are divided into two sections; two gateway configuration attributes. The default-reply-timeout is set by the SI configured and is the amount of time that a client call is wiling to wait for a response from the gateway. Secondly, synchronous flows are represented by Single-threaded flows, asynchronous by Multi-threaded flows. A synchronous, or single-threaded flow, is one such as the following: The implicit input channel (gateway-request-channel) has no associated dispatcher configured. An asynchronous, or multi-threaded flow, is one such as the following: The explicit input channel has a dispatcher configured ("taskExecutor"). This task executor specifies a thread pool that supplies threads for execution and whose configuration as above marks a thread boundary. Note: This is not the only way of making channels asynchronous The other configuration attribute referenced is default-reply-timeout, this is set on the gateway namespace configuration such as the example above. Note that both of these runtime aspects are set by the configurer during SI flow design and implementation. They are entirely under developer control. The 'Runtime Events' column indicates gateway relevant runtime events that have to be considered during gateway configuration - these are obviously not under developer control. Trigger conditions for these events are not as unusual as one may hope. 1. Long Running Processes It's not uncommon for thread pools to become exhausted because all pooled threads are waiting for an external resource accessed through a socket, this may be a long running database query, a firewall keeping a connection open despite the server terminating etc. There is significant potential for these types of trigger. Some long-running processes terminate naturally, sometimes they never completed - an application restart is required. 2. Null returned downstream A null may be returned from a downstream SI construct such as a Transformer, Service Activator or Gateway. A Gateway may return null in some circumstances such as following a gateway timeout event. 3. Void method downstream Any custom code invoked during an SI flow may use a void method signature. This can also be caused by configuration in circumstances where flows are determined dynamically at runtime. 4. Runtime Exception RuntimeException's can be triggered during normal operation and are generally handled by catching them at the gateway or allowing them to propagate through. The reason that they are coloured green in the table above is that they are generally much easier to handle than timeouts. Gateway Timeout Handling Strategies There are four possible outcomes from invoking a gateway with a request message, all of these as a result of specific runtime events: a) an ordinary message response, b) an exception message, c) a null or d) no-response. Ordinary business responses and exceptions are straight forward to understand and will not be covered further in this article. The two significant outcomes that will be explored further are strategies for dealing with nulls and no-response. Generally speaking, long running processes either terminate or not. Long running processes that terminate may eventually return a message through the invoked gateway or timeout depending on timeout configuration, in which case a null may be returned. The severity of this as a problem depends on throughput volume, length of long running process and system resources (thread-pool size). Configuration exists for default-reply-timeout In the case where a long running process event is underway and a default-reply-timeout has been set, as long as the long running process completes before the default-reply-timeout expires, there is no problem to deal with. However, if the long running process does not complete before that timeout expires one of three outcomes will apply. Firstly, if the long running process terminates subsequent to the reply timeout expiry, the gateway will have already returned null to the invoker so the null response needs handling by the invoker. The thread handling the long-running process will be returned to the pool. Secondly, if the long running process does not terminate and a reply timeout has been set, the gateway will return null to the gateway invoker but the thread executing the long-running process will not get returned to the pool. Thirdly, and most significantly, if a default-reply-timeout has been configured but the long running process is running on the same thread as the invoker, i.e. synchronous channels supply messages to that process, the thread will not return, the default-reply-timeout has no affect. Assuming the most common processing scenario, a long running process completes either before or after the reply timeout expiry. When a null is returned by the gateway, the invoker is forced to deal with a null response. It's often unacceptable to force gateway consumers to deal with null responses and is not necessary as with a little additional configuration, this can be avoided. Absent Configuration for default-reply-timeout The most significant danger exists around gateways that have no default-reply-timeout configuration set. A long running process or a null returned from downstream will mean that the invoking thread is parked. This is true for both synchronous and asynchronous flows and may ultimately force an application to be restarted because the invoker thread pool is likely to start on a depletion course if this continues to occur. Spring Integration Timeout Handling Design Strategies For those Spring Integration configuration designers that are comfortable with gateway invokers dealing with null responses, exceptions and set default-reply-timeouts on gateways, there's no need to read further. However, if you wish to provide clients of your gateway a more predictable response, a couple of strategies exist for handling null responses from gateways in order that invokers are protected from having to deal with them. Firstly, the simpliest solution is to wrap the gateway with a service activator. The gateway must have the default-reply-timeout attribute value set in order to avoid unnecessary parking of threads. In order to avoid the consequence of long-running threads it's also very prudent to use a dispatcher soon after entry to the gateway - this breaks the thread boundary. Whilst this is a valid technical approach, the impact is that we have forced a different entry point to our message sub-system. Entry is now via a Service Activator rather than a Gateway. A side affect of this change is that the testing entry point changes. Integration tests that would normally reference a gateway to send a message now have to locate the backing implementation for the Service Activator, not ideal. An alternative approach toward solving this problem would be to configure two gateways with a Service Activator between them. Only one of the gateways would be exposed to invokers, the outer one. Both Gateways would reference the same service interface. The outer gateway specification would not specify the default-reply-timeout but would specify the input and output channels in the same way that a single gateway would. The Service Activator between the Gateways would handle null gateway responses and possibly any exceptions if preferred to the gateway error handler approach. An example is as follows: The Service Activator bean (enrollmentServiceGatewayHandler) deals with both null and exception responses from the adapted gateway (enrollmentServiceAdaptedGateway), in the situation where these are generated a business response detailing the error is generated. Spring Integration R2.1 Changes async-executor on gateway spec
May 26, 2012
by Matt Vickery
· 24,559 Views · 1 Like
article thumbnail
Connection Pooling in a Java Web Application with Tomcat and NetBeans IDE
After my article Connection Pooling in a Java Web Application with Glassfish and NetBeans IDE, here are the instructions for Tomcat. Requirements NetBeans IDE (this tutorial uses NetBeans 7) Tomcat (this tutorial uses Tomcat 7 that is bundled within NetBeans) MySQL database MySQL Java Driver Steps Assuming your MySQL database is ready, connect to it and create a database. Lets call it connpool: mysql> create database connpool; Now we create and populate the table from which we will fetch the data: mysql> use connpool; mysql> create table data(id int(5) not null unique auto_increment, name varchar(255) not null); mysql> insert into data(name) values("Fred Flintstone"), ("Pink Panther"), ("Wayne Cramp"), ("Johnny Bravo"), ("Spongebob Squarepants"); That is it for the database part. We now create our web application. In NetBeans IDE, click File → New Project... Select Java Web → Web Application: Click Next and give the project the name TomPool. Click Next Choose the server as Tomcat and, since we are not going to use any frameworks, click Finish. The project will be created and the start page, index.jsp, opened for us in the IDE. Now we create the connection pooling parameters. In the Projects window, expand configuration files and open "context.xml". You will see that the IDE has added this code for us: Delete the last line: and then add the following to the context.xml file. I have explained the sections along the way. Make sure you edit your MySQL username and password appropriately: Next, expand the Web Pages node, right-click WEB-INF → New → Other → XML → XML Document. Click Next and type web for the File Name. Click next and choose Well-Formed Document then Finish. You will now have the file "web.xml": Delete everything in the file and paste this code: MySQL Test App DB Connection connpool javax.sql.DataSource Container That is it for the connection pool. We now edit our code to make use of it. Edit index.jsp by adding this code just after the initial coments but before Edit the section of the page: Data in my Connection Pooled Database Now, we test the connection pool by running the application: If you want to have the one connection pool used in multiple applications, you need to edit the following two files: 1. /conf/web.xml Just before the closing tag, add the code DB Connection connpool javax.sql.DataSource Container 2. /conf/context.xml Just before the closing tag, add the code Now you can use the pool without editing XML files in each of your applications. Just use the sample code as given in index.jsp That's it folks!
May 23, 2012
by Arthur Buliva
· 70,433 Views · 2 Likes
article thumbnail
A Full Overview of the CamelOne 2012 Conference
CamelOne was yet again a really cool and fun conference. I just returned back home, from the 2nd annual CamelOne conference, held in downtown Boston. It was a 2 day packed with great talks with a balanced mix of technical talks, cloud stuff, and showcases of integration in the real world. CamelOne speaker podium The feedback of the conference was really good, as you can see from the image below. Feedback wall from CamelOne attendees The FuseSource engineering team was present, and on the end of the 2nd day, Debbie, got us together for a photo session. The FuseSource Engineering Team CamelOne 2012 - Day 1 So back the the 1st day. This year Jonathan and I was asked to do the opening key note, with our Camel story, and where the Camel project is today, and some thoughts about how Camel could be riding the cloud in the near future. Jonathan and I wanted to tell our Camel story with a sense of humor. I can say mission accomplished when the slide with the lovely Camel picture was shown. And no the picture is not retouched, it was found using google image search. Apache Camel is a project that stands out After the keynote I gave a talk about how to get started riding the Camel. The talk is a practical focus talk so I was sharing the time 50/50 between slides and live coding. As all sessions were recorded, and we can all watch them later, as they will be posted on the CamelOne website, free for anymore to watch. A professional production company is currently processing the videos. They should be ready in weeks from now. I will blog when the videos are online. Free Apache/Fuse Resources Apache Project Leader Videos Open Source Integration Tool Downloads Integrate Anywhere: Fuse ESB Super Fast Messaging with Fuse MQ Free SOA Webcasts Apache ActiveMQ and ServiceMix Lessons Integration Resources Jonathan was next after my talk, and his talk was a natural progress from mine talk. As he gave a rundown how you can run and deploy Camel and CXF applications in the ESB server. Jonathan showed how this works in practice as well. I got engaged in a number of hallway conversations, and didn't have the chance to attend a session at every slot. It was really great to meet so many happy Camel users, and hear their stories, where the Camel is riding in the real world. Also I was told that more and more commercial vendors is adapting Camel and embedding it internally in their commercial products. Kai Wahner gave his first of two talks today. Kai Wahner giving a talk about choosing Integration Frameworks He was talking about his experience with evaluating Apache Camel, Spring Integration, and Mule ESB. I guess Camel was in favor at a Camel conference :) James gave the ending general session of the first day. James Strachan giving ending key note on 1st day As always a pleasure to watch James talk with such a enthusiasm. His talk was a technical talk addressed to the developers how to develop and get Camel riding in the cloud. He gave a tour of the cool and awesome much improved Fuse IDE 2.1 product. It now has even more Camel crack for runtime insight. As well as easier deployment for both local jvms, remove machines, and as well the clouds. CamelOne 2012 - Day 2 On the 2nd day, we have Gabe Zichermann giving a very entertaining keynote, about gamification. Gabe talking about Gamification The idea of getting people engaged, based on the ideas of computer games. But applying them in a real life processes. For example a company managed to get its employees go to the gym, based on teaming up, and competing against your co-workers. In Sweden they have traffic cameras, using reverse sychology, by enlisting people in a lottery, if they are within speed limits. However people above the speed limit will of course still get a fine, and not participate in the lottery. I have heard good buzz about Stan Lewis and Dhirajs talk about how to manage, monitor and provision a cluster of machines, in a data centre or the cloud. Dhiraj showed how Fuse HQ could monitor the Camel applications running on numerous machines. And how that worked as well when Stan did a rolling upgrade on the fly, leaving Fuse HQ being able to compare and display a "before" vs. "after" overview. Likewise the tweets about Charles Moulliard were very positive. Seems like people wanted to go and play with websockets, and the Camel. This is definitly cool. So Camel 2.10 is a much anticipated release, having the websocket component out of the box. Kai was on the stage again, giving a talk about using Apache Camel with BPM (Avtiviti). Kai gave us a rundown of the differences between Camel and Activiti, and where they overlap. As well when you should use either one, or both of them. In Kais talk he give live demos which is a nice change in the flow, to see the "code" for real. Activiti and Camel together seems powerful. And the Activiti designer looks beautiful. Did you know that Camel is help protecting the Canadians. Mike Gingell from General Dynamics Canada gave us a rundown of how they have been successful by using open source integration technologies from Apache. The Camel is helping in cool stuff such as with the marine to detect torpedo attacks, with satellite surveillance of the north poles, and to keep track of personel and whatnot. Torpedo Warning System. Slide from Mike Gingell, General Dynamics Canada, Mike gave a really great talk, and also took us through how his team is battling uphill in a traditionally conservative organization where software projects take millions of $ and years to just get started. They have been on the open source road for about 5 years, and jumped on Apache ServiceMix when it became OSGi based. And the Camel has been riding all along together with ActiveMQ and CXF. So the Camel is help protecting Jonathan Anstey, who lives in New Foundland, Canada. Must be cool to know that the software he works on every day, is now serving the people of Canada. The ending keynote, was a real treat to all of us. Felix Ehmn from CERN gave us a very interesting talk how CERN is using ActiveMQ in their control room, to monitor the most complex machine man have ever built - the Large Hadron Collider; eg the 27km circle where they smash atoms together and see what happens. Felix giving ending keynote, about CERN using ActiveMQ There is 85.000 devices, which they need the monitor. Its everything, from censors on the collider, to fire alarms, door buttons and whatnot. CERN is definitily a cool place. In fact the coolest place on earth as well, as they need to cool down the collider, to 1 degree kelvin. That is - 272 degrees celsius. Like CERN, the CamelOne conference was very cool. I discovered a number of other blogs covering the CamelOne 2012 conference Kai Waehner blogged his CamelOne report. Christian Posta blogged as well And Rob Terpilowski who gave a talk also Hope to see you in 2013 at the next CamelOne conference. As David Reiser tweeted, the conference was awesome. David liked the conference
May 23, 2012
by Claus Ibsen
· 7,108 Views
article thumbnail
The Limited Usefulness of AsyncContext.start()
Some time ago I came across What's the purpose of AsyncContext.start(...) in Servlet 3.0? question. Quoting the Javadoc of aforementioned method: Causes the container to dispatch a thread, possibly from a managed thread pool, to run the specified Runnable. To remind all of you, AsyncContext is a standard way defined in Servlet 3.0 specification to handle HTTP requests asynchronously. Basically HTTP request is no longer tied to an HTTP thread, allowing us to handle it later, possibly using fewer threads. It turned out that the specification provides an API to handle asynchronous threads in a different thread pool out of the box. First we will see how this feature is completely broken and useless in Tomcat and Jetty - and then we will discuss why the usefulness of it is questionable in general. Our test servlet will simply sleep for given amount of time. This is a scalability killer in normal circumstances because even though sleeping servlet is not consuming CPU, but sleeping HTTP thread tied to that particular request consumes memory - and no other incoming request can use that thread. In our test setup I limited the number of HTTP worker threads to 10 which means only 10 concurrent requests are completely blocking the application (it is unresponsive from the outside) even though the application itself is almost completely idle. So clearly sleeping is an enemy of scalability. @WebServlet(urlPatterns = Array("/*")) class SlowServlet extends HttpServlet with Logging { protected override def doGet(req: HttpServletRequest, resp: HttpServletResponse) { logger.info("Request received") val sleepParam = Option(req.getParameter("sleep")) map {_.toLong} TimeUnit.MILLISECONDS.sleep(sleepParam getOrElse 10) logger.info("Request done") } } Benchmarking this code reveals that the average response times are close to sleep parameter as long as the number of concurrent connections is below the number of HTTP threads. Unsurprisingly the response times begin to grow the moment we exceed the HTTP threads count. Eleventh connection has to wait for any other request to finish and release worker thread. When the concurrency level exceeds 100, Tomcat begins to drop connections - too many clients are already queued. So what about the the fancy AsyncContext.start() method (do not confuse with ServletRequest.startAsync())? According to the JavaDoc I can submit any Runnable and the container will use some managed thread pool to handle it. This will help partially as I no longer block HTTP worker threads (but still another thread somewhere in the servlet container is used). Quickly switching to asynchronous servlet: @WebServlet(urlPatterns = Array("/*"), asyncSupported = true) class SlowServlet extends HttpServlet with Logging { protected override def doGet(req: HttpServletRequest, resp: HttpServletResponse) { logger.info("Request received") val asyncContext = req.startAsync() asyncContext.setTimeout(TimeUnit.MINUTES.toMillis(10)) asyncContext.start(new Runnable() { def run() { logger.info("Handling request") val sleepParam = Option(req.getParameter("sleep")) map {_.toLong} TimeUnit.MILLISECONDS.sleep(sleepParam getOrElse 10) logger.info("Request done") asyncContext.complete() } }) } } We are first enabling the asynchronous processing and then simply moving sleep() into a Runnable and hopefully a different thread pool, releasing the HTTP thread pool. Quick stress test reveals slightly unexpected results (here: response times vs. number of concurrent connections): Guess what, the response times are exactly the same as with no asynchronous support at all (!) After closer examination I discovered that when AsyncContext.start() is called Tomcat submits given task back to... HTTP worker thread pool, the same one that is used for all HTTP requests! This basically means that we have released one HTTP thread just to utilize another one milliseconds later (maybe even the same one). There is absolutely no benefit of calling AsyncContext.start() in Tomcat. I have no idea whether this is a bug or a feature. On one hand this is clearly not what the API designers intended. The servlet container was suppose to manage separate, independent thread pool so that HTTP worker thread pool is still usable. I mean, the whole point of asynchronous processing is to escape the HTTP pool. Tomcat pretends to delegate our work to another thread, while it still uses the original worker thread pool. So why I consider this to be a feature? Because Jetty is "broken" in exactly same way... No matter whether this works as designed or is only a poor API implementation, using AsyncContext.start() in Tomcat and Jetty is pointless and only unnecessarily complicates the code. It won't give you anything, the application works exactly the same under high load as if there was no asynchronous logic at all. But what about using this API feature on correct implementations like IBM WAS? It is better, but still the API as is doesn't give us much in terms of scalability. To explain again: the whole point of asynchronous processing is the ability to decouple HTTP request from an underlying thread, preferably by handling several connections using the same thread. AsyncContext.start() will run the provided Runnable in a separate thread pool. Your application is still responsive and can handle ordinary requests while long-running request that you decided to handle asynchronously are processed in a separate thread pool. It is better, unfortunately the thread pool and thread per connection idiom is still a bottle-neck. For the JVM it doesn't matter what type of threads are started - they still occupy memory. So we are no longer blocking HTTP worker threads, but our application is not more scalable in terms of concurrent long-running tasks we can support. In this simple and unrealistic example with sleeping servlet we can actually support thousand of concurrent (waiting) connections using Servlet 3.0 asynchronous support with only one extra thread - and without AsyncContext.start(). Do you know how? Hint: ScheduledExecutorService. Postscriptum: Scala goodness I almost forgot. Even though examples were written in Scala, I haven't used any cool language features yet. Here is one: implicit conversions. Make this available in your scope: implicit def blockToRunnable[T](block: => T) = new Runnable { def run() { block } } And suddenly you can use code block instead of instantiating Runnable manually and explicitly: asyncContext start { logger.info("Handling request") val sleepParam = Option(req.getParameter("sleep")) map { _.toLong} TimeUnit.MILLISECONDS.sleep(sleepParam getOrElse 10) logger.info("Request done") asyncContext.complete() } Sweet!
May 22, 2012
by Tomasz Nurkiewicz
· 17,783 Views · 1 Like
article thumbnail
The surgery metaphor
As you know in the last months I've been intrigued more and more by metaphors for object-oriented systems, since they brilliantly solve the problem of naming by borrowing terminology from an existing field. However, it is also interesting (and indeed has happened many times) to propose metaphors for a software development process. Analogies like building a skyscraper and growing a crop have let us ground some of our hypothesis in "thousand-years old domains"; and often lead us ashtray by false comparisons like the one between programmers and bricklayers. The goal of this article is to describe the surgery metaphor for software development and check where it is useful to explain development concepts to newcomers and non-technical people. Quality There are some shared values between surgery and a certain category of software development, that deeply cares about the quality of the final product. For example, the diatribe of long-term and short-term value is resolved in favor of a the former: a solution must work without requiring larger operations for years (ideally, for decades). The cost of maintenance is taken into account and never discounted when discussing different approaches to the current problem. Attention to the detail is omnipresent in surgery, down to the singles procedure to follow; software development faces risk by automating most of these checks: broken builds cannot be deployed, and business metrics like current active users or satisfied requests must be monitored to ensure availability of the service. TDD and refactoring Following Uncle Bob's metaphor, common Agile practices like TDD are akin to aseptic techniques in surgery. These procedures started out simply by hand washing, and has evolved into gloves, masks and sterilization. Thus practices are not strictly necessary conditions for success: emergency scenarios require to operate without it, like in the case of first aid. However, standardized procedures are facilitating conditions: not as strong as necessary, but able to improve the odds of a good outcome enough to show a good return on investment. Post-surgery infections were as common and lethal in medieval times as finding bugs in production is nowadays. However, practices are never a sufficient condition: you don't bring a postman into a surgery room, make him wash hands and tell him to operate (while many people tell him to code without even the hand washing part.). There is a whole set of training that he has to undergo before being able to make a positive contribution. Training The training of surgeons is one of the hardest in the world. Depending on the country, there are strong qualifications to obtain and associations of certified professionals that a surgeon must belong to in order to operate the profession. In cases of misconduct, a surgeon can be stopped or expelled from the order. Try imagining a programmer getting expelled for doing a sloppy job. However, given how certifications work in the field at this time, we still have much work to do before they become a reliable signal for employees. A big part of the medical training happens on the field (in hospitals and periodically in operating rooms), although the apprentice is usually never left in charge. Moreover, the training is never declared complete, and there is a costant update on the latest tools and techniques on the part of doctors. Their publication ofscientific papers and journals can be compared to our blogs and articles reporting the best (or good) practices of a field, although the selection system is based on peer review in the former case and on popularity in the latter. The issues A first way in which the metaphor fails is in the different definition of value: while maintaining software and adding new features to it is often necessary, the best surgical operation is still the one that is not performed. In this sense, the value of getting the application to work again would be preferred to the one of further product development. Another issue that we would face is the inflating cost and time needed for training of doctors, alghouth the long training may actually be necessary for such a delicate domain. After all, the surgeon's salary justifies the investment costs to become one. High compensation systems seem to be able to attract the best programmers as for the best surgeons in the market. The inflating costs of healthcare are instead more worrying. In the case of software, there is a trade-off between value (and so monetary revenue) produced and cost, while it is much more difficult to ethically quantify if the costs of medical procedures are worth bearing. What is happening in software is that there is absolutely no regulation on who can be a supplier in the market, and as such the average (and also median) quality of the products is terrifying. I'm not saying that you should adopt the values of medicine in your work, which can be a stretch for Wordpress applications, but that if you share them, the surgery metaphor becomes interesting for you. Software is as important as human lives only when they depend on it, in the case of biomedical and transportation systems such as pacemakers and flight control; other important categories of software are business critical, and as such economic metaphors will suit them more than the medical one.
May 21, 2012
by Giorgio Sironi
· 8,622 Views
article thumbnail
7 Application Deployment Best Practices
Someone just asked me to define “best practices” for a collection of application deployments.
May 21, 2012
by James Betteley
· 38,365 Views
article thumbnail
Lucene Setup on OracleDB in 5 Minutes
This tutorial is for people who want to run an Apache Lucene example with OracleDB in just five minutes.
May 19, 2012
by Mohammad Juma
· 31,575 Views · 4 Likes
article thumbnail
Spring Integration: Splitter-Aggregator
Within Spring Integration, one form of EIP scatter-gather is provided by the splitter and aggregator constructs.
May 18, 2012
by Matt Vickery
· 47,832 Views · 2 Likes
article thumbnail
Creating A Custom Camel Component
While Camel supports an ever growing number of components, you might have a need to create a custom component. This could be to either promote reuse across projects, customize an existing component or provide a simplified interface to an existing system. Whatever the reason, here is an overview of the options that are available within the Camel framework... first, consider just creating a Bean or Processor Before you jump in and create a component, consider just creating a simple class to handle your custom logic. Behind the scenes, all components are just Processors with a bunch of lifecycle support around them. Beans and Processors are simple, streamlined and easy to manage. using a Bean... from(uri).bean(MyBean.class); ... public class MyBean { public void doSomething(Exchange exchange) { //do something... } } using a Processor... from(uri).process(new MyProcessor()); ... public class MyProcessor implements Processor { public void process(Exchange exchange) throws Exception { //do something... } } create a custom component If you decide to go down this route, you should start by start by using a Maven archetype to stub out a new component project for you. mvn archetype:generate -DarchetypeGroupId=org.apache.camel.archetypes -DarchetypeArtifactId=camel-archetype-component -DarchetypeVersion=2.7 -DarchetypeRepository=https://repository.apache.org/content/groups/snapshots-group -DgroupId=org.apache.camel.component -DartifactId=camel-ben This will create a new Maven component project that contains an example HelloWorld component as seen here... HelloWorldComponent endpoint factory which implements createEndpoint() HelloWorldEndpoint producer/consumer factory which implements createConsumer(), createProducer(), createExchange() HelloWorldConsumer acts as a service to consumes request at the start of a route HelloWorldProducer acts as a service consumer to dispatch outgoing requests and receive incoming replies Exchange encapsulate the in/out message payloads and meta data about the data flowing between endpoints Message represent the message payload their is an IN and OUT message for each exchange So, how do all these classes/method actually work? The best way to get your head around this is to load the project into Eclipse (or IntelliJ) and debug the unit test. This will allow you to step into the route initialization and message processing to trace the flow. Consumer Lifecycle When you define a route that uses your new component as a consumer, like this from("helloworld:foo").to("log:result"); It does the following: creates a HelloWorldComponent instance (one per CamelContext) calls HelloWorldComponent createEndpoint() with the given URI creates a HelloWorldEndpoint instance (one per route reference) creates a HelloWorldConsumer instance (one per route reference) register the route with the CamelContext and call doStart() on the Consumer consumers will then start in one of the following modes: event driven - wait for message to trigger route polling consumer - manually polls a resource for events scheduled polling consumer - events automatically generated by timer custom threading - custom management of the event lifecyle Producer Lifecycle When you define a route that uses your new component as a producer, like this from("direct:start").to("helloworld:foo"); It does the following: creates a HelloWorldComponent instance (one per CamelContext) calls HelloWorldComponent createEndpoint() with the given URI creates a HelloWorldEndpoint instance (one per route reference) creates a HelloWorldProducer instance (one per route reference) register the route with the CamelContext and start the route consumer the Producer's process(Exchange) method is then executed generally, this will decorate the Exchange by interfacing with some external resource (file, jms, database, etc) Other Resources: http://camel.apache.org/writing-components.html http://fusesource.com/docs/router/2.8/prog_guide/Component.html
May 16, 2012
by Ben O'Day
· 38,647 Views · 3 Likes
article thumbnail
Taking Browser Screenshots With No Display (Selenium/Xvfb)
In my last two blog posts, I showed examples of using Selenium WebDriver to capture screenshots, and running in a headless (no X-server) mode. This example combines the two solutions to capture screenshots inside a virtual display. To achieve this, I use a combination of Selenium WebDriver and pyvirtualdisplay (which uses xvfb) to run a browser in a virtual display and capture screenshots. the setup you need is: Selenium 2 Python bindings: PyPI pyvirtualdisplay Python package (depends on xvfb): PyPI On Debian/Ubuntu Linux systems, you can install everything with: $ sudo apt-get install python-pip xvfb xserver-xephyr $ sudo pip install selenium once you have it setup, the following code example should work: #!/usr/bin/env python from pyvirtualdisplay import Display from selenium import webdriver display = Display(visible=0, size=(800, 600)) display.start() browser = webdriver.Firefox() browser.get('http://www.google.com') browser.save_screenshot('screenie.png') browser.quit() display.stop() this will: launch a virtual display launch Firefox browser inside the virtual display navigate to google.com capture and save a screenshot close the browser stop the virtual display
May 16, 2012
by Corey Goldberg
· 25,885 Views
article thumbnail
Virtualization in WPF with VirtualizingStackPanel
First blogged about this on my previous blog site here: http://consultingblogs.emc.com/merrickchaffer/archive/2011/02/14/virtualization-in-wpf-with-virtualizingstackpanel.aspx However, having come across this again today on a project, I thought it was important enough to re-blog! Finally managed to figure out how to get virtualization to actually behave itself in a listbox wpf control. Turns out that in order for Virtualization to work, you need three things satisfied. Use a control that supports virtualization (e.g. list box or list view). (see Controls That Implement Performance Features section at bottom of this page for more info http://msdn.microsoft.com/en-us/library/cc716879.aspx#Controls ) Ensure that the ScrollViewer.CanContentScroll attached property is set to True on the containing list box / list view control. Ensure that either the list box has a height set, or that it is contained within a parent Grid row, where that row definition has a height set (Height="*" will do if you want it to occupy the Client window height). Note: Do not use height=”Auto” as this will not work, as this instructs WPF to simply size the row to the height needed to fit all the items of the list box in, hence you do not get the vertical scroll bar appearing. Ensure that there is no wrapping ScrollViewer control around the list box, as this will prevent virtualization from occuring. Ensure that you use a VirtualizingStackPanel in the ItemsPanelTemplate for the ListBox.ItemsPanel Example
May 14, 2012
by Merrick Chaffer
· 28,468 Views
article thumbnail
Functional Programming on the JVM
Introduction In recent times, many programming languages that run on JVM have emerged. Many of these languages support the concept of writing code in a functional style. Programmers have started realizing the benefits of functional programming and are beginning to rediscover the powerful style of this programming paradigm. The emergence of multiple languages on JVM have only helped to reignite the strong interest in this paradigm. Java at its core is an imperative programming language. However in recent past many new languages like Scala, Clojure, Groovy etc. have become popular which supports functional programming style and yet run on JVM. However none of these languages can be considered as pure functional language since all of them allow Java code to be called from within them and Java on its own is not a functional language. Still they have different degree of support for writing code in functional style and have their own benefits. Functional programming requires different kind of thinking and has its own advantages as compared to imperative programming. It seems that Java has also realized functional programming advantages and is slowly inching towards it. First sign of this can be seen in the form of Lambda Expressions that will be supported in Java 8. Although it's too early to comment on this as the draft for Java 8 is still under review and is expected to be released next year, but it does show that Java has plans of supporting functional programming style going forward. In this article we will first discuss what functional programming is and how it is different from imperative programming. Later we will see where does each of the above mentioned Java based programming languages i.e. Scala, Clojure and Groovy fits in the world of functional programming and what each of them has to offer. And at the last we will sneak-peak into Java 8's lambda expressions. Why Functional Programming? Computers of current era are shipped with multicore processors. Going forward the number of processors in a machine is only going to increase. The code we write today and tomorrow will probably never run on a single processor system. In order to get best out of this, software must be designed to make more and more use of concurrency and hence keep all available processors busy. Java does provide concurrency concepts like threads, synchronization, locks etc. to execute code in parallel. But shared memory multi-threading approach in Java causes more trouble than solving the problem. Java based functional programming languages like Scala, Clojure, Groovy etc. looks into these problems with a different angle and provides less complex and less error-prone solutions as compared to imperative programming. They provide immutability concepts out of the box and hence eliminate need of synchronization and associated risk of deadlocks or livelocks. Concepts like Actors, Agents and DataFlow variables provide high level concurrency abstraction and makes very easy to write concurrent programs. What is Functional Programming? Functional Programming is a concept which treats functions as first class citizens. At the core of functional programming is immutability. It emphasizes on application of functions in contrast to imperative programming style which emphasizes on change in state. Functional programming has no side effects whereas programming in imperative style can result in side-effects. Let's elaborate more on each of these characteristics to understand the concept behind functional programming. Immutable state - The state of an object doesn't change and hence need not be protected or synchronized. That might sound a bit awkward at first, since if nothing changes, one might think that we are not writing a useful program. However that's not what immutable state means. In functional programming, change in state occurs via series of transformations which keeps the object immutable and yet achieves change in state. Functions as first class citizens - There was a major shift in the way programs were written when Object oriented concepts came into picture. Everything was conceptualized as object and any action to be performed was treated as method call on objects. Hence there is a series of method calls executed on objects to get the desired work done. In functional programming world, it's more about thinking in terms of communication chain between functions than method calls on objects. This makes functions as first class citizens of functional programming since everything is modelled around functions. Higher-order functions - Functions in functional programming are higher order functions since following actions can be performed with them. 1. Functions can be passed within functions as arguments. 2. Functions can be created within functions just as objects can be created in functions 3. Functions can be returned from functions Functions with no side-effects - In functional programming, function execution has no side-effects. In other words a function code will always return same result for same argument when called multiple times. It doesn't change anything outside its boundaries and is also not affected by any external change outside it's boundary. It doesn't change input value and can only produce new output. However once the output has been produced and returned by function, it also becomes immutable and cannot be modified by any other function. In other words, they support referential transparency i.e. if a function takes an input and returns some output, multiple invocation of that function at different point of time will always return same output as long as input remains same. This is one of the main motivations behind using functional language as it makes easy to understand and predict behaviour of program. Characteristics like immutability and no side-effects are extremely helpful while writing multi-threaded code and developers need not to worry for synchronizing the state. Hence functional code is very easy to distribute across multiple cores as they don't have any side effects. JVM based Functional Programming Languages There are many JVM based languages which supports functional programming paradigm. However I intend to limit discussion around following. Scala Clojure Groovy Lambda Expressions in Java 8 Lambda Expressions is not a programming language but a feature that will be supported in Java8. The reason for including it in this article is to emphasize on the fact that going forward Java will also support writing code in functional style. Scala Scala is a statically typed multi-paradigm programming language designed to integrate features of object oriented programming and functional programming. Since it is static, one cannot change class definition at run time i.e. one cannot add new methods or variables at run-time. However Scala does provide functional programming concepts i.e. immutability, higher-order functions, nested functions etc. Apart from supporting Java's concurrency model, it also provides concept of Actor model out of the box for event based asynchronous message passing between objects. The code written in Scala gets compiled into very efficient bytecode which can then be executed on JVM. Creating immutable list in Scala is very simple and doesn't require any extra effort. "val" keyword does the trick. val numbers = List(1,2,3,4) Functions can be passed as arguments. Let's see this with an example. Suppose we have a list of 10 numbers and we want to calculate sum of all the numbers in list. val numbers = List(1,2,3,4,5,6,7,8,9,10) val total = numbers.foldLeft(0){(a,b) => a+b } As can be seen in above example, we are passing a function to add two variables "a" and "b" to another function "foldLeft" which is provided by Scala library on collections. We have also not used any iteration logic and temporary variable to calculate the sum. "foldLeft" method eliminates the need to maintain state in temporary variable which would have otherwise be required if we were to write this code in pure Java way (as mentioned below). int total = 0; for(int number in numbers){ total+=number; } Scala function can easily be executed in parallel without any need for synchronization since it does not mutate state. This was just a small example to showcase the power of Scala as functional programming language. There are whole lot of features available in Scala to write code in functional style. Clojure Clojure is a dynamic language with an excellent support for writing code in functional style. It is a dialect of "lisp" programming language with an efficient and robust infrastructure for multithreaded programming. Clojure is predominantly a functional programming language, and features a rich set of immutable, persistent data structures. When mutable state is needed, Clojure offers a software transactional memory system and reactive Agent system that ensure clean, correct multithreaded designs. Apart from this since Clojure is a dynamic language, it allows to modify class definition at run time by adding new methods or modifying existing one at run time. This makes it different from Scala which is a statically typed language. Immutability is in the root of Clojure. To create immutable list just following needs to be done. By default list in Clojure is immutable, so does not require any extra effort. (def numbers (list 1 2 3 4 5 6 7 8 9 10)) To add numbers without maintaining state, reduce function can be used as mentioned below (reduce + 0 '(1 2 3 4 5 6 7 8 9 10)) As can be seen, adding list of numbers just requires one line of code without mutating any state. This is the beauty about functional programming languages and plays an important role for parallel execution. Groovy Groovy is again a dynamic language with some support for functional programming. Amongst the 3 languages, Groovy can be considered weakest in terms of functional programming features. However because of it's dynamic nature and close resemblance to Java, it has been widely accepted and considered good alternative to Java. Groovy does not provide immutable objects out of the box but has excellent support for higher order functions. Immutable objects can be created with annotation @Immutation, but it's far less flexible than immutablity support in Scala and Clojure. In Groovy functions can be passed around just as any other variable in the form of Closures. The same example in Groovy can be written as follows def numbers = [1,2,3,4,5,6,7,8,9,10] def total = numbers.inject(0){a,b -> a+b } However the point to be noted is that variables "numbers" and "total" are not immutable and can be modified at any point of time. Hence writing multithreaded code can be a bit challenging. But Groovy does provide the concept of Actors, Agents and DataFlow variables via library called GPars(Groovy Parallel System) which reduces the challenges associated with multithreaded code to a greater extent. Java8 Lambda Expression Java has finally realized the power of writing code in functional style and is going to support the concept of closures starting from Java8. JSR 335 - Lambda Expressions for the JavaTM Programming Language aims to support programming in a multicore environment by adding closures and related features to the Java language. So it will finally be possible to pass around functions similar to variables in pure Java code. Currently if someone wants to try out and play around lambda expressions, Project Lambda of OpenJDK provides prototype implementation of JSR-335. Following code snippet should run fine with OpenJDK Project Lambda compiler. ExecutorService executor = Executors.newCachedThreadPool(); executor.submit(() -> {System.out.println("I am running")}) As can be seen above, a closure(function) has been passed to executor's submit method. It does not take any argument and hence empty brackets () have been placed. This function just prints "I am running" when executed. Just as we can pass functions to function, it will also be possible to create closure within functions and return closure from function. I would recommend to try out OpenJDK to get a feel of lambda expressions which is going to be part of Java8 Conclusion So this was all about functional programming, it's concepts, benefits and options available on JVM to write function code. Functional programming requires a different mind-set and can be very useful if used correctly. Functional Programming along with Object Oriented Programming can be a jewel in crown. As discussed there are various options available to write code in functional style that can be executed on JVM. Choice depends on various factors and there is no one language that can be considered best in all aspects. However one thing is for sure, going forward we are going to see more and more usage of functional programming.
May 14, 2012
by Gagan Agrawal
· 29,595 Views
article thumbnail
Basic REST service in Apache CXF vs. Camel-CXF
This article demonstrates how to create/test a basic REST service in CXF vs. Camel-CXF. Given the range of configuration and deployment options, I'm focusing on building a basic OSGi bundle that can be deployed in Fuse 4.2 (ServiceMix)...basic knowledge of Maven, ServiceMix and Camel are assumed. Apache CXF For more details, see http://cxf.apache.org/docs/jax-rs.html. Here is an overview of the steps to get a basic example running... 1. add dependencies to your pom.xml org.apache.cxf cxf-rt-frontend-jaxrs 2.3.0 2. setup the bundle-context.xml file 3. create a service bean class @Path("/example") public class ExampleBean { @GET @Path("/") public String ping() throws Exception { return "SUCCESS"; } } 4. deploy and test build the bundle using "mvn install" start servicemix deploy the bundle open a browser to "http://localhost:9000/example" (should see "SUCCESS") Camel-CXF For details, see http://camel.apache.org/cxfrs.html. Here is an overview of the steps to get a basic example running... 1. add dependencies to your pom.xml org.apache.camel camel-core ${camel.version} org.apache.camel camel-cxf ${camel.version} 2. setup the bundle-context.xml file com.example 3. create a RouteBuilder class public class ExampleRouter extends RouteBuilder { @Override public void configure() throws Exception { from("cxfrs://http://localhost:9000?resourceClasses=" + ExampleResource.class.getName()) .process(new Processor() { public void process(Exchange exchange) throws Exception { //custom processing here } }) .setBody(constant("SUCCESS")); } } 4. create a REST Resource class @Path("/example") public class ExampleResource { @GET public void ping() { //strangely, this method is not called, only serves to configure the endpoint } } 5. deploy and test build bundle using "mvn install" start servicemix deploy the bundle open a browser to "http://localhost:9000/example" (should see "SUCCESS") Unit Testing To perform basic unit testing for either of these approaches, use the Apache HttpClient APIs by first adding this dependency to your pom.xml... org.apache.httpcomponents httpclient 4.0.1 Then, you can use these APIs to create a basic test to validate the REST services created above... String url = "http://localhost:9000/example"; HttpGet httpGet = new HttpGet(url); HttpClient httpclient = new DefaultHttpClient(); HttpResponse response = httpclient.execute(httpGet); String responseMessage = EntityUtils.toString(response.getEntity()); assertEquals("SUCCESS", responseMessage); assertEquals(200, response.getStatusLine().getStatusCode()); Summary Overall, the approaches are very similar, but you can use various combinations of Spring XML and Java APIs to set this up. I focused on a common approach to demonstrate the basics of each approach side-by-side. That being said, if you have requirements for complex REST services (security, interceptors, filters, etc), I recommend grabbing a copy of Apache CXF Web Service Development and following some of the more complex examples on the Apache CXF, Camel-CXFRS pages. In practice, I've generally used Camel-CXF because it gives you the flexibility of integrating with other Camel components and allows you to leverage the rich routing features of Camel. I hope to cover more complex scenarios in future posts...
May 14, 2012
by Ben O'Day
· 33,709 Views · 2 Likes
article thumbnail
uDeploy Built-in Properties Run-Down
A few folks suggested to me that a bit more information on the built-in properties and property scoping for uDeploy would be handy. Message received, and we’ll flesh out the documentation on that front. In the meantime, here’s a quick list of the automaticly available properties. ${p:version.name} ${p:version.id} ${p:component.name} ${p:component.id} ${p:resource.name} ${p:resource.id} ${p:application.name} ${p:application.id} ${p:environment.name} ${p:environment.id} ${p:} – Process properties. Defined on the process’s “properties” tab, given values by whoever is running the process. ${p:component/} – Component custom properties, set on the component’s “properties” tab. ${p:environment/} – Environment properties. These come from two places. You can define properties on the component’s properties tab, under the Environment Properties table. You then give values for these on each environment using the component. In addition, you can set custom environment properties on the environment’s properties tab. These custom properties will override the properties coming from components, although it’s recommended to avoid having the same name in both places. ${p:resource/} – Resource properties. This can include the built-in agent properties as well as any custom properties. Each of these have their own tab on the resource. ${p:resource//} – Resource role properties. These are defined on resource roles, and the values are set when you add a role to a resource. ${p:application/} – Global system properties. These are set on the “System Properties” page in the Settings area. All of the following are comma-separated series of name=value, including each property on the given object. ${p:component/allProperties} ${p:environment/allProperties} ${p:resource/allProperties} ${p:system/allProperties}
May 13, 2012
by Eric Minick
· 12,687 Views
article thumbnail
EasyNetQ, a simple .NET API for RabbitMQ
After pondering the results of our message queue shootout, we decided to run with Rabbit MQ. Rabbit ticks all of the boxes, it’s supported (by Spring Source and then VMware ultimately), scales and has the features and performance we need. The RabbitMQ.Client provided by Spring Source is a thin wrapper that quite faithfully exposes the AMQP protocol, so it expects messages as byte arrays. For the shootout tests spraying byte arrays around was fine, but in the real world, we want our messages to be .NET types. I also wanted to provide developers with a very simple API that abstracted away the Exchange/Binding/Queue model of AMQP and instead provides a simple publish/subscribe and request/response model. My inspiration was the excellent work done by Dru Sellers and Chris Patterson with MassTransit (the new V2.0 beta is just out). The code is on GitHub here: https://github.com/mikehadlow/EasyNetQ The API centres around an IBus interface that looks like this: /// /// Provides a simple Publish/Subscribe and Request/Response API for a message bus. /// public interface IBus : IDisposable { /// /// Publishes a message. /// /// The message type /// The message to publish void Publish(T message); /// /// Subscribes to a stream of messages that match a .NET type. /// /// The type to subscribe to /// /// A unique identifier for the subscription. Two subscriptions with the same subscriptionId /// and type will get messages delivered in turn. This is useful if you want multiple subscribers /// to load balance a subscription in a round-robin fashion. /// /// /// The action to run when a message arrives. /// void Subscribe(string subscriptionId, Action onMessage); /// /// Makes an RPC style asynchronous request. /// /// The request type. /// The response type. /// The request message. /// The action to run when the response is received. void Request(TRequest request, Action onResponse); /// /// Responds to an RPC request. /// /// The request type. /// The response type. /// /// A function to run when the request is received. It should return the response. /// void Respond(Func responder); } To create a bus, just use a RabbitHutch, sorry I couldn’t resist it :) var bus = RabbitHutch.CreateRabbitBus("localhost"); You can just pass in the name of the server to use the default Rabbit virtual host ‘/’, or you can specify a named virtual host like this: var bus = RabbitHutch.CreateRabbitBus("localhost/myVirtualHost"); The first messaging pattern I wanted to support was publish/subscribe. Once you’ve got a bus instance, you can publish a message like this: var message = new MyMessage {Text = "Hello!"}; bus.Publish(message); This publishes the message to an exchange named by the message type. You subscribe to a message like this: bus.Subscribe("test", message => Console.WriteLine(message.Text)); This creates a queue named ‘test_’ and binds it to the message type’s exchange. When a message is received it is passed to the Action delegate. If there are more than one subscribers to the same message type named ‘test’, Rabbit will hand out the messages in a round-robin fashion, so you get simple load balancing out of the box. Subscribers to the same message type, but with different names will each get a copy of the message, as you’d expect. The second messaging pattern is an asynchronous RPC. You can call a remote service like this: var request = new TestRequestMessage {Text = "Hello from the client! "}; bus.Request(request, response => Console.WriteLine("Got response: '{0}'", response.Text)); This first creates a new temporary queue for the TestResponseMessage. It then publishes the TestRequestMessage with a return address to the temporary queue. When the TestResponseMessage is received, it passes it to the Action delegate. RabbitMQ happily creates temporary queues and provides a return address header, so this was very easy to implement. To write an RPC server. Simple use the Respond method like this: bus.Respond(request => new TestResponseMessage { Text = request.Text + " all done!" }); This creates a subscription for the TestRequestMessage. When a message is received, the Func delegate is passed the request and returns the response. The response message is then published to the temporary client queue. Once again, scaling RPC servers is simply a question of running up new instances. Rabbit will automatically distribute messages to them. The features of AMQP (and Rabbit) make creating this kind of API a breeze. Check it out and let me know what you think.
May 13, 2012
by Mike Hadlow
· 11,444 Views
article thumbnail
Eclipse Global Preferences
rate this eclipse is good, but like any other tool: it gets better after i have it customized for my special needs. eclipse stores a lot of settings in the workspace, see my article about copy my workspace settings . but is there a way to apply some settings to every workspace? at least to the new ones? because importing/exporting the settings can get really tedious as i have many workspace. and indeed, there are global settings in eclipse. and i want to have them changed… warning: changing eclipse global preferences might break an eclipse installation. so better have a backup of the changed files at hand! i’m using here the eclipse based codewarrior for mcu10.2 , but things are pretty much the same for any eclipse based product (see the documentation in defining your own global preferences ). question: where are the global preferences stored? the first thing to check is the eclipse\configuration\.settings folder: here some plugins store their global preferences. for example: the recent workspace settings are in org.eclipse.ui.ide.prefs. #fri apr 06 16:46:14 cest 2012 recent_workspaces_protocol=3 max_recent_workspaces=10 show_workspace_selection_dialog=true eclipse.preferences.version=1 recent_workspaces=c\:\\tmp\\wsp_test\nc\:\\tmp\\wsp_10.2 but what about all the other settings? looking at the codewarrior installation, inside the eclipse folder, i find the cwide.ini file. cwide.ini file this file defines the eclipse startup options for launching the ide (cwide.exe for codewarrior). the interesting part is this line: -declipse.plugincustomization=cwide.properties this tells eclipse to use the cwide.properties as a default configuration file. if i inspect that file, it has the following content: org.eclipse.debug.ui/org.eclipse.debug.ui.switch_perspective_on_suspend=always org.eclipse.debug.ui/org.eclipse.debug.ui.switch_to_perspective=always org.eclipse.ui.editors/spellingengine=org.eclipse.cdt.internal.ui.text.spelling.cspellingengine ok, that gives me an idea how settings could look like. but the question is: how to know the settings and syntax? what works (most of the time) is following approach: launch eclipse with a new workspace export the settings using file > export > general > preferences to a file change the setting in window > preferences export the settings using file > export > general > preferences to a different file compare/inspect the exported information and find the settings apply the settings to the cwide.properties file, without the /instance/ part restart the ide and check if it works with a new workspace the last check is necessary as not all settings might work that way, see this forum post . this is maybe best illustrated with an example. i have configured my workspace to use 2 for tab width and to insert spaces for tabs: changed preferences for tabs if i compare the two exported .epf files, this gives me: diffing eclipse preference files that means the two following lines are configuring what i have changed: /instance/org.eclipse.ui.editors/tabwidth=2 /instance/org.eclipse.ui.editors/spacesfortabs=true for the cwide.properties file i need to cut off the /instance/ part, so i have this added to the cwide.properties : # set tab width to 2 org.eclipse.ui.editors/tabwidth=2 # using spaces for tabs org.eclipse.ui.editors/spacesfortabs=true note: preferences are applied in following order: global preferences, then local (workspace) preferences this does not overwrite an existing setting of my workspace. as i can see from above diff, my initial workspace settings do not have any settings for tabwidth and spacesfortabs. creating a new workspace use and apply my new settings. but once i have the them, they will not be overwritten with new global ones. which makes sense: the local settings are winning. note: post a comment if you know an elegant way how to enforce/overwrite workspace settings with global ones.
May 12, 2012
by Erich Styger
· 19,009 Views · 1 Like
article thumbnail
Runtime Classpath vs Compile-Time Classpath
This should really be a simple distinction, but I’ve been answering a slew of similar questions on Stackoverflow, and often people misunderstand the matter. So, what is a classpath? A set of all the classes (and jars with classes) that are required by your application. But there are two, or actually three distinct classpaths: compile-time classpath. Contains the classes that you’ve added in your IDE (assuming you use an IDE) in order to compile your code. In other words, this is the classpath passed to “javac” (though you may be using another compiler). runtime classpath. Contains the classes that are used when your application is running. That’s the classpath passed to the “java” executable. In the case of web apps this is your /lib folder, plus any other jars provided by the application server/servlet container test classpath – this is also a sort of runtime classpath, but it is used when you run tests. Tests do not run inside your application server/servlet container, so their classpath is a bit different Maven defines dependency scopes that are really useful for explaining the differences between the different types of classpaths. Read the short description of each scope. Many people assume that if they successfully compiled the application with a given jar file present, it means that the application will run fine. But it doesn’t – you need the same jars that you used to compile your application to be present on your runtime classpath as well. Well, not necessarily all of them, and not necessarily only them. A few examples: you compile the code with a given library on the compile-time classpath, but forget to add it to the runtime classpath. The JVM throws NoClasDefFoundError, which means that a class is missing, which was present when the code was compiled. This error is a clear sign that you are missing a jar file on your runtime classpath that you have on your compile-time classpath. It is also possible that a jar you depend on in turn depends on a jar that you don’t have anywhere. That’s why libraries (must) have their dependencies declared, so that you know which jars to put on your runtime classpath containers (servlet containers, application servers) have some libraries built-in. Normally you can’t override the built-in dependencies, and even when you can, it requires additional configuration. So, for example, you use Tomcat, which provides the servlet-api.jar. You compile your application with the servlet-api.jar on your compile-time classpath, so that you can use HttpServletRequest in your classes, but do not include it in your WEB-INF/lib folder, because tomcat will put its own jar in the runtime classpath. If you duplicate the dependency, you may get bizarre results, as classloaders get confused. a framework you are using (let’s say spring-mvc) relies on another library to do JSON serialization (usually Jackson). You don’t actually need Jackson on your compile-time classpath, because you are not referring to any of its classes or even spring classes that refer to them. But spring needs Jackson internally, so the jackson jar must be in WEB-INF/lib (runtime classpath) for JSON serialization to work. The cases might be complicated even further, when you consider compile-time constants and version mismatches, but the general point is this: the classpaths that you use for compiling and for running the application are different, and you should be aware of that.
May 12, 2012
by Bozhidar Bozhanov
· 30,414 Views · 2 Likes
article thumbnail
TeamCity Build Dependencies
The subject of build dependencies is neither a trivial nor a minor one. Various build tools approach this subject from different perspectives contributing various solutions, each with its own strengths and weaknesses. Maven and Gradle users who are familiar with release and snapshot dependencies may not know about TeamCity snapshot dependencies or assume they’re somehow related to Maven (which isn’t true). TeamCity users who are familiar with artifact and snapshot dependencies may not know that adding an Artifactory plugin allows them to use artifact and build dependencies as well, on top of those provided by TeamCity. Some of the names mentioned above seem not to be established enough while others may require a discussion about their usage patterns. Having this in mind I’ve decided to explore each solution in its own blog post, setting a goal of providing enough information so that people can choose what works best. The first post explored Maven snapshot and release dependencies. This is the second post, which covers artifact and snapshot dependencies provided by TeamCity and the third and final part will cover the artifact and build dependencies provided by TeamCity Artifactory plugin. Non-Maven Dependencies While Maven-based dependencies management and artifact repositories are very common and widespread in Java, there are cases where you may still find them insufficient or inadequate for your needs. For starters, you may not be developing in Java or perhaps your build tool is not providing built-in integration with Maven repositories, as is the case with Ant (or its Gant and NAnt spin-offs), SCons, Rake or MSBuild. Secondly, snapshot Maven dependencies provide their own set of challenges covered in the previous blog post, making it harder to ensure correct snapshot dependency is used in a chain of builds. In order to address these scenarios, TeamCity provides two ways to connect dependent build configurations and their outcomes: artifact and snapshot dependencies. TeamCity Artifact Dependencies The idea of artifact dependencies in TeamCity is very simple: download the artifacts produced by an other build before the current one begins. After the artifacts are downloaded to the folder specified (checkout directory by default), your build script can use them to achieve its goals. You can find configuration details in TeamCity documentation. Naturally, this scheme is not suitable for build tools with automatic dependencies management, but it works well with build or shell scripts accepting and expecting local paths, relative to the checkout directory. Note that the copying works not only for the produced build binaries, but for any kind of binary or text files, like the TeamCity coverage report as demonstrated on the screenshot above. There is one important detail about specifying artifact dependencies and that is “Get artifacts from” configuration where you specify what type of build should files be taken from. Possible values of this field are “last successful”, “finished”, “pinned”, or “tagged build”, as well as the build number or “Build from the same chain”. While most values should be trivial to understand with “Last successful build” being the default and generally suitable option, the definition of “same chain” build is directly related to TeamCity snapshot dependencies. TeamCity Snapshot Dependencies Imagine a monolithic multi-step build process (build, test, package, deploy) which you decide to split into multiple smaller builds, invoked sequentially, forming a chain of executions. Doing so allows one to configure or trigger every chain step separately and run certain steps in parallel in order to speedup the process (like executing tests or building independent components). Most of all, it makes the overall maintenance significantly easier. However, while doing so you need to ensure every chain step uses the same consistent set of sources pulled from VCS even if newer commits are made all the while chain steps are running. That’s what TeamCity snapshot dependencies are for: they connect several build configurations into a single chain of execution, called build chain, with every step using the same set of sources, regardless of VCS updates. Note that the TeamCity use of the term “snapshot dependencies” may confuse people familiar with Maven snapshot dependencies which are two unrelated concepts. Snapshot dependencies are configured similarly to artifact dependencies. You can find configuration details in TeamCity documentation. Using Artifact and Snapshot Dependencies Together When applicable, it is recommended to define both kinds of dependencies between build configurations, as this ensures not only a consistent set of sources used throughout a chain steps but also a consistent flow of artifacts produced. Now the definition of “Build from the same chain” in artifact dependency mentioned above becomes clear, as this is the only meaningful option in this scenario. In a way, you can think of build chain steps running in isolation from VCS updates after the first sources’ “snapshot” is taken. Chain artifacts are either re-created from the same sources or passed through chain steps with artifact dependencies. This makes chain steps consistent, reproducible and always up-to-date (when applied to using chain artifacts), something that can’t be easily achieved with Maven snapshot dependencies. Build Chains Visibility in TeamCity 7.0 TeamCity 7.0 took the notion of build chains to a whole new level by providing build chains a new UI, making chain steps visible and re-runnable. Once you have snapshot dependencies defined, a new “Build Chains” tab appears in project reports, providing a visual representation of all related build chains and a way to re-run any chain step manually, using the same set of sources pulled originally. Build Chain Triggering Having build configurations connected with snapshot dependencies and, therefore, their builds grouped into build chains not only makes them more consistent regarding the sources used, it also impacts the way builds are added to the build queue: after a certain chain step is triggered, the default behavior is to add all preceding chain steps as well, keeping their respective order, in addition to the one that was triggered initially. Let me repeat it for more clarity: triggering certain chain configuration adds preceding (those to the left of it) and not subsequent (to the right of it) configurations to the build queue, although it may seem counterintuitive at first. The idea is to mark the location where chain execution stops, which is exactly the configuration that was triggered initially; it becomes the last execution step. To trigger subsequent chain steps upon VCS changes found in a chain configuration, you can add a VCS trigger with the “Trigger on changes in snapshot dependencies” option to the configuration that would be the last execution step. This configuration is then triggered whenever any of the preceding chain steps is updated, which schedules the whole chain for execution. Having this behavior in mind, you therefore need to decide which configurations are triggered automatically and which should be run manually. Usually, earlier chain steps having no impact on external environment can be triggered automatically by VCS trigger but final chain steps, potentially modifying external systems, are invoked manually after a human verification of the previous chain results. The process of running the final chain steps manually is usually referred to as “promoting” previously finished builds. Sample Build Chain: Compile, Test, Deploy Imagine three sample build configurations, "Compile", "Test" and "Deploy" connected into a build chain: "Deploy" is snapshot dependent on "Test" which is snapshot dependent on "Compile". In this sample scenario the "Compile" and "Test" configurations are triggered automatically while "Deploy" is triggered manually, following the recommendations given above. VCS changes in "Compile" configuration only trigger an execution of this chain step, while VCS changes in "Test" configuration trigger "Compile" and "Test" execution (in that order). Once a "Compile" configuration is added to the builds queue, its sources’ timestamp is recorded on the server to be used in all subsequent chain steps. If any of the chain steps is connected to a different VCS root, its sources are also pulled according to the same timestamp. Promoting Finished Builds As soon as the automatic chain execution stops (after running "Test"), you can continue it by clicking the corresponding “Run” button on the "Deploy" configuration that was not triggered (see the build chain screenshot above). Alternatively, it is possible to promote a finished "Test" build through its “Build Actions” and invoke configurations which are snapshot dependent on it – "Deploy" configuration in this case. Summary This article has provided an overview of TeamCity artifact and snapshot dependencies, build chains, how their steps are triggered and how finished builds are promoted. I hope you now have a good understanding of how it works and of when it is appropriate (or not) to use TeamCity build dependencies in addition to those provided by build tools such as Maven. Please, refer to the TeamCity documentation for more information about this subject: Dependent Build Build Chain The final blog post in the series will uncover how you can use the TeamCity Artifactory plugin in order to achieve a behavior which is similar to build chains for projects with Maven-based dependency management. Stay tuned!
May 11, 2012
by Evgeny Goldin
· 19,706 Views · 2 Likes
article thumbnail
Martin Fowler on ORM Hate
while i was at the qcon conference in london a couple of months ago, it seemed that every talk included some snarky remarks about object/relational mapping (orm) tools. i guess i should read the conference emails sent to speakers more carefully, doubtless there was something in there telling us all to heap scorn upon orms at least once every 45 minutes. but as you can tell, i want to push back a bit against this orm hate - because i think a lot of it is unwarranted. the charges against them can be summarized in that they are complex, and provide only a leaky abstraction over a relational data store. their complexity implies a grueling learning curve and often systems using an orm perform badly - often due to naive interactions with the underlying database. there is a lot of truth to these charges, but such charges miss a vital piece of context. the object/relational mapping problem is hard . essentially what you are doing is synchronizing between two quite different representations of data, one in the relational database, and the other in-memory. although this is usually referred to as object-relational mapping, there is really nothing to do with objects here. by rights it should be referred to as in-memory/relational mapping problem, because it's true of mapping rdbmss to any in-memory data structure. in-memory data structures offer much more flexibility than relational models, so to program effectively most people want to use the more varied in-memory structures and thus are faced with mapping that back to relations for the database. the mapping is further complicated because you can make changes on either side that have to be mapped to the other. more complication arrives since you can have multiple people accessing and modifying the database simultaneously. the orm has to handle this concurrency because you can't just rely on transactions- in most cases, you can't hold transactions open while you fiddle with the data in-memory. i think that if you if you're going to dump on something in the way many people do about orms, you have to state the alternative. what do you do instead of an orm? the cheap shots i usually hear ignore this, because this is where it gets messy. basically it boils down to two strategies, solve the problem differently (and better), or avoid the problem. both of these have significant flaws. a better solution listening to some critics, you'd think that the best thing for a modern software developer to do is roll their own orm. the implication is that tools like hibernate and active record have just become bloatware, so you should come up with your own lightweight alternative. now i've spent many an hour griping at bloatware, but orms really don't fit the bill - and i say this with bitter memory. for much of the 90's i saw project after project deal with the object/relational mapping problem by writing their own framework - it was always much tougher than people imagined. usually you'd get enough early success to commit deeply to the framework and only after a while did you realize you were in a quagmire - this is where i sympathize greatly with ted neward's famous quote that object-relational mapping is the vietnam of computer science [1] . the widely available open source orms (such as ibatis, hibernate, and active record) did a great deal to remove this problem [2] . certainly they are not trivial tools to use, as i said the underlying problem is hard, but you don't have to deal with the full experience of writing that stuff (the horror, the horror). however much you may hate using an orm, take my word for it - you're better off. i've often felt that much of the frustration with orms is about inflated expectations. many people treat the relational database "like a crazy aunt who's shut up in an attic and whom nobody wants to talk about" [3] . in this world-view they just want to deal with in-memory data-structures and let the orm deal with the database. this way of thinking can work for small applications and loads, but it soon falls apart once the going gets tough. essentially the orm can handle about 80-90% of the mapping problems, but that last chunk always needs careful work by somebody who really understands how a relational database works. this is where the criticism comes that orm is a leaky abstraction. this is true, but isn't necessarily a reason to avoid them. mapping to a relational database involves lots of repetitive, boiler-plate code. a framework that allows me to avoid 80% of that is worthwhile even if it is only 80%. the problem is in me for pretending it's 100% when it isn't. david heinemeier hansson, of active record fame, has always argued that if you are writing an application backed by a relational database you should damn well know how a relational database works. active record is designed with that in mind, it takes care of boring stuff, but provides manholes so you can get down with the sql when you have to. that's a far better approach to thinking about the role an orm should play. there's a consequence to this more limited expectation of what an orm should do. i often hear people complain that they are forced to compromise their object model to make it more relational in order to please the orm. actually i think this is an inevitable consequence of using a relational database - you either have to make your in-memory model more relational, or you complicate your mapping code. i think it's perfectly reasonable to have a more relational domain model in order to simplify your object-relational mapping. that doesn't mean you should always follow the relational model exactly, but it does mean that you take into account the mapping complexity as part of your domain model design. so am i saying that you should always use an existing orm rather than doing something yourself? well i've learned to always avoid saying "always". one exception that comes to mind is when you're only reading from the database. orms are complex because they have to handle a bi-directional mapping. a uni-directional problem is much easier to work with, particularly if your needs aren't too complex and you are comfortable with sql. this is one of the arguments for cqrs . so most of the time the mapping is a complicated problem, and you're better off using an admittedly complicated tool than starting a land war in asia. but then there is the second alternative i mentioned earlier - can you avoid the problem? avoiding the problem to avoid the mapping problem you have two alternatives. either you use the relational model in memory, or you don't use it in the database. to use a relational model in memory basically means programming in terms of relations, right the way through your application. in many ways this is what the 90's crud tools gave you. they work very well for applications where you're just pushing data to the screen and back, or for applications where your logic is well expressed in terms of sql queries. some problems are well suited for this approach, so if you can do this, you should. but its flaw is that often you can't. when it comes to not using relational databases on the disk, there rises a whole bunch of new champions and old memories. in the 90's many of us (yes including me) thought that object databases would solve the problem by eliminating relations on the disk. we all know how that worked out. but there is now the new crew of nosql databases - will these allow us to finesse the orm quagmire and allow us to shock-and-awe our data storage? as you might have gathered , i think nosql is technology to be taken very seriously. if you have an application problem that maps well to a nosql data model - such as aggregates or graphs - then you can avoid the nastiness of mapping completely. indeed this is often a reason i've heard teams go with a nosql solution. this is, i think, a viable route to go - hence my interest in increasing our understanding of nosql systems. but even so it only works when the fit between the application model and the nosql data model is good. not all problems are technically suitable for a nosql database. and of course there are many situations where you're stuck with a relational model anyway. maybe it's a corporate standard that you can't jump over, maybe you can't persuade your colleagues to accept the risks of an immature technology. in this case you can't avoid the mapping problem. so orms help us deal with a very real problem for most enterprise applications. it's true they are often misused, and sometimes the underlying problem can be avoided. they aren't pretty tools, but then the problem they tackle isn't exactly cuddly either. i think they deserve a little more respect and a lot more understanding. 1: i have to confess a deep sense of conflict with the vietnam analogy. at one level it seems like a case of the pathetic overblowing of software development's problems to compare a tricky technology to war. nasty the programming may be, but you're still in a relatively comfy chair, usually with air conditioning, and bug-hunting doesn't involve bullets coming at you. but on another level, the phrase certainly resonates with the feeling of being sucked into a quagmire. 2: there were also commercial orms, such as toplink and kodo. but the approachability of open source tools meant they became dominant. 3: i like this phrase so much i feel compelled to subject it to re-use.
May 9, 2012
by Martin Fowler
· 115,887 Views · 4 Likes
article thumbnail
Continuous Delivery vs. Traditional Agile
in working with development teams at organizations which are adopting continuous delivery , i have found there can be friction over practices that many developers have come to consider as the right way for agile teams to work. i believe the root of conflicts between what i’ve come to think of as traditional agile and cd is the approach to making software “ready for release”. evolution of software delivery a usefully simplistic view of the evolution of ideas about making software ready for release is this: waterfall believes a team should only start making its software ready for release when all of the functionality for the release has been developed (i.e. when it is “feature complete”). agile introduces the idea that the team should get their software ready for release throughout development. many variations of agile (which i refer to as “traditional agile” in this post) believe this should be done at periodic intervals. continuous delivery is another subset of agile which in which the team keeps its software ready for release at all times during development. it is different from “traditional” agile in that it does not involve stopping and making a special effort to create a releasable build. continuous delivery is not about shorter cycles going from traditional agile development to continuous delivery is not about adopting a shorter cycle for making the software ready for release. making releasable builds every night is still not continuous delivery. cd is about moving away from making the software ready as a separate activity, and instead developing in a way that means the software is always ready for release. ready for release does not mean actually releasing a common misunderstanding is that continuous delivery means releasing into production very frequently. this confusion is made worse by the use of organizations that release software multiple times every day as poster children for cd. continuous delivery doesn’t require frequent releases, it only requires ensuring software could be released with very little effort at any point during development. (see jez humble’s article on continuous delivery vs. continuous deployment .) although developing this capability opens opportunities which may encourage the organization to release more often, many teams find more than enough benefit from cd practices to justify using it even when releases are fairly infrequent. friction points between continuous delivery and traditional agile as i mentioned, there are sometimes conflicts between continuous delivery and practices that development teams take for granted as being “proper” agile. friction point: software with unfinished work can still be releasable one of these points of friction is the requirement that the codebase not include incomplete stories or bugfixes at the end of the iteration. i explored this in my previous post on iterations . this requirement comes from the idea that the end of the iteration is the point where the team stops and does the extra work needed to prepare the software for release. but when a team adopts continuous delivery, there is no additional work needed to make the software releasable. more to the point, the cd team ensures that their code could be released to production even when they have work in progress, using techniques such as feature toggles . this in turn means that the team can meet the requirement that they be ready for release at the end of the iteration even with unfinished stories. this can be a bit difficult for people to swallow. the team can certainly still require all work to be complete at the iteration boundary, but this starts to feel like an arbitrary constraint that breaks the team’s flow. continuous delivery doesn’t require non-timeboxed iterations, but the two practices are complementary. friction point: snapshot/release builds many development teams divide software builds into two types, “snapshot” builds and “release” builds. this is not specific to agile, but has become strongly embedded in the java world due to the rise of maven, which puts the snapshot/build concept at the core of its design. this approach divides the development cycle into two phases, with snapshots being used while software is in development, and a release build being created only when the software is deemed ready for release. this division of the release cycle clearly conflicts with the continuous delivery philosophy that software should always be ready for release. the way cd is typically implemented involves only creating a build once, and then promoting it through multiple stages of a pipeline for testing and validation activities, which doesn’t work if software is built in two different ways as with maven. it’s entirely possible to use maven with continuous delivery, for example by creating a release build for every build in the pipeline. however this leads to friction with maven tools and infrastructure that assume release builds are infrequent and intended for production deployment. for example, artefact repositories such as nexus and artefactory have housekeeping features to delete old snapshot builds, but don’t allow release builds to be deleted. so an active cd team, which may produce dozens of builds a day, can easily chew through gigabytes and terabytes of disk space on the repository. friction point: heavier focus on testing deployability a standard practice with continuous delivery is automatically deploying every build that passes basic continuous integration to an environment that emulates production as closely as possible, using the same deployment process and tooling. this is essential to proving whether the code is ready for release on every commit, but this is more rigorous than many development teams are used to having in their ci. for example, pre-cd continuous integration might run automated functional tests against the application by deploying it to an embedded application server using a build tool like ant or maven. this is easier for developers to use and maintain, but is probably not how the application will be deployed in production. so a cd team will typically add an automated deployment to an environment will more fully replicates production, including separated web/app/data tiers, and deployment tooling that will be used in production. however this more production-like deployment stage is more likely to fail due to its added complexity, and may be may be more difficult for developers to maintain and fix since it uses tooling more familiar to system administrators than to developers. this can be an opportunity to work more closely with the operations team to create a more reliable, easily supported deployment process. but it is likely to be a steep curve to implement and stabilize this process, which may impact development productivity. is cd worth it? given these friction points, what benefit is there to moving from traditional agile to continuous delivery worthwhile, especially for a team that is unlikely to actually release into production more often than every iteration? decrease risk by uncovering deployment issues earlier, increase flexibility by giving the organization the option to release at any point with minimal added cost or risk, involves everyone involved in production releases - such as qa, operations, etc. - in making the full process more efficient. the entire organization must identify difficult areas of the process and find ways to fix them, through automation, better collaboration, and improved working practices, by continuously rehearsing the release process, the organization becomes more competent at doing it, so that releasing becomes autonomic, like breathing, rather than traumatic, like giving birth, improves the quality of the software, by forcing the team to fix problems as they are found rather than being able to leave things for later. dealing with the friction the friction points i’ve described seem to come up fairly often when continuous delivery is being introduced. my hope is that understanding the source of this friction will be helpful in discussing it when it comes up, and working through the issues. if developers who are initially uncomfortable with breaking with the “proper” way of doing things, or find a cd pipeline overly complex or difficult understand the aims and value of these practices, hopefully they will be more open to giving them a chance. once these practices become embedded and mature in an organization, team members often find it’s difficult to go back to the old ways of doing them. edit: i’ve rephrased the definition of the “traditional agile” approach to making software ready for release. this definition is not meant to apply to all agile practices, but rather applies to what seems to me to be a fairly mainstream belief that agile means stopping work to make the software releasable.
May 9, 2012
by Kief Morris
· 54,402 Views · 7 Likes
  • Previous
  • ...
  • 1582
  • 1583
  • 1584
  • 1585
  • 1586
  • 1587
  • 1588
  • 1589
  • 1590
  • 1591
  • ...
  • 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
×