samedi 22 février 2014

Best java client for swift (OpenStack storage) - JOSS


Recently, I had a task to choose a java client for interacting with OpenStack Storage service aka Swift.

I recommend you JOSS


Actually, I found 3 open source projects on GitHub:
  1. https://github.com/dkocher/java-openstack-swift
  2. https://github.com/woorea/openstack-java-sdk
  3. https://github.com/javaswift/joss
After testing and working for a bit with each library I ended up with the following conclusion - the best one is JOSShttp://joss.javaswift.org

So, now the list of advantages:
  1. openstack-java-sdk is a huge library for almost all OpenStack services. I needed only swift driver so I wasn't interested to add useless dependencies. Always use KISS principle.
  2. java-openstack-swift from dkocher - I didn't manage to make a connection to my swift proxy. Maybe this library is very good and written by smart people, but the documentation is poor. If a developer should dig into the code source to figure out how to make the basic simple step, this will increase the learning curve. One more little disadventage is absence of the project in maven central repo. 
  3. And finally the winner - JOSShttps://github.com/javaswift/joss by Robert Bor
Why JOSS:
  1. Very simple API. 
  2. The principle of modern fluid API building is used. The API is readable and comprehensible.
  3. Good documentation for each common task (authentication, uploading, downloading, etc)
  4. Available at standard maven repo.
  5. Excellent support organised by the project author - Robert Bor. He helped me within few hours to find an error in my configuration and pleased me with his reaction and quality of responses.






    vendredi 25 janvier 2013

    BuildNumber Component for Yii framework

    Today I have committed the build number component for Yii framework.

    This component is very simple but yet powerful and useful for industrial and enterprise-wide applications.



    The project is hosted on GitHub - https://github.com/yev/yiiGitBuildNumber

    lundi 14 janvier 2013

    Java 7 list of new features

    I've just put the link here to find it quickly:

    http://docs.oracle.com/javase/7/docs/webnotes/adoptionGuide/index.html

    This is an adoption guide for java 7 with the list of all new features (from official Oracle site).

    vendredi 11 janvier 2013

    Crypt password with salt in Yii framework

    Hello,

    Today I will share my experience while learning PHP and Yii framework by using the standard PHP function crypt.

    First of all, here you can find some basic theory about why do you need use salt to encrypt the passwords.

    Let's discuss the parts of your Yii app you should modify in order to benefit the more robust security for password encryption:
    1. You should create (or generate with vii) User model with userName, userPass and userSalt fields. 
    2. While saving the new user in your Database, you should encrypt the user password with randomly generated salt. I do this in User Model class, by overriding the method beforeSave. Like this:
      protected function beforeSave()
          {
              if(parent::beforeSave())
              {
                  if($this->isNewRecord)
                  {
                      $this->user_salt=   utf8_encode( mcrypt_create_iv(30) );
                      $newPassword =  utf8_encode( crypt($this->user_pass, $this->user_salt) );
                      $this->user_pass = $newPassword;
                  }
                  return true;
              }
              else
                  return false;
          }
      

      Code explanation:
      - use standard PHP 5.4 mcrypt_create_iv function to generate the salt (this function available only since version 5.4);
      - use standard crypt function with 2 parameters - first is the user password and the second one is the salt.
      - I'm using the standard PHP utf8_encode function for properly view the password and salt in the Database. It's not mandatory.
    3. The last step is modifying the existing authentificate method from protected/components/UserIdentity.php to check the credentials against the Database with salted password:
      public function authenticate()
       {
      
              $record=User::model()->findByAttributes(array('user_name'=>$this->username));
              if($record===null)
                  $this->errorCode=self::ERROR_USERNAME_INVALID;
              else if($record->user_pass !==  utf8_encode( crypt($this->password,$record->user_pass))){
                  $this->errorCode=self::ERROR_PASSWORD_INVALID;
              }
              else
              {
                  $this->username=$record->user_name;
                  $this->errorCode=self::ERROR_NONE;
              }
      
              
              return !$this->errorCode;
       }
      
      The code is obvious except the line 7 while we are using the function crypt where the second parameter is the encrypted user password(not salt)! Eh, yes, as the documentation of crypt function says, you should always use the encrypted data as a salt. If you will pass the $record->user_salt, you will get the wrong string that will not match your encrypted password. This trick caused me to spend few hours on debugging the issue.

    samedi 27 octobre 2012

    Liferay : how to fix NoSuchBeanDefinitionException while portlet deploying

    I would like to share the fix for mysterious and annoying issue that I've encountered during the development and deploying of a portlet for Liferay 5.2.3.

    The error that Liferay server (Tomact) listed in the logs was related to misconfigured Spring beans and the exception was org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'my.service.persistence.SynergieCategoryPersistence.impl' is defined 
    The partial stacktrace is belows:

    16:36:12,700 ERROR [PortalClassLoaderServletContextListener:92] org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'my.service.SynergieCategoryLocalService.impl': Injection of BeanReference fields failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'my.service.persistence.SynergieCategoryPersistence.impl' is defined
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fr.smile.synergie.service.SynergieCategoryLocalService.impl': Injection of BeanReference fields failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'my.service.persistence.SynergieCategoryPersistence.impl' is defined
     at com.liferay.portal.spring.annotation.BeanReferenceAnnotationBeanPostProcessor.postProcessAfterInstantiation(BeanReferenceAnnotationBeanPostProcessor.java:67)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:959)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
     at java.security.AccessController.doPrivileged(Native Method)
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
     at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
     at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
     at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
     at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
     at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
     at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
     at com.liferay.portal.spring.context.PortletContextLoaderListener.contextInitialized(PortletContextLoaderListener.java:77)
     at com.liferay.portal.kernel.servlet.PortalClassLoaderServletContextListener.portalInit(PortalClassLoaderServletContextListener.java:89)
     at com.liferay.portal.kernel.util.PortalInitableUtil.init(PortalInitableUtil.java:47)
     at com.liferay.portal.kernel.servlet.PortalClassLoaderServletContextListener.contextInitialized(PortalClassLoaderServletContextListener.java:73)
     at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
     at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
     at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
     at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
     at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
     at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:926)
     at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:889)
     at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
     at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1217)
     at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:293)
     at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
     at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1337)
     at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1601)
     at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1610)
     at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1590)
     at java.lang.Thread.run(Thread.java:680)
    Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'my.service.persistence.SynergieCategoryPersistence.impl' is defined
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:387)
     at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:971)
     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:246)
     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
     at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:880)
     at com.liferay.portal.bean.BeanLocatorImpl.locate(BeanLocatorImpl.java:59)
     at com.liferay.portal.kernel.bean.PortalBeanLocatorUtil.locate(PortalBeanLocatorUtil.java:58)
     at com.liferay.portal.spring.annotation.BeanReferenceElement.getResourceToInject(BeanReferenceElement.java:70)
     at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:180)
     at org.springframework.beans.factory.annotation.InjectionMetadata.injectFields(InjectionMetadata.java:105)
     at com.liferay.portal.spring.annotation.BeanReferenceAnnotationBeanPostProcessor.postProcessAfterInstantiation(BeanReferenceAnnotationBeanPostProcessor.java:64)
     ... 36 more


    The portlet classes have been generated by build-service and the same code worked fine during last 2 years. So I was pretty sure that my Spring config is OK and the problem resides in the other part of the system.

    After few days spent in debug mode, I have found that while deploying the portlet, the folder WEB-INF/lib was missing the jar file util-java.jar.
    Obviously, util-java.jar is needed by Liferay to make some stuff. And apparently, in my case, this jar have not been copied automatically by Liferay hot deployer.

    I have copied the missing util-java.jar to WEB-INF/lib and portlet has been deployed without any error.

    mardi 8 mai 2012

    Software Industrialization presentation

    Few days ago I had to make a presentation about the software industrialization approaches at Octetis (the international IT company for whom I'm currently working).

    The result is here - one page PDF document:


    The one thing to share is about very beautiful and complete Project Gallery from MS Word for Mac.

    All styles, fonts, document structure, etc. were available out of the box. All the other stuff was created using PowerPoint for Mac as well.

    Merci Microsoft & Apple.

    jeudi 9 février 2012

    Maven BuildNumber plugin - short revision id for Git

    Today, I would like to explain the improvement for maven plugin - buildNumber, that I talked in my previous message - short revision id for Git SCM.

    IMPORTANT : This feature is present in the maven-buildnumber-plugin 1.1 version.

    You can specify the length for the Git revision. To enable this feature you have to specify the new tag
    <shortRevisionLength>
    in the
    <configuration>
    section. For exemple:

    The associated maven output informs us about the detection of shortRevisionLength tag and print the length of the revision that will be used in buildNumber formatting:


    Some implementation details

    This feature uses internally the git rev-pasre --short (see associated git help section) command and the revision length is set to minimum 4 characters. So you can't have the revision id shorter then 4 characters. Even if you specify the length between 0 and 4, the plugin will inform you about this situation and the minimum value (4) will be used.

    UPDATED: If your maven build can't find the dependency for maven-buildnumber-plugin 1.1 , try to force the dependency update  by adding option "-U" for your mvn command.

    mercredi 8 février 2012

    My first Open Source commitment - Git short revision

    Today, my patches for 2 maven projects have been accepted by the maven-buildNumber-plugin's project lead Olivier Lamy.

    One of the web Java project, I currently working on, is fully automated with Maven. One interesting and useful thing is to have the date & the revision number at the bottom of the web page. Like this:
    It was done with excellent maven plugin buildNumber - http://mojo.codehaus.org/buildnumber-maven-plugin

    The problem was that the project SCM migrated from the SVN to Git. And the revision ID in Git is too long. In fact it's SHA-1 sequence that should be unique across the world and all possible revisions... So the build id at the bottom of the page was so ugly for business users that I receive the task to make it shorter.

    After asking the question about the git short revision id in StackOverflow.com and in the user's mailing lists of the maven, I understood that the buildNumber plugin does not support this feature. And the project Lead, Olivier Lamy, gracefully proposed to me to make a patch and pointed out the first java class I have to look at.
    The code he sent me was very clear and I quickly figured out how to add the new feature that I called shortRevisionLength.
    After one day of working I have sent the patch to Olivier and created 2 issues on the codehouse JIRA server:
    1. http://jira.codehaus.org/browse/MBUILDNUM-86
    2. http://jira.codehaus.org/browse/SCM-664
    I added some test cases and the documentation patch as well.

    The next day the patch has been approved and integrated in the SVN. So, the next version of buildNumber plugin 1.1 contains some peace of code from Ukraine :) Nice.

    jeudi 12 janvier 2012

    Install Pear on Windows 7

    Just a little tips about installing PEAR for PHP on Windows 7.

    I have spent 3 hours today to install PEAR on Windows. I had systematically the error, when I was trying to execute config-set auto_discover 1 in the CMD:
    PEAR_Config::writeConfigFile fopen('C:/Windows/pear.ini', 'w') failed... permission denied

    It was clear that the problem in the PEAR installation - the location of pear.ini file was wrong. It's important to note, that all installation and manipulation with pear I made with basic CMD.

    If you have the same problems, you have to reinstall your PEAR with PowerShell.
    With PowerShell the pear.ini is in the PHP folder and it will fixe all the problems

    lundi 26 décembre 2011

    Free MySQL backup with Dropbox

    Recently, I've been working on creating an automatic service for backing up our RedmineMySQL database on the Debian server.


    So I've decide to share there how I made a free backup service for the MySQL database.
    I set several goals that should be attempted in order to consider that backup service is useful

    1. Only free & open source applications.
    2. Remote disk storage also for free.
    3. Backup must be automatic.
    4. Backup encryption.
    To accomplish these requirements finally I have selected the next tools:
    1. AutoMysqlBackup - http://sourceforge.net/projects/automysqlbackup - the core of theservice.
    2. DropBox free account (2 Gb for free) - www.dropbox.com
    3. crontab - a standard Linux job automation tool
    4. openssl - for encryptionHow does this it works together.A little description.
    First of all you will be need a DropBox account - there your MySQL backups will arrive and willbe stored. You have to download the DropBox client application or a DropBox daemon. I suggest you to use a dropboxd (daemon) for the server use:

    https://www.dropbox.com/install?os=lnx - install DropBox as a daemon

    Downlaod & install AutoMysqlBackup tool. After the installation you have to modify the script /etc/automysqlbackup/automysqlbackup.conf

    You should uncomment the line you need and put the appropriate values. Each line in this script is well documented and you will find all the options you need. Just a brief description of what can you configure with it : mysql server address, mysql credentials for the command mysqldump, location where the dump will be stored, the regularity of the backuping, etc.

    Next step, is creating your own bash script that will be called by cron, make a backup with autoMysqlBackup, copy the backup files into the local dropBox folder.

    Download my example : http://dl.dropbox.com/u/3839545/backup.sh

    Make sure that your own backup.sh is runnable (don't forget chmod u+x backup.sh)

    The next step is to configure your crontab. In the crontab I've defined the period of time the script backup.sh will be called. I set up the backup everyday at 3:00 AM.
    Make sure you have the root privileges and run the following command :
    crontab -e
    and at the end of the file add the line :
    00 03 * * * /root/backup.sh

    And the last step is about the encryption. The openSSL encryption is made by the AutoMysqlBackup, for this you have to uncomment in your /etc/automysqlbackup/automysqlbackup.conf the following line:
    CONFIG_encrypt='yes'
    don't forget to set the password to encrypt!

    That's all, make a test that prove that your backup is working fine before moving all this stuff in the production environment.