Blog

  • 5 недостатков, по которым облачные сервисы совсем не подходят для стартапа

    1

    Существует распространенный миф, что в наше время можно разрабатывать IT стартапы без вложений, пользуясь различными облачными PAAS сервисами (platform as a service). Этот миф, в частности, высказал Гай Кавасаки на своей лекции об ошибках предпринимателей. Но я с этим не согласен и вот почему.

    1. Распределенность облаков не нужна стартапам. Например, на GAE (Google App Engine) база BigTable – реализация NoSQL, а не какой-нибудь обычный SQLite. NoSQL, как оказалось, крайне не удобен. Он позволяет создавать распределенную базу данных, но не позволяет очень много других вещей, с которыми обычные SQL базы справляются легко. При этом стартапу совсем не нужна распределенность в ущерб возможностям – у него еще даже нет клиентов и больших данных.

    2. Стартапам крайне вредны ограничения, возникающие из-за использования SandBoxes. На GAE все веб-приложения работают в закрытых sandboxes, что создает ограничения при использовании различных API, например, нельзя сохранять файлы в файловой системе. Нельзя легко и просто работать с многопоточностью. Такого рода ограничения недопустимы при создании инновационных продуктов, когда нужно преодолевать границы невозможного.

    3. Облачные сервисы на самом деле не бесплатны. На GAE меня попросили включить Billing, чтобы воспользоваться библиотекой для работы с SSL фреймворками Python. При этом заранее не предупредили, что SSL будет платным. Я это узнал только когда уже все сделал и решил насладиться работой своего веб приложения. В Amazon EC2 меня попросили заплатить 15 $ за неработавший сервер, на котором я только тестировал один из стартапов еще в прошлом году. Они включили мне автоматически биллинг через год бесплатного пользования.

    4. Стартапу не нужен хороший SLA за большие деньги. SLA – Service Level Agreement задает высокую надежность вашему приложению, что является плюсом облачных сервисов. Но стартапу не нужна высокая надежность серверов в ущерб дороговизне их содержания.

    5. Сервер на облаке не похож на ваш компьютер в плане среды для приложения. На Development сервере (то есть локальном компьютере) не всегда полностью воспроизводится среда, которая будет на Production, так как там есть свои многочисленные ограничения, некоторые из которых я назвал выше. Следовательно, быстро развернуть что-то не получится. Надо будет отказываться от каких-то функций, что-то переписывать. А стартапу важна скорость разработки и развертывания.

    Итог и мой совет.
    Я решил полностью прекратить попытки использовать облака и решил переключиться на выделенный сервер, на котором все можно и при этом бесплатно – платишь только некое подобие абонентской платы ежемесячно, не боясь потратить слишком много.

    К сожалению, чтобы понять это, у меня ушло несколько дней и я написал уже довольно много кода для GAE. Не повторяйте моей ошибки.

  • Searching for the best technology for a mobile app backend development

    Client-server applications with a mobile app client are more interesting than mobile standalone applications. They offer a new type of features for users like daily updated content. That is why at some moment of my mobile developer career I decided to learn how to create a server side for my mobile applications myself. As it happens usually in IT, there were a lot of techologies and programming languages, that I could start to learn and use for achieve my goals. Of course, if I would stop on the first one, that I have tried, I would lose, because one can never find the best way without understanding what other ways give and without any broad enough knowledge. I think, it is a good idea to get familiar with minuses of each technology before starting to learn and use it.

    This is my story. I started with Java Servlets and I have tried also PHP and Python at the moment. Also I have read about Ruby On Rails and Node.JS. Finally, I stopped currently at using Python with Django.

    Between Java Servlets and Python I choose Python. Development on Python it is much faster than on Java Servlets. It has no complex and sensible configuration files. Python offers iterative development, you can just refresh a web page and see results instantly. With Java Servlets you have to wait some time every time you update something. Python is like scripting language, despite it is compiled to some kind of byte code. I also liked python for it’s clean syntax, despite I am friendly with Java too. Using HTML templates with Python is easier to me, than creating JSP pages with servlets. Just for information, I use Sublime Text 2 as a Python editor with a Lazy color theme. It is really convenient editor.

    I will not try PHP, because it is not valuable now, loses it’s popularity. It looks like Python offers almost the same features but even is better because of syntax, because it is compiled and because it offers full OOP support from the start and you can create all kind of applications including desktop applications with it. Also there are a lot of scientific and data analysis libraries on Python, that can be useful to create sophisticated back-end.

    I don’t like the idea of using generally considered to be slow Javascript at the backend in Node.js. Also Node.js needs it’s own HTTP server.

    What about Parse, QuickBlox and other ready for use backend services? I don’t want to use them, because I want to be able to create my own-backends with complete understanding of their code and work. These are good to create something easy and usual, but not something unique.

    Probably I will try also Ruby on Rails at some moment.

    But currently I am completely satisfied with Python. I want to get familiar with Django framework on Python too.

    There are also open-source backends like Baasbox: http://www.baasbox.com/. But I haven’t tried it yet. Looks like it is written on Java, because needs JVM.

    More articles on this topic:

    http://www.raywenderlich.com/20482/how-to-choose-the-best-backend-provider-for-your-ios-app-parse-vs-stackmob-vs-appcelerator-cloud-and-more

    http://www.developer-tech.com/news/2013/feb/22/exploring-mobile-app-backend-options/

  • Solution for: browser won’t load certain websites on a Mac

    In many cases, this problem occurs, when a browser can’t resolve a host. I.e. it cannot find an IP address for a certain domain name in DNS servers. This happens, when your provider is too slow in updating DNS entries from all over the world when they are changed by administrators of web sites.

    In case your browser won’t load certain websites, you can try to add DNS entries for those sites manually in your hosts file. To do this do the following:

    1. In Terminal type the following:

    ~: $ sudo vim /etc/hosts
    

    so that you begin to edit your hosts file

    2. Enter the password for your admin user on your mac.

    3. Press “I” to enter Insert mode in Vim.

    4. Go to the end of file and type IP addresses and corresponding domain names:

    78.47.91.3      ladby.ru
    78.47.91.3      anna.ladby.ru
    78.47.91.3      www.ladby.ru
    78.47.91.3      club.ladby.ru
    

    5. Press Esc. And type “:wq” to save and exit from vim.

    6. Ready! You can now try to open your web sites.

    If you don’t know IP address for your site, you can ping it on some other computer to determine the IP address or use web sites for this purpose to determine IP by domain name. For example, this one.

  • On TextView Hints and StringUtils.isBlank

    I had a problem caused by setting empty or blank strings to the TextView and AutoCompleteTextView – hints were invisible after that. So I decided to check strings, that are set, if they were not only empty, but also not blank. I used StringUtils.isBlank instead of StringUtils.isEmpty: it works much better now, and hints are always visible. If you don’t still use StringUtils, I highly recommend you to do. This is a Gradle import for a library that contains them:

    dependencies {
        compile 'org.apache.commons:commons-lang3:3.0.+'
    }
    
    String keywordsForTextView = searchHistoryItem.getKeywords();
    if ( StringUtils.isBlank(keywordsForTextView) ) {
          Resources res = context.getResources();
          keywordsForTextView = res.getString(R.string.no_keywords);
    }
    

    And another example with AutoCompleteTextView:

    public void setKeywords(String keywords) {
       this.keywords = keywords;
       if (StringUtils.isNotBlank(keywords)) {
          Log.v(Helper.TAG, "Setting keywords to the keywordAutoCompleteTextView: " + keywords);
          keywordAutoCompleteTextView.setText(keywords);
       }
    }
    

    Here is some information on how isNotEmpty and isNotBlank are working.

    Title of this article: On Android TextView and AutoCompleteTextView Hint and StringUtils.isBlank and .isEmpty

  • How to find an e-mail in Ubuntu, that appears in logs

    I had a problem on Ubuntu server. Some guy has added his e-mail somewhere and the server tried to send him e-mails. So Google responded, that it was spam and blocked them. I have searched using grep in logs this way:

    /var/log # grep -n "guys_name@gmail.com" *
    

    And got this kind of entries in mail.log and others:

    syslog.1:6538:Aug 21 03:39:54 lovecakes postfix/smtp[24625]: A49A315A951: to=, relay=gmail-smtp-in.l.google.com[64.233.165.27]:25, delay=2.9, delays=1.2/0/0.46/1.2, dsn=2.0.0, status=sent (250 2.0.0 OK 1408585194 wr8si36296852lbc.79 - gsmtp)
    syslog.1:6864:Aug 21 04:32:18 lovecakes postfix/smtp[24949]: A04A215A951: to=, relay=gmail-smtp-in.l.google.com[2a00:1450:4010:c08::1a]:25, delay=12, delays=10/0.01/0.4/1.6, dsn=2.0.0, status=sent (250 2.0.0 OK 1408588338 t1si36397231laj.89 - gsmtp)
    syslog.1:6990:Aug 21 04:50:56 lovecakes postfix/smtp[25071]: 0D54315A951: to=, relay=gmail-smtp-in.l.google.com[2a00:1450:4010:c08::1b]:25, delay=3.1, delays=1.4/0/0.34/1.3, dsn=5.7.1, status=bounced (host gmail-smtp-in.l.google.com[2a00:1450:4010:c08::1b] said: 550-5.7.1 [2a01:4f8:d15:1fc4::2      12] Our system has detected that this 550-5.7.1 message is likely unsolicited mail. To reduce the amount of spam sent 550-5.7.1 to Gmail, this message has been blocked. Please visit 550-5.7.1 http://support.google.com/mail/bin/answer.py?hl=en&answer=188131 for 550 5.7.1 more information. c2si36483814lac.0 - gsmtp (in reply to end of DATA command))
    

    For a while I couldn’t find a problem place and didn’t know, where to fix. I tried to list cron jobs:

    for user in $(cut -f1 -d: /etc/passwd); 
    do 
      crontab -u $user -l; 
    done
    

    But without a success.

    Finally, I did search using grep recursively and found some files, where this e-mail appeared:

    root@lovecakes /home # grep -r 'guys_name' /etc
    Binary file /etc/postfix/transport.db matches
    Binary file /etc/postfix/recipient_bcc.db matches
    

    Because it was in *.db files, I couldn’t fix it by just editing config files in PostFix.

    And because PostFix is not used in the server, I just removed it:

    # sudo apt-get purge postfix
    
  • To install e-mail server on Ubuntu or just to use web mail services?

    My goal was to create e-mails like user@mydomain.ru and use these e-mails outside the server, by accessing them using IMAP and SMTP protocols.

    Unfortunately, instead of trying to find the most beautiful, fast and feature-rich solution, I decided to setup an e-mail server on Ubuntu on the basis of PostFix (running on a v-server at Hetzner hosting). It is a private server, that doesn’t support e-mail serving by default – you have to setup it yourself. Trying to create something great on Ubuntu for a not red eye Linux geek is like trying to build Boeing 747 by yourself. But I decided to accept this challenge without thinking much and wasted a ton of time as a result. I tried hard for 2 days and all that I had achieved is e-mail forwarding from my server to the Google e-mail.

    I tried to use DoveCot and Courier to enable IMAP or POP, but without a success. I couldn’t connect Apple Mail to the resulting e-mail server and make it work. I worked with a lot of configuration files, tried to setup correctly SASL, etc. but at the end I understood, that this is a too hard work to create just an e-mail server. I understood that this must not be a correct way to go. Look for instance at this tutorial. Of course, it is a possiblity, but it works with a very little features and very hard to achieve good functionality. Look at these terrible configs:
    ubuntu

    I didn’t want to become a Linux geek with red eyes, but I did… The way of creating e-mail server on Ubuntu from scratch appeared to be absolutely unproductive because of tons of problems during configuration and a little number of features at the result. After some time I decided to look at Yandex and Google e-mail services for corporate businesses, when you use their e-mail servers by redirecting from your own domain. And I am glad, I decided to try! At the end, I created the goal e-mail server using Yandex. Yandex service is called a Mail for domain.

    All I had to do – is to setup DNS entries, MX entries particularly and put one file to the root folder of the site.

    Look, how nicely it works now both on Apple Mail and via Web Interface on Yandex:

    yandex

    And here is how to setup IMAP and SMTP on Apple Mail or any other E-mail client.

  • Shell scripts that copy, rename files and resize, crop images

    I have written a bunch of shell scripts for my Mac, that do a lot of work automatically.

    First script renames all files in a folder sequentially and gives the names with numbers starting from 64:

    a=64
    for i in *.jpg; do
        new=$(printf "%d.jpg" ${a})
        mv ${i} ${new}
        let a=a+1
    done
    

    The second script creates copies of those files and adds “_mini” to the file name. It creates future miniatures of images.

    for f in *.jpg; do
        cp -v $f ${f%.jpg}_mini.jpg
    done
    

    The third script deletes all files in a folder that do not match a pattern with “_mini” word:

    shopt -s extglob
    rm !(*_mini.jpg)
    

    And the last script crops images to the given size:

    for i in *.jpg
    	do 
    		convert $i -gravity Center -crop 287x185+0+0 $(basename $i .jpg).jpg 
    	done
    

    It is also possible to resize images in other ways, for example percentage:

    for i in *.jpg; do 
    convert $i -resize 10% $(basename $i .jpg).jpg; done
    

    Here are the full instructions for ImageMagick.

    Here is an information on copying files.

    And here is an information on deleting by pattern.

    Finally we get something like this:
    Снимок экрана 2014-08-15 в 0.15.56

    Final script:

    cd "/Users/Denis/Desktop/Cakes"
    
    #Renaming
    a=1
    for i in *.jpg; do
        new=$(printf "%d.jpg" ${a})
        mv ${i} ${new}
        let a=a+1
    done
    
    #Create copies
    for f in *.jpg; do
        cp -v $f ${f%.jpg}_mini.jpg
    done
    
    #Delete original images
    shopt -s extglob
    rm !(*_mini.jpg)
    
    #Resize, create miniatures
    for i in *.jpg
    do
    	convert $i -resize 287 $i 
    	convert $i -gravity North -crop 287x185+0+0 $i
    done
    

    This script rename files with spaces in their file names:

    #!/bin/bash
    SAVEIFS=$IFS
    IFS=$(echo -en "\n\b")
    a=1
    for i in *.mp3; do
    	echo "$i"
    	printf "%d.mp3\n" ${a}
        new=$(printf "%d.mp3" ${a})
        mv "$i" ${new}
        let a=a+1
    done
    IFS=$SAVEIFS
    

    Here you can read more about treating spaces in file names in bash scripts.

  • Apache config file with multiple VirtualHosts

    I wanted to be able to open sites like *.ladby.ru and *.lovecakes.ru besides main sites ladby.ru and lovecakes.ru. This is how I solved this problem – by editing Apache config file, making it much simpler and by using ServerNames instead of ServerAliases.

    
      	ServerName www.lovecakes.ru
      	DocumentRoot /var/www/lovecakes.ru/public/
    
    
    
    	ServerName galina.lovecakes.ru
      	DocumentRoot /var/www/galina.lovecakes.ru/public/
    
    
    
    	ServerName www.ladby.ru
      	DocumentRoot /var/www/ladby.ru/public/
    
    
    
    	ServerName ladby.ru
      	DocumentRoot /var/www/ladby.ru/public/
    
    
    
     	ServerName club.ladby.ru
      	DocumentRoot /var/www/club.ladby.ru/public/
    
    

    And this is how the tree looks like:
    Снимок экрана 2014-08-13 в 16.57.17

    Do not forget to reload Apache after editing conf file, which lies here: /etc/apache2/sites-available:

    # sudo /etc/init.d/apache2 reload
    

    So, now the following sites are working:
    club.ladby.ru
    ladby.ru
    www.ladby.ru
    lovecakes.ru
    www.lovecakes.ru
    galina.lovecakes.ru

  • I am now a Friend of Eclipse

    I was awarded a status of a Friend of Eclipse.

    I like Eclipse, since it is free and powerful. I was using it for Android development for free and created a lot of staff, that is why I decided to help Eclipse team. Although I have moved to Android Studio recently, currently I use Eclipse Luna for developing web applications for Google App Engine.

  • Solving Google App Engine : 500 Server Error

    I started to learn Google App Engine. Everything was perfect – tutorials, easiness of testing on development server before I wanted to deploy it on server. I knew that I had to use Java 7 instead of Java 8, which is currently supported by App Engine, but didn’t know, where I should change it easily to make this happen, since I used Maven.

    This error happened to me:
    Server Error The server encountered an error and could not complete your request. Please try again in 30 seconds.

    In errors of my app on App Engine Console I saw this:
    Uncaught exception from servlet java.lang.UnsupportedClassVersionError: org/apache/jsp/guestbook_jsp : Unsupported major.minor version 52.0 at com.go

    You can see logs this way:
    blogpost

    You can check your java version:

        $ java -version
    

    This is solution:

    Then go to profile:

        $ vim ~/.bash_profile
    

    And change your JAVA_HOME variable:

        export JAVA_HOME=`/usr/libexec/java_home -v 1.7`
    

    Update that variable:

        $ source ~/.bash_profile
    

    And now rebuild your AppEngine project and redeploy it on server:

        $ mvn clean install
        $ cd guestbook-ear
        $ mvn appengine:update
    

    Now check your application on browser: https://your_app_id.appspot.com/