I have any number of articles that I have drafted and not published. Why, because sometimes it is cathartic to rant privately and get over it. Sometimes though it needs to be said. This is one of those times...
As a consultant, I typically work with organizations with very high system availability and resiliency requirements or SLAs. These organizations are in the 20th or 10th or even the 1st percentile of market. Enterprise organizations that are striving for some level of zero down time, immediate recovery and zero data loss on high-volume systems. These same organizations are also starting to embrace Free and Open-Source Software (FOSS) to replace their current Commercial Off-The-Shelf (COTS) product. And after they have completed 90% of their new project using FOSS I am typically called in and asked to solve the following: How do I make this "free" stuff meet my current SLA needs.
My answer is typically "you can't".
How did we get here?
It usually starts with a developer or architect that has been given the green light to develop a new application with FOSS. They read articles and see documented capabilities that will help them avoid writing large amounts of code to gain the same functionality. They download the product and run through some demos and see that bam, delivers as expected. Then they start the prototype...
The prototype is done in a vacuum, many times on a desktop. An environment that can in no way replicate the daily stress of a production environment. Then this person demonstrates their prototype to management, extrapolates some numbers and gets green lighted. And the project takes off.
Then after months of development they drop their newly minted product into a test environment and it doesn't come close to failing over fast enough or recovering fast enough or performing fast enough. They tweek and nob-turn and then they call.
"This product is awful. Come make this work!"
I typically arrive and find that there is little I can do for them in the short term. You know, turn a nob and all is well. Unfortunately the issue is really a misapplication of the capability or the capability just isn't working as expected. So while it has shaved significant amounts of time off of the development cycle the capability is now under tremendous stress and cracks began to show. Why did it work when it was in my prototype and not in production? Typically it is because you are using a product that has been written by the masses, for the masses or the other 80 percent of the market.
That doesn't mean it won't work. It is just important to keep in mind that FOSS projects are almost always on the bleeding edge of their given scope. They are in a perpetual state of motion, with that motion being forward, and as new capabilities are added it takes time before they are fully baked. Remember, someone out there with the greatest of intents and a genuine desire to help has added that handy new widget, one that you fully expect to make a living on. Sometimes it is a single use-case, sometimes it is a full-blown API. If it is a new capability, hopefully someone other than yourself needed it and went through the pains of hardening it for those in the 20th percentile. If not, it is now up to you and/or me. And you should never assume.
So how do you avoid this scenario?
Get Educated
Don't just read some articles and run through some demos. Download the sources and familiarize yourself with the unit tests that cover the capability you were planning on using. There are times you will find that what is being tested is not completely in line with what is documented. Again, FOSS is in a constant state of motion so there are going to be times when what is on paper and what is in the codebase don't align.
Get Involved
Are all your use cases covered? If not, write some and test it out. Make sure it works the way you were expecting. And when you are done, offer those test cases back to the community so others don't have to go through what you just did. Also, with all those new test cases you have just written, if you find an issue report it and follow through. The last part of that is so important. I see so many people jump in and say they have an issue or open up a Jira ticket and then just disappear. There is no indication as to whether the problem was solved or not. I know it takes time but you chose to use the free product. So don't be surprised when you are expected to give back.
Get Help
Finally, get those with experience involved early. Don't be afraid to ask questions on the mailing lists. You will get answers from a great many qualified folks who love to help. Its in their nature. They spend their free time writing software to give a way for free. That being the case I bet they would love to sit and talk with you about it.
There are also commercial organizations that provide services and support for all sorts of FOSS products. They have highly technical folks who are specialized in FOSS and how to get the best out of it. Spending a week with one of them in the early stages of your application may save you many weeks or months of issues later.
Having worked with a great number of developers on open-source projects like ActiveMQ, Camel, CXF, ServiceMix and Karaf, I have gotten to know these folks and one thing should be understood, they are very good at what they do. But there are only so many of them out there and so many use cases to cover. They need you to be involved to deliver that first class quality product.
Besides it is in your own best interest. Your application may be dependent on it.
Thursday, September 6, 2012
Monday, May 21, 2012
Karaf SCR Components
Hi All,
A while back I submitted a collection of SCR command and management components to the Apache Karaf project that were ultimately incorporated into the Karaf 3 trunk. They have been added to the Karaf 3 Feature XML also so you can look for it in the feature list. The components provide the ability to list, stop, start and get the details on currently loaded SCR components in the container. There are also a small set of examples that I will be writing about here in the near future on simplifying OSGi development using SCR and the BND Annotations for SCR & Metatype.
Now while this is great for those of us that use SCR it is currently only available in the Karaf 3.0.0-SNAPSHOT and as such, is not backwards compatible with the Karaf 2 releases. To remedy that I have released a couple of versions for Karaf 2 out on github under my karaf-sandbox project.
Currently I have created versions that are directly compatible with versions 2.2.5 & 2.2.7 as there were changes between them that broke the compatibility. They can be found in branches of the same name.
I will be changing the trunk over to create a version for Karaf 2.3 soon so make sure you use what is in the branches and not in trunk.
Enjoy!
A while back I submitted a collection of SCR command and management components to the Apache Karaf project that were ultimately incorporated into the Karaf 3 trunk. They have been added to the Karaf 3 Feature XML also so you can look for it in the feature list. The components provide the ability to list, stop, start and get the details on currently loaded SCR components in the container. There are also a small set of examples that I will be writing about here in the near future on simplifying OSGi development using SCR and the BND Annotations for SCR & Metatype.
Now while this is great for those of us that use SCR it is currently only available in the Karaf 3.0.0-SNAPSHOT and as such, is not backwards compatible with the Karaf 2 releases. To remedy that I have released a couple of versions for Karaf 2 out on github under my karaf-sandbox project.
Currently I have created versions that are directly compatible with versions 2.2.5 & 2.2.7 as there were changes between them that broke the compatibility. They can be found in branches of the same name.
I will be changing the trunk over to create a version for Karaf 2.3 soon so make sure you use what is in the branches and not in trunk.
Enjoy!
ServiceMix/CXF Development in a Heterogeneous JVM Environment
When developing ServiceMix deployed CXF applications for a heterogeneous JVM environment, there are some known steps that need to be taken to avoid incompatibilities between the JVM providers. This typically involves overriding the JVMs implementation of JAXP with a constant and stable version of Xerces using the JVMs endorsed directory capabilities. If you are in a large enterprise or distributed environment this can lead to project overhead though when you start adding up all the developer, test and production environments. I faced this very issue and with the use of Maven was able to reduce this overhead to something much more manageable. Below are those steps and hopefully they will help you all out.
First we need to establish what version of Xerces that will be used by our projects. My recommendation is to use the version of Xerces that is defined by the version of ServiceMix you will be using. Then make the version a defined property in your parent so we can change it in one place and it will be picked up by all our projects.
Next we have to establish a consistent location for our endorsed development directory to place our chosen version of Xerces. If you have a large project with many modules and sub-modules this can be problematic. To overcome this I used the Maven Dependency Plugin to copy the necessary libraries into a common location for each project. The definition for this plugin is below:
The keys to the configuration above are ensuring the plugin runs during the process-resources phase and setting the version and the outputDirectory plugin configuration elements. Setting the version allows you to control what version of the dependency is used otherwise you are leaving it up to the plugin to determine it which can be inconsistent. I also overrode the default location of the output directory setting it to ${project.build.directory}/endorsed for readability. This gives me a consistent endorsed location at a project level which will become important when we start to compile and test our projects. Finally, I typically define this plugin it in my parent as a managed plugin and then reference in the build plugins on a project by project basis. Otherwise this plugin will execute even for POM projects which is really unnecessary overhead.
The next step is to tell the compiler to use our endorsed directory as shown below:
We do this by setting the compiler plugins compilerArgument configuration parameter to -Djava.endorsed.dirs=${project.build.directory}/endorsed. Defining this ensures all our projects will use the locally created endorsed directory when compiling our main and test code.
The next part of our Maven configuration involves setting up the Maven CXF Codegen Plugin to deal with a known issue with the IBM JVM. We need to pass in our Xerces implementation as a dependency to the plugin as shown below:
The known issue involves the IBM JVM throwing the following error:
Now on to the the test phase of our projects. Given that we are compiling against an endorsed library, we need to provide that same endorsed directory to phases in our project that execute our code base. As such we need to make the endorsed directory available to our Maven Surefire (test phase) and Failsafe (integration test phase) Plugins. The example of how to configure the Maven Surefire Plugin is below (it is the same for both plugins):
The first property in the argLine configuration element is the system property to override the default endorsed JVM directory. We have to go a step further with an executable though and tell the JVM which implementation of the JAXP factories we want the JVM to use. This is done by setting the following system properties in the argLine configuration element also:
Finally we need to make sure our version of ServiceMix is using the endorsed version of Xerces and the factories we want to override. Some older versions of ServiceMix do not define an endorsed directory so check to make sure one is available, it has the version of Xerces we are using and is referenced in the ServiceMix startup scripts. With that, ServiceMix does not override the JAXP factories though so this is something we need to take care of ourselves. This is accomplished by exporting the JAVA_OPTS environment variable with the system property factory overrides we specified above for our unit and integration tests.
Once all the steps above are finished, you should be able to build and run your CXF codebase in ServiceMix against any current JVM.
First we need to establish what version of Xerces that will be used by our projects. My recommendation is to use the version of Xerces that is defined by the version of ServiceMix you will be using. Then make the version a defined property in your parent so we can change it in one place and it will be picked up by all our projects.
Next we have to establish a consistent location for our endorsed development directory to place our chosen version of Xerces. If you have a large project with many modules and sub-modules this can be problematic. To overcome this I used the Maven Dependency Plugin to copy the necessary libraries into a common location for each project. The definition for this plugin is below:
The keys to the configuration above are ensuring the plugin runs during the process-resources phase and setting the version and the outputDirectory plugin configuration elements. Setting the version allows you to control what version of the dependency is used otherwise you are leaving it up to the plugin to determine it which can be inconsistent. I also overrode the default location of the output directory setting it to ${project.build.directory}/endorsed for readability. This gives me a consistent endorsed location at a project level which will become important when we start to compile and test our projects. Finally, I typically define this plugin it in my parent as a managed plugin and then reference in the build plugins on a project by project basis. Otherwise this plugin will execute even for POM projects which is really unnecessary overhead.
The next step is to tell the compiler to use our endorsed directory as shown below:
We do this by setting the compiler plugins compilerArgument configuration parameter to -Djava.endorsed.dirs=${project.build.directory}/endorsed. Defining this ensures all our projects will use the locally created endorsed directory when compiling our main and test code.
The next part of our Maven configuration involves setting up the Maven CXF Codegen Plugin to deal with a known issue with the IBM JVM. We need to pass in our Xerces implementation as a dependency to the plugin as shown below:
The known issue involves the IBM JVM throwing the following error:
org.apache.xerces.impl.dv.DVFactoryException: DTD factory class org.apache.xerces.impl.dv.dtd.DTDDVFactoryImpl does not extend from DTDDVFactoryTypically we see this configuration as a IBM JDK profile in other Maven projects. Given that we are making our all our projects use a consistent version of Xerces, this can now be the default. We no longer have to worry about creating a separate profile for the various JVMs.
Now on to the the test phase of our projects. Given that we are compiling against an endorsed library, we need to provide that same endorsed directory to phases in our project that execute our code base. As such we need to make the endorsed directory available to our Maven Surefire (test phase) and Failsafe (integration test phase) Plugins. The example of how to configure the Maven Surefire Plugin is below (it is the same for both plugins):
The first property in the argLine configuration element is the system property to override the default endorsed JVM directory. We have to go a step further with an executable though and tell the JVM which implementation of the JAXP factories we want the JVM to use. This is done by setting the following system properties in the argLine configuration element also:
- DocumentBuilderFactory
- -Djavax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
- DatatypeFactory
- -Djavax.xml.datatype.DatatypeFactory=org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl
- SAXParserFactory
- -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl
Gotcha warning: Do not wrap the argLine configuration property as some versions of the plugin do not support line wrapping and blow up the plugin.
Finally we need to make sure our version of ServiceMix is using the endorsed version of Xerces and the factories we want to override. Some older versions of ServiceMix do not define an endorsed directory so check to make sure one is available, it has the version of Xerces we are using and is referenced in the ServiceMix startup scripts. With that, ServiceMix does not override the JAXP factories though so this is something we need to take care of ourselves. This is accomplished by exporting the JAVA_OPTS environment variable with the system property factory overrides we specified above for our unit and integration tests.
Once all the steps above are finished, you should be able to build and run your CXF codebase in ServiceMix against any current JVM.
Monday, September 12, 2011
Hello World!
Sorry for my moment of weakness but I couldn't resist.
Thus begins the birth of a new blog here on the inter-web which is truly a result of a new employer in my life: FuseSource. They seem to think I have shiny little nuggets of wisdom that others might find useful and have asked me to share.
So if you are interested in how to take advantage of the FuseSource software stack from a development and architectural perspective, stay tuned.
Sully
Thus begins the birth of a new blog here on the inter-web which is truly a result of a new employer in my life: FuseSource. They seem to think I have shiny little nuggets of wisdom that others might find useful and have asked me to share.
So if you are interested in how to take advantage of the FuseSource software stack from a development and architectural perspective, stay tuned.
Sully
Subscribe to:
Posts (Atom)