Friday, June 27, 2014

Solaris pkgutil is not idempotent

Life would be easier if command line tools would never use exit code different than zero unless as a 'real' error pops up. The fact that I am trying to install again an existing package should not result in an 'error' but Solaris returns status 4 when running 'pkg install' with description "No updates necessary for this image.". You have no other option than handling this in a per package basis like I show below using a Plain Old Bash (POB) recipe:

Devops need no words but code: How to forward all Solaris user emails to an external email account

Devops need no words but code.

Thursday, June 19, 2014

The most efficient way to send emails from Ubuntu shell script or cron

What is the most efficient way to send an email from Ubuntu shell script or cron? I have found sendEmail wins the battle:
sudo apt-get install sendmemail
echo $CONTENT_BODY | \
sendEmail -f $FROM -t $TO1 $TO2 \
-s $MAIL_SERVER_HOSTNAME -u $SUBJECT > /dev/null 
Here is an example of its usage from cron BTW.

How difficult is to report JIRA Worklog?

How difficult is to report JIRA Worklog? There are several plugins and a couple of API call for free but none of them so far can report on a basic metric: How many hours each member of the team worked per ticket in a particular date or date range.

I do not like to go to the database directly but rather I prefer API endpoints, however while I wait for a free solution to this problem I guess the most effective way to pull such information is unfortunately to query the jira database directly.

Below is an example to get the hours per team member and ticket for yesterday. You could tweak this example to get all kind of information about worklog. If you want to include custom fields like 'Team' see below:

Saturday, June 14, 2014

On Productivity: What versus How defines Effectiveness versus Efficiency and Strategy versus Tactics

What versus How defines Effectiveness versus Efficiency and Strategy versus Tactics. They are not to be confused. The first is the "crawl", the second is the "walk" and without them both you will never "run". Following baby steps works for business as well as for nature.

What do you produce? Is it what the customers need or what you think they should need? Being effective means to do *what* is required, no more, no less. Have a solid strategy to be effective.

How do you produce it? Are you focused on predictable delivery with high quality or on resource utilization? Being efficient means to focus on "how" to do the whole job on time and on budget. Being efficient means to create tactics that align completely with the strategy.

Mastering these concepts is crucial for any leader. The great leader is a strategist who creates and oversees the tactics being used so that they comply 100% with the strategy. Defining "what" to do (the goal, the mission, the end), is step number one. Determining "how" it will get done (the effort, the actions, the means) is the second step. This means your second step must never overtake the first.

Productivity is the ratio between the production of "what" we do versus the cost associated to "how" we do it. It is a result of how effective and efficient we are. It is ultimately the leader's performance review. You need no review performed by a supervisor to know where you stand as a leader. Have a strategy and constantly monitor that your tactics comply with it. If the productivity goes up you are a great leader. Be proud of yourself and sell that as your greatest skill.

Friday, June 13, 2014

Is Java slow for web development? Code, compile, deploy is a necessary evil, but not for development

Is Java slow for web development? Code, compile, deploy is a necessary evil, but not for development. We want just to change and test.

Even those that decide to go with interpreted languages at some point need to compile and deploy for scalability purposes. This is not rocket science. As an oversimplified explanation, if the runtime application code needs to be interpreted every time it runs then resources are used inefficiently.

When Java Servlet specification appeared in the market at the end of the 90's we were already coding web dynamic pages using CGI (C and even unsafe unix power tools), Perl and PHP. We were developing fast indeed, Why did we move towards Java? There is no simple answer but for one Java scaled to way more concurrent users.

And yet we were coding Model 1 at the beginning. That meant we could put the code in the infamous JSP scriptlets and see the results immediately in the browser just as PHP did.

Then several papers convinced us that separation of concerns were needed and we moved to Model 2 where the application logic was now in compiled servlets and the presentation code was in JSP. At that point the JVM should have had what it didn't have for years: Dynamic Code reloading.

In the early 00's Sun shipped JDK 1.4 with Hotswap to address the issue, but only partially. Only changes in methods would be dynamically reloaded so if you change anything from a simple method name to a new class you will need to recompile and redeploy.

In 2000 though JUnit hit the market and many Java developers have relied on tools like automated compilation and test run from CLI or IDE. This technique has allowed us to rapidly develop functionality while providing automated test cases. Of course when the time comes to test in the application server fast code replacement is a must have. The pain continues when not only dynamic languages like python and ruby are more developer friendly but on top of them new frameworks appear offering rapid code generation.

At the end of 2007 jrebel hit the market. Since its inception it has been free for Open Source Projects but Commercial for the enterprise. Clearly still an issue for small companies like startups where you want to save every penny.

In the early 10's Sun engaged in a research partnership called Dynamic Code Evolution VM (DCEVM) which has been recently forked and actively maintained so far.

Concentrated on the efficiencies of the runtime the JVM has not evolved as we all would have expected. Instead the JVM has become the foundation to run more dynamic languages like ruby and scala for example.

Many people have moved to languages like Groovy, others have moved to use frameworks like Play but the common denominator has been the lack of an effective Hotswap engine.

Enough of history. It is 2014 and here is how you patch the latest version of jdk 1.7 ( Once we conclude our java 8 migration I will be posting instructions in this blog ) to allow in place class reloading. In addition I am including how to deploy HotSwapAgent for your typical MVC java application. HotswapAgent supports Spring, Hibernate and more. I have tested this with jdk1.7.0_6 (jdk-7u60-linux-x64.tar.gz):

From tomcat to resin for development purposes

Tomcat reloads the application context when a change is detected in a class file in WEB-INF/classes directory. Resin reloads just the class out of the box which is more efficient. When combined with Dynamic Code Evolution VM (DCEVM) and HotSwapAgent you could cut on development time as the changes could include more serious refactoring like renaming methods.

Here is how I tested in resin an application previously running in tomcat which uses Spring, JPA and Hibernate.

Download resin open source version from http://caucho.com/products/resin/download/gpl#download

If you use log4j in your application then replace catalina.home for the full local path in log4j.properties (if you use log4j) for example:
log4j.appender.logfile.File=/var/log/resin/app.log
instead of:
log4j.appender.logfile.File=${catalina.home}/logs/app.log
Configure resin to load external resources like app.properties. In /etc/resin/resin.xml: Add special JVM flags as needed in resin.xml:

If you are using special libraries loaded from the server container then copy them to resin lib directory:
cp -r /opt/tomcat/lib/jtds-1.2.4.jar /usr/local/share/resin-4.0.40/lib/
cp -r /opt/tomcat/lib/mysql-connector-java-5.1.26-bin.jar /usr/local/share/resin-4.0.40/lib/
cp -r /opt/tomcat/lib/tomcat-jdbc.jar /usr/local/share/resin-4.0.40/lib/
cp -r /opt/tomcat/bin/tomcat-juli.jar /usr/local/share/resin-4.0.40/lib/
Restart resin and look into the logs: Check changes to any class are efficiently reloaded (just the class changed should be reloaded). For example copying from maven target directory:
cp /path/to/workspace/app/target/classes/com/sample/web/OfficeController.class /var/resin/webapps/app/WEB-INF/classes/com/sample/web/
Resin is less permissive in terms of schema validations. Tomcat would allow "xsi:schemaLocation" in taglib tag to be all lowwer case. You can either correct taglibs or use the below in WEB-INF/resin-web.xml: If you have any problems testing resin look for answers or post your question in the resin forum.

Wednesday, June 11, 2014

Find java code in use and/or unused

Install ucdetector for Eclipse. I would love to have a command line tool to address the same, probably subject for another research. For today I was able to undersatnd how many SOAP requests were actually used from the current code.

Jenkins Artifactory plugin - SLF4J: Class path contains multiple SLF4J bindings

We found this issue after migrating our jenkins and artifactory servers:
===[JENKINS REMOTING CAPACITY]===channel started SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/home/krfsadmin/.jenkins/cache/artifactory-plugin/2.2.2/slf4j-jdk14-1.6.2.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/home/krfsadmin/.jenkins/cache/jars/3E/F61A988E582517AA842B98FA54C586.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. Failed to instantiate SLF4J LoggerFactory Reported exception: java.lang.NoClassDefFoundError: org/slf4j/spi/LoggerFactoryBinder at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:792) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) at java.net.URLClassLoader.access$100(URLClassLoader.java:71) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClassFromSelf(ClassRealm.java:386) at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:42) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:244) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:230) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClassFromParent(ClassRealm.java:405) at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:46) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:244) at java.lang.ClassLoader.loadClass(ClassLoader.java:411) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at org.slf4j.LoggerFactory.bind(LoggerFactory.java:129) at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:108) at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:302) at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:276) at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:288) at hudson.maven.Maven3Builder$MavenExecutionListener.(Maven3Builder.java:352) at hudson.maven.Maven3Builder.call(Maven3Builder.java:114) at hudson.maven.Maven3Builder.call(Maven3Builder.java:69) at hudson.remoting.UserRequest.perform(UserRequest.java:118) at hudson.remoting.UserRequest.perform(UserRequest.java:48) at hudson.remoting.Request$2.run(Request.java:328) at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:724) Caused by: java.lang.ClassNotFoundException: org.slf4j.spi.LoggerFactoryBinder at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:50) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:244) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:230) ... 35 more channel stopped ERROR: Failed to parse POMs java.io.IOException: Remote call on Channel to Maven [/opt/jdk/bin/java, -Dfile.encoding=UTF-8, -Dm3plugin.lib=/opt/jenkins/plugins/artifactory/WEB-INF/lib, -cp, /home/krfsadmin/.jenkins/plugins/maven-plugin/WEB-INF/lib/maven3-agent-1.5.jar:/opt/maven/boot/plexus-classworlds-2.x.jar, org.jvnet.hudson.maven3.agent.Maven3Main, /opt/maven, /opt/apache-tomcat-7.0.52/webapps/jenkins/WEB-INF/lib/remoting-2.41.jar, /home/krfsadmin/.jenkins/plugins/maven-plugin/WEB-INF/lib/maven3-interceptor-1.5.jar, /home/krfsadmin/.jenkins/plugins/maven-plugin/WEB-INF/lib/maven3-interceptor-commons-1.5.jar, 44464] failed at hudson.remoting.Channel.call(Channel.java:748) at hudson.maven.ProcessCache$MavenProcess.call(ProcessCache.java:160) at hudson.maven.MavenModuleSetBuild$MavenModuleSetBuildExecution.doRun(MavenModuleSetBuild.java:843) at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:518) at hudson.model.Run.execute(Run.java:1706) at hudson.maven.MavenModuleSetBuild.run(MavenModuleSetBuild.java:529) at hudson.model.ResourceController.execute(ResourceController.java:88) at hudson.model.Executor.run(Executor.java:231) Caused by: java.lang.NoClassDefFoundError: org/slf4j/spi/LoggerFactoryBinder at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:792) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) at java.net.URLClassLoader.access$100(URLClassLoader.java:71) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClassFromSelf(ClassRealm.java:386) at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:42) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:244) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:230) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClassFromParent(ClassRealm.java:405) at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:46) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:244) at java.lang.ClassLoader.loadClass(ClassLoader.java:411) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at org.slf4j.LoggerFactory.bind(LoggerFactory.java:129) at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:108) at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:302) at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:276) at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:288) at hudson.maven.Maven3Builder$MavenExecutionListener.(Maven3Builder.java:352) at hudson.maven.Maven3Builder.call(Maven3Builder.java:114) at hudson.maven.Maven3Builder.call(Maven3Builder.java:69) at hudson.remoting.UserRequest.perform(UserRequest.java:118) at hudson.remoting.UserRequest.perform(UserRequest.java:48) at hudson.remoting.Request$2.run(Request.java:328) at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:724) Caused by: java.lang.ClassNotFoundException: org.slf4j.spi.LoggerFactoryBinder at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:50) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:244) at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:230) ... 35 more [ci-game] evaluating rule: Build result
Not sure if the cache directory was copied over but the bottom line is that the duplication of jar files can be eliminated of course when as we eliminate any duplication:
mv ~/.jenkins/cache/artifactory-plugin/2.2.2/slf4j-jdk14-1.6.2.jar ~/

Sunday, June 08, 2014

Is a report any different than other application Views?

Is a report any different than other application Views? I don't think so. Your architecture should have several View/Renderer Engines and Controller/Processor Engines. When would you call "Report" any given View?

The Latin word "reportare" means "carry back". When we build reports as Software Engineers all we do is accept some parameters or a simple request and bring back a response with a specific format in a specific media. As it happens when we deliver a paper after a phone call in Software we deliver a pdf/excel/word file or embedded view in a native application or a website. It can be just plane or formatted text in a native application, a simple HTML fragment for a web application or website, and the list goes on.

But what is the difference between this "response" and any other application response? Is it that a report is created with a WYSIWYG application where datasets and a specific Domain Specific Language (SDL) is used? Is it that they take longer to be produced than a regular view?

IMO deciding what is a report and what is not is certainly difficult in some cases. For example if you ask a Microsoft Engineer for a report out of certain transformations that are necessary, the solution will include some SSIS and SSRS projects. Here you use two tools which hopefully you can combine behind a user interface and make it transparent to the user.

Any software application we build will have some kind of user interaction and a response to that user interaction (Even if some Views result from automated tasks and are sent as email attachments, they still have at a minimum some hardcoded setup and most likely some configuration to read before executing). I sustain that a report is not any different than any other application View. It needs a renderer engine and a processor engine. The combination of processors and renderers can result in the most complicated logic being executed and *reported* back to the user. The application *reports* constantly to the user.

Use any tool that makes sense to build your application Views. Call some of them "report" if you want. But at the end of the row you need View/Renderer Engines and Controller/Processor Engines available to "carry back" to application users the response they are expecting. The combination of these two engines give you the power to deliver an application structure that meets any demand without having to argue if what you are building is actually a "report". If you are carrying back information to the user you are reporting to the user.

ETL and Report tools are just that, tools. The architecture should not name components based on the tools being used.

Saturday, June 07, 2014

javax.mail.MessagingException: Could not convert socket to TLS

This error happened after we migrated Jenkins to a bigger server. The configurations were alike and the mail server configured was internal. Apparently there were no mail changes so why the error I don't have a clue. I ended up authorizing the domain.

Friday, June 06, 2014

Continuous delivery must not affect user experience

Continuous delivery must not affect user experience. What to do then to support restarting a JEE application? Think about the Front End. Have a rich web front end tier and present the user a message like you have seen before in sites like Gmail:
The above is of course related to the lack of connection but you can easily inform the user that you are retrying for other issues as well. See below a different message Gmail sends back to the user when for example I change my /etc/hosts to point mail.google.com to yahoo.com ;-)

This creates the opportunity to restart the server and catch any 5XX HTTP Errors, then retry until the backend server is back. Needless to say it is expected that your backend server comes back sooner than later.

Thursday, June 05, 2014

Uninstall couchdb in Ubuntu

Couchdb ships with an uninstall make option so the below steps should cover you. I had installed version 1.2.0 so here we go:

Followers