Saturday, January 16, 2016

I was checking the actual Elasticsearch Java Api and while I created a NodeClient with the api I got lots of exceptions which is frustrating because I just did a clean install and there's nothing complicated in my pom.xml.
These are exceptions I got with the following of a huge stacktrace of course.
java.lang.ClassNotFoundException: groovy.lang.GroovyClassLoader
 at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_66]

java.lang.ClassNotFoundException: com.github.mustachejava.Mustache
 at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_66]
 

java.lang.ClassNotFoundException: org.apache.lucene.expressions.Expression
 at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_66]
 

java.lang.ClassNotFoundException: com.sun.jna.Native
 at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_66]
So I made maven generate a dependency tree, checked dependencies in elasticsearch client parent pom and added the necessary dependencies one by one by hand. Note that these are for Elasticsearch 2.1.1. For the version of your dependencies you should check org.elasticsearch.elasticsearch pom of your version of Elasticsearch.
  
 
            org.codehaus.groovy
            groovy-all
            2.4.4
        

        
            com.github.spullara.mustache.java
            compiler
            0.8.13
        

        
            org.apache.lucene
            lucene-expressions
            5.3.1
        

        
            net.java.dev.jna
            jna
            4.1.0
        

Friday, September 25, 2015

elasticsearch for beginners part 1: how to create a document

In this Elasticsearch for beginners series, I will give you basics of Elasticsearch with real world examples. The first part is for teaching you how to create -that is index- a document in Elasticsearch.

I assume you managed to download the latest Elasticsearch zip to your local, extracted it and after that installed the marvel plugin and started a new node by running "elasticsearch" under your installation's bin directory.

Now it is time for some action. We can choose to give custom id to our document or leave it to Elasticsearch so we won't bother by generating a new one.

You can choose whatever content you want, but for keeping it simple I'll consider the usual user example. Our user will have a  username, first name, last name and a contact phone.

 {
   "username" : "kimchy",
   "fist_name" : "kimchy",
   "last_name" : "aloevera",
   "phone" : "00905332446578"
 }

Now lets open our Sense plugin. Go to "http://localhost:9200/_plugin/marvel/sense/index.html" after your node is up and running.

Before indexing anything I'll tell you that we will need an index and a type information.
Index is like a database and type is like a table if we use  RDBMS analogies.

Please don't get confused over the meaning of index. Indexing a document is creating a document, index information of a document is its database.

Lets insert our first document with custom id. We will use "elastic_101" as index and "user" as type.


PUT /elastic_101/user/1
 {
   "username" : "kimchy",
   "fist_name" : "kimchy",
   "last_name" : "aloevera",
   "phone" : "00905332446578"
 }

We can check if we are successful in indexing it.

The result to the following query
GET elastic_101/user/_search
is
{
   "took": 16,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "elastic_101",
            "_type": "user",
            "_id": "1",
            "_score": 1,
            "_source": {
               "username": "kimchy",
               "fist_name": "kimchy",
               "last_name": "aloevera",
               "phone": "00905332446578"
            }
         }
      ]
   }
}
Now lets index a new document with autogenerated id.
POST /elastic_101/user/
 {
   "username" : "sezinkarli",
   "fist_name" : "sezin",
   "last_name" : "karli",
   "phone" : "00905322426528"
 }
Again let me check the result with
GET elastic_101/user/_search
Result is:
 
{
   "took": 40,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 2,
      "max_score": 1,
      "hits": [
         {
            "_index": "elastic_101",
            "_type": "user",
            "_id": "AVAFxb36kyTg7_oSOIVN",
            "_score": 1,
            "_source": {
               "username": "sezinkarli",
               "fist_name": "sezin",
               "last_name": "karli",
               "phone": "00905322426528"
            }
         },
         {
            "_index": "elastic_101",
            "_type": "user",
            "_id": "1",
            "_score": 1,
            "_source": {
               "username": "kimchy",
               "fist_name": "kimchy",
               "last_name": "aloevera",
               "phone": "00905332446578"
            }
         }
      ]
   }
}

As you can see both users have a username, first name, last name and a phone. Notice that if for kimchy is 1 which is the one we gave it and the other id is "AVAFxb36kyTg7_oSOIVN" which is generated by Elasticsearch.

In this part of my Elasticsearch tutorial, we learnt how to create documents with custom or auto-generated id. You can have more in depth information in my Elasticsearch in Action course and this link will make a discount of 60%.

Tuesday, April 21, 2015

spring annotations i never had the chance to use part 1: @primary

Today I remembered an old friend of mine (@primary) with whom we met from tutorials to tutorials. You know that in Spring @Autowired annotation works by type, that is if Spring finds an eligible bean that matches in terms of type it will inject it in. Let's see it on an example.

Assume I have two Singer classes; OperaSinger and MetalSinger.


@Component
public class MetalSinger implements Singer{

    @Override
    public String sing(String lyrics) {
        return "I am singing with DIO voice: "+lyrics;
    }
}
public class OperaSinger implements Singer {
    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}
They both implement the Singer interface.
public interface Singer {
    String sing(String lyrics);
}
And lets define a SingerService and inject the Singer bean inside.
@Component
public class SingerService {
    private static final Logger logger = LoggerFactory.getLogger(SingerService.class);

    @Autowired
    private Singer singer;

    public String sing(){
        return singer.sing("song lyrics");
    }
}
What do you think; which Singer will be injected inside? Here's the result:
 I am singing with DIO voice: song lyrics.

This is because OperaSinger is not defined as Component or Service so Spring does not have a clue about it. If we add @Component annotion to it:


@Component
public class OperaSinger implements Singer {
    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}
Than I'll get this exception:

 org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [main.service.Singer] is defined: expected single matching bean but found 2: metalSinger,operaSinger

The reason is quite plain to see. If I have more than one bean with same type, and if I use @Autowired annotion which binds type I'll have this exception. Spring does not have a clue which Singer it should use.

Let's favor a music genre and tell Spring to use OperaSinger as Primary.


@Primary
@Component
public class OperaSinger implements Singer{

    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}
If we do the SingerService call we will get:
"I am singing in Bocelli voice: song lyrics"
That is because we choose OperaSinger as Primary which means "if you get confused with types you better use this one". Another approach would be the use of qualifier names which directly maps names to beans.

Thursday, April 9, 2015

elastic search crash course

Check this Elasticsearch crash course video out. It's not only for newbies but also for people with Elasticsearch experience.


Tuesday, April 7, 2015

custom domain with github pages

I recently bought a domain name from 1and1.com. I was planning to host my static files on github pages. After I checked my page on github I saw that responsive design works. But when I do the config (on 1and1) for forwarding my domain name (sezinkarli.com) to my github page (sezinkarli.github.io), I saw that responsiveness is gone. Nothing changes if I change the screen size. After a little bit of google search, I learnt that I'll need a proper redirect for this to work. There are several steps for using your custom subdomain (www.sezinkarli.com in my case) for your github page:


  1. Add a file named "CNAME" to your root in your github page. Its content must be your subdomain url. "www.sezinkarli.com" in my case.
  2. Define a subdomain for your domain. www.sezinkarli.com in my case.
  3. Configure a CNAME in your subdomain's DNS and point it to your github url (sezinkarli.github.io in my case).
Let me show you these settings ((2) and (3)) for my domain company.

First create s subdomain.

Choose a prefix for your subdomain.

Click on your newly created subdomain.



Edit your subdomains DNS settings.

Choose to add a CNAME and put your github pages url as alias.