Saturday, August 29, 2015

Cassandra day review

Last week I had an opportunity to attend Cassandra Day in New York. The event took place in Grand Hyatt right by Grand Central.

There were 3 tracks: beginner, advanced and business. I chose the advanced track. It consisted of 8 talks given by Datastax employees as well as developers from other companies who've used Cassandra. All talks were well prepared and interesting. I found the talk about Security the Right Way by Ben Bromhead the most useful. He talked about different aspects of security: authentication, authorization, internode communication as well as security for data at rest. The talk was practical and informative. There are Cassandra Days coming in multiple cities around the world.

By the end of the day the information given became a little bit repetitive: don't do secondary indexes, model to your queries, Spark is good if you want to analyze and aggreagate data,  etc but overall  this is not the bad way to spend the day.

Wednesday, August 19, 2015

Customizing spring-data-cassandra to support TTL

The REST service I mentioned previously uses Cassandra for data storage and talks to it using Spring Data Cassandra (1.2.2). Integrating with it was easy peasy, all it took is a couple of beans in configuration, and a couple of Repository interfaces (which caused some problems with Spring Boot as I described in this post). But then a new requirement came in, columns in Cassandra had to be inserted with TTL (time to live). CrudRepository methods don't support TTL. In order to support TTL during insertion, save method has to be able to take ttl as a parameter. I wanted to implement this functionality once for all repositories in the application. As described in the documentation2 classes needed to be created:

Interface MyRepository, where I added another save method:
Class MyRepositoryImpl, where the method was implemented:

Notice that the documentation is for JPA repositories. For Cassandra repository one more step was needed (I did not find the way around it). Reporsitory Factory Bean needed to be created: and it had to be defined in Configuration: Now we can define a Repository, e.g : Then we just autowire it and call it:

Tuesday, August 18, 2015

Migrating Spring Rest Service Application to Spring Boot (Part II)

As I mentioned in my previous post, things were not going smoothly. I got a weird java.lang.reflect.InvocationTargetException which was hard to explain. After some Googling I found an explanation.  Turns out the culprit was @Repository annotation in the Repository interfaces which is not needed there. Removing the annotation fixed the issue.

I ran the application and I was able to make REST calls  at localhost:8080/resturl. VICTORY!!!

Wait... Not so fast. I need to add v1/ in front resturl for versioning so the call would be like localhost:8080/v1/resturl .

Hmm. For that I needed to register DispatcherServlet and define the mapping:

I also needed to add a custom filter for Dispatcher Servlet. That was easy: Now I am ready to deploy. But how do I that?

Monday, August 17, 2015

Migrating Spring Rest Service Application to Spring Boot

I have a relatively  simple Spring-based REST Service application. I wanted to see how difficult it will be to migrate to Spring Boot.
Some of the details of the application I have:
  • Simple REST Service which uses cassandra-data in the backend
  • Configuration in web.xml which includes filters and listeners
  • Spring Configuration in Java 
  • Logback logging 
  • Maven configuration
I had an older version of maven installed. I had to install the latest version because Spring Boot supports maven 3.3 and higher.

With  this out of the way I added the new dependencies to pom.xml:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.5.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
   .....
</dependencies>
I also commented out all spring dependencies I had execpt for spring-data-cassandra, which is not yet suppported directly by Spring Boot.

Then I created Application.java in the root package with the following code:
 
package basepackage;
import .....
 
@Configuration@EnableAutoConfiguration@ComponentScan@EnableCassandraRepositories(basePackages = { "basepackage" })
public class Application  extends SpringBootServletInitializer{


    @Override    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }
.... 
}

and removed @Configuration and @ComponentScan annotations from WebConfig, which did not have anything else in it.

After that I ran:

 mvn spring-boot:run

and application compiled, started and then spit out a nice big stack trace:

java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.springframework.boot.maven.RunMojo$LaunchRunner.run(RunMojo.java:418)
        at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: 
To be continued ....