Tuesday, December 23, 2014

err: non-serializable object

I'm using Cacheable annotation and getting "err: Non-serializable object" from the underlying caching mechanism (memcache). My code was such as this:

public class MyResult implements Serializable
{
private MyEnum myEnum;
private AnotherObject anotherObj;
}
It is implementing Serializable why it would not work? That's because I forgot that every object in my class must also implement Serializable. So adding this to AnotherObject fixed my problem. But I did not implement Serializable in MyEnum, why it worked? It worked because enums in Java by default implement Serializable.

Wednesday, December 10, 2014

unknown column 'date' in 'field list'

When working on a project in which we use hibernate, I get
Unknown column 'date' in 'field list'
as exception. The spring exception was:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [select this_.ID as ID3010_0_, this_.date as date3010_0_,
The only field I have in my entity named 'date' is not marked with column annotation. So it should not be mapped to database table and thus should not be used in the query right? No, think again. Every field in the entity class is mapped and column annotation is optional. So if you ever want hibernate to ignore a field in your entity (because either this field is not present in the table or you don't want to use it somehow), use transient annotation. So,
@Entity
public class MyEntity implements Serializable
{
    private String date;

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;
must become this
@Entity
public class MyEntity implements Serializable
{
    @Transient
    private String date;

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

Thursday, September 25, 2014

docker presentation

You can find the Docker presentation I did for Sony eurasia below.

Tuesday, July 1, 2014

access to dialectResolutionInfo cannot be null when 'hibernate.dialect' not set

While I was trying JPA stuff on Spring Boot I had a "Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set" exception. I was using "spring-boot-starter-data-jpa" and everything seemed to be in place but still I was getting this. Later I realized that I did not include my database's dependency. After I added it to my pom the problem was fixed.



  postgresql
  postgresql
  9.1-901.jdbc4

Thursday, June 26, 2014

spring boot presentation

Yesterday I did a Spring Boot presentation at Sony Eurasia. Here are the slides:


Wednesday, June 4, 2014

spring social example on spring boot or how I stopped worrying and loved autoconfiguration

As of Spring Boot 1.1.0.RC1, autoconfiguration and the starter pom of Spring Social  is added which means that I won't have to add a hundred dependency to my pom and lots of meaningless Spring configuration will be handled for me. Let's see how it works on an example.

 I will implement a web application of two pages. One will show the given user's Twitter timeline and the other user's profile information. Here's my pom:



    4.0.0

    nr.co.caught
    BootTwitterJoy
    1.0-SNAPSHOT
    war

    
    
        org.springframework.boot
        spring-boot-starter-parent
        1.1.0.RC1
    

    
        
            org.springframework.boot
            spring-boot-starter-social-twitter
        

        
        
            org.apache.tomcat.embed
            tomcat-embed-jasper
        
        
            javax.servlet
            jstl
        

    

    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

    
    
    
        
            spring-snapshots
            http://repo.spring.io/snapshot
            
                true
            
        
        
            spring-milestones
            http://repo.spring.io/milestone
        
    
    
        
            spring-snapshots
            http://repo.spring.io/snapshot
        
        
            spring-milestones
            http://repo.spring.io/milestone
        
    


As you can see, I have my starter-social-twitter dependency which gives me Spring Social and Web capabilities. I'll add jasper and jstl for my jsp pages to work. My repositories part is quite populated due to the milestone repositories.
Now we will add our Service to do Twitter method calls and a Controller for handling the requests. Our Controller is plain and simple:
@Controller
public class TwitterController {

    @Autowired
    private TwitterService twitterService;

 @RequestMapping(value = "/timeline/{twitterUser}")
 public String getUserTimeline(@PathVariable String twitterUser, Model model) {
        model.addAttribute("tweets", twitterService.getUserTimeline(twitterUser));
        model.addAttribute("user", twitterUser);

  return "timeline";
 }

    @RequestMapping(value = "/profile/{twitterUser}")
    public String getUserProfile(@PathVariable String twitterUser, Model model) {
        model.addAttribute("userProfile", twitterService.getUserProfile(twitterUser));

        return "profile";
    }
}
If the request comes with "/timeline/username", our controller will get the user timeline and if it comes with "/profile/username" it will get the user profile from TwitterService. Here's our TwitterService:
@Service
public class TwitterService {

   @Autowired
    private Twitter twitter;

    public List < Tweet > getUserTimeline(String twitterUser) {
        TimelineOperations timelineOps = twitter.timelineOperations();
        List tweets = timelineOps.getUserTimeline("@" + twitterUser);

        return tweets;
    }

    public TwitterProfile getUserProfile(String twitterUser) {
        UserOperations userOperations = twitter.userOperations();
        TwitterProfile userProfile = userOperations.getUserProfile(twitterUser);

        return userProfile;
    }
}
We have a Twitter object that'll be created thanks to Spring Boot's autoconfiguration. We just have to provide an app id and app secret key (a.k.a. consumer key and consumer secret) in our application properties and Boot will do the rest. I'm quoting Twitter object explanation from Spring javadoc: "This instance of TwitterTemplate is limited to only performing operations requiring client authorization. For instance, you can use it to search Twitter, but you cannot use it to post a status update. The client credentials given here are used to obtain a client access token via OAuth 2 Client Credentials Grant". If you try to do a status update, you'll get "org.springframework.social.MissingAuthorizationException: Authorization is required for the operation, but the API binding was created without authorization". For further Twitter functionality, we would need to provide access token and access token secret keys as well but as far as I know autoconfiguration would not handle these cases yet.
My JSPs:
profile.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title></title>
</head>
<body>
<img src="${userProfile.profileImageUrl}"/>  
Screen name: ${userProfile.screenName}
Name: ${userProfile.name}
Description: ${userProfile.description}
Location: ${userProfile.location}
Followers: ${userProfile.followersCount}
</body> </html>
As you can see, profile takes the userProfile provided by our Controller and show the basic profile properties. timeline.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Time Line for <c:out value="${twitterUser}" /> TimeLine</title>
</head>
<body>
<ul>
    <c:forEach items="${tweets}" var="tweet">
        <li>${tweet.text}
at <c:out value="${tweet.createdAt}"/></li> <br/> </c:forEach> </ul> </body> </html>
Tweets are shown with their text and creation date. My application.properties content:
# Config for JSPs
spring.view.prefix: /WEB-INF/jsp/
spring.view.suffix: .jsp

# SPRING SOCIAL TWITTER (TwitterAutoConfiguration)
spring.social.twitter.appId= someAppId
spring.social.twitter.appSecret= someSecretId
spring.view properties are for the jsp handling. spring.social.twitter properties can be obtained from http://dev.twitter.com. Just login there with your twitter account, create your app and get your api keys. Here's the result:




You can check the code at github.

Thursday, May 29, 2014

exception after main class package change in spring boot

In my Spring Boot toy project ( web + mongodb), I want to change the structure of my packages. My old structure was like this:

Putting @ComponentScan annotation (without a base package) was fine for scanning all my classes. But when I update the structure and moved my main file (BootQeyfi) to launch package, I needed to update base package with
@ComponentScan(basePackages = "main") . After that definition Spring will scan the main as a base package and handle everything perfectly.

But of course that's not the case. I got the following exception which basically means "I could not autowire your repository class (your interface which extends MongoRepository)" 
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private main.service.HelloService main.controller.HelloController.service; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: main.dao.ProductRepository main.service.HelloService.repository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [main.dao.ProductRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
 at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
 at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
 at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
 at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:120)
 at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:648)
 at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
 at launch.BootQeyfi.main(BootQeyfi.java:27)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private main.service.HelloService main.controller.HelloController.service; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: main.dao.ProductRepository main.service.HelloService.repository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [main.dao.ProductRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
 at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
 ... 14 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: main.dao.ProductRepository main.service.HelloService.repository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [main.dao.ProductRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
 at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
 at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1017)
 at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:960)
 at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
 ... 16 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: main.dao.ProductRepository main.service.HelloService.repository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [main.dao.ProductRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
 at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
 ... 27 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [main.dao.ProductRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
 at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1103)
 at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963)
 at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
 ... 29 more
To fix this problem, @EnableMongoRepositories must be added to your main class. My repository is under "main.dao" so my definition is like @EnableMongoRepositories(basePackages = "main.dao").

Sunday, May 25, 2014

rocking with mongodb on spring boot

I'm a fan of Spring Boot and here's my mongodb example project on Spring Boot. Most of the mongodb example projects are so basic that you won't go far with them. You can search for plain Spring Data examples but they can get much complex than you'd like. So here's mine.


Here's the pom I'll use.


    4.0.0

    caught.co.nr
    boottoymongodb
    1.0-SNAPSHOT
    war


    
    
        org.springframework.boot
        spring-boot-starter-parent
        1.0.0.BUILD-SNAPSHOT
    

    
        
            org.springframework.boot
            spring-boot-starter-data-mongodb
        

    

    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

    
        
            spring-snapshots
            Spring Snapshots
            http://repo.spring.io/snapshot
            
                true
            
        
    

    
        
            spring-snapshots
            http://repo.spring.io/snapshot
        
    

The only dependency I need is "spring-boot-starter-data-mongodb" which contains all necessary dependencies for a spring boot mongodb project. Next is the model for my collection. Document annotation points to my collection named "products". It is need only if your model name does not match your collection name. You can see a field annotation which maps the field name in the collection to the model's field name.

@Document(collection = "products")
public class Product {
    @Id
    private String id;
    private String sku;

    @Field(value = "material_name")
    private String materialName;

    private Double price;
    private Integer availability;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getSku() {
        return sku;
    }

    public void setSku(String sku) {
        this.sku = sku;
    }

    public String getMaterialName() {
        return materialName;
    }

    public void setMaterialName(String materialName) {
        this.materialName = materialName;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Integer getAvailability() {
        return availability;
    }

    public void setAvailability(Integer availability) {
        this.availability = availability;
    }

    @Override
    public String toString() {
        return "Product{" +
                "id='" + id + '\'' +
                ", sku='" + sku + '\'' +
                ", materialName='" + materialName + '\'' +
                ", price=" + price +
                ", availability=" + availability +
                '}';
    }
}
Not we will need a DAO layer to manipulate my data. MongoRepository is the interface I should implement if I want to use autogenerated find methods in my DAO layer and I want that. Every field of my model can be queried with these autogenerated methods. For a complete list of method name syntax check here. My query below will take a sku name and search my collection for this name and return the matching ones.

public interface ProductRepository extends MongoRepository < Product, String >{
    public List < Product > findBySku(String sku);
}
Now I'll introduce a Service which will call my DAO interface. But wait a minute, I didn't implement this interface and wrote necessary code for fetching the models right? Yep, these methods are autogenerated and I don't need an implementation for this interface.
@Service
public class ProductService {
    @Autowired
    private ProductRepository repository;

    public List < Product > getSku(String sku){
        return repository.findBySku(sku);
    }
}
Next, lets launch our Boot example. Here's our main class:
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class BootMongoDB implements CommandLineRunner {

    @Autowired
    private ProductService productService;

    private static final Logger logger = LoggerFactory.getLogger(BootMongoDB.class);

    public void run(String... args) throws Exception {
        List < Product > sku = productService.getSku("NEX.6");
        logger.info("result of getSku is {}", sku);
    }

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

If you have a connection to a mongodb instance and a sku matching to the name you searched than you should see one or more Products as a result. What we did was quite basic. What if I want more complex queries? For instance if I want a specific sku with an availability equal to "1"? I can't do it without using some @Query magic. So I'm updating my DAO class.
public interface ProductRepository extends MongoRepository < Product, String >{
    public List < Product > findBySku(String sku);

    @Query(value = "{sku: ?0, availability : 1}")
    public List < Product > findBySkuOnlyAvailables(String sku);
}
I provided a direct query for mongodb where sku in the signature of my method will be inserted to "?0" in the query and will be sent to mongodb. You can update your Service and then your main method to see if it works. You may not like writing queries which are not much readable if you're not very familiar with mongodb's syntax. Then this is the time for adding custom DAO classes. It's not possible to add and use methods other than the autogenerated ones to ProductRepository. So we will add few classes and have a nice featured methods. Our repository class was named "ProductRepository". We will add a new interface named "ProductRepositoryCustom" and a new method which will find available skus for the given name (twin of findBySkuOnlyAvailables method).
public interface ProductRepositoryCustom {
    public List < Product > findBySkuOnlyAvailablesCustom(String sku);
}
 
Then provide an implementation for this. Below you see that we inject ProductRepositoryCustom's mongotemplate and do stuff with it. We create two criteria. First one is for the sku name and the second one is for availability.
public class ProductRepositoryImpl implements ProductRepositoryCustom {
    @Autowired
    private MongoTemplate mongoTemplate;

    public List < Product > findBySkuOnlyAvailablesCustom(String sku) {
        Criteria criteria = Criteria.where("sku").is(sku).
andOperator(Criteria.where("availability").is(1));
        return mongoTemplate.find(Query.query(criteria), Product.class);
    }
}
The last step for custom implemetation is the update of ProductRepository class. As you can see below the only update I need is the addition of my ProductRepositoryCustom so we can link both of them together. All this naming can sound a little stupid. But notice that although the name of your custom interface is not important, a change in the name of the implementation will result in the throw of an exception:
Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property only found for type String! Traversed path: Product.sku.
To fix this make sure that the name of your implementation class is "ProductRepositoryImpl" which is the concatenation of the name of the interface that extends MongoRepository and "Impl".
public interface ProductRepository extends MongoRepository < Product, String>, ProductRepositoryCustom
If we add our new method to our Service layer:
@Service
public class ProductService {
    @Autowired
    private ProductRepository repository;

    public List < Product > getSku(String sku){
        return repository.findBySku(sku);
    }

    public List < Product > getAvailableSkuCustom(String sku){
        return repository.findBySkuOnlyAvailablesCustom(sku);
    }
}
Then update our main class' run method:
   public void run(String... args) throws Exception {
        List < Product > sku = productService.getSku("NEX.6");
        logger.info("result of getSku is {}", sku);

        List < Product > availableSkuCustom = productService.getAvailableSkuCustom("NEX.6");
        logger.info("result of availableSkuCustom is {}", availableSkuCustom);
    }
Again you must see something in the log :). You can check the whole project on github.

Friday, May 23, 2014

fixing "no such app as" error in heroku deployment after application rename

I did few changes in my toy project and pushed it to heroku with

git push heroku master
but got this error:
!  No such app as myOldApplicationName.

fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
I googled a bit to see that this is due to my application rename in heroku website. The previous name was "myOldApplicationName". Then I searched my .git directory to see if there are references to the old application name. I found it under "config".
[remote "heroku"]
 url = git@heroku.myOldApplicationName.git
Edit it with your new application to fix the issue.
[remote "heroku"]
 url = git@heroku.com:myNewApplicationName.git

Sunday, May 11, 2014

how to build your web application on spring boot and deploy it on heroku

Why would you need a tutorial for building your web application on spring boot and deploying it on heroku?
That's because our web application will serve JSP files and as Spring Boot's JSP support is limited we will have to use war files for deployment and it can get a bit tricky to deploy it on heroku. Furthermore, as the web application we will deploy is super concise you can use it on your own project by just editing it.

Our controller is quite basic. It will take the name of the user from url and print it on the next page. So calling "/hello/sezin" will print on "hello sezin" on the page.


package main.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author sezin karli (skarligmail.com)
 * @since 3/19/14 3:42 PM
 *        User: Sezin Karli
 */
@Controller
@RequestMapping(value = "/hello")
public class HelloController {

    @RequestMapping(value = "/{user}")
    public String handleOne(@PathVariable String user, ModelMap modelMap){
        String helloToken = "Hello " + user;
        modelMap.put("token", helloToken);
        return "welcome-page";
    }
}

Our main Spring class is below. PORT attribute is taken from environment variables if it can't be found 8080 is used. This part is a requirement for Heroku.

package main;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author sezin karli (skarligmail.com)
 * @since 3/19/14 9:26 AM
 *        User: Sezin Karli
 */
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class ToyProjectLauncher {

    public static void main(String[] args) throws Exception {
        String webPort = System.getenv("PORT");
        if (webPort == null || webPort.isEmpty()) {
            webPort = "8080";
        }
        System.setProperty("server.port", webPort);

        SpringApplication.run(ToyProjectLauncher.class, args);
    }
}

Our application properties. We need to show a folder for jsp files and if we don't want to print ".jsp" suffix for every return value in the controller we will also need the suffix parameter below.

server.port: ${port:8080}
spring.view.prefix: /WEB-INF/jsp/
spring.view.suffix: .jsp
Our jsp is as follows. We just print the token we get from the controller.
<%@ page language="java" contentType="text/html; charset=US-ASCII"
         pageEncoding="US-ASCII"%>



    
    Hello Page
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    






If we analyze the pom below you can see that we have a spring boot parent which's needed to inherit defaults from spring boot. Then we add starter-web dependency because it will add web dependency template. Jasper and jstl dependencies are needed for JSPs to work. We would need spring-boot-maven-plugin if we want a fat jar which makes it easier to deploy.

    4.0.0

    nr.co.caught
    boot-toy-project
    1.0-SNAPSHOT
    war


    
    
        org.springframework.boot
        spring-boot-starter-parent
        1.0.0.BUILD-SNAPSHOT
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            org.apache.tomcat.embed
            tomcat-embed-jasper
        
        
            javax.servlet
            jstl
        

    

    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

    
        
            spring-snapshots
            Spring Snapshots
            http://repo.spring.io/snapshot
            
                true
            
        
    

    
        
            spring-snapshots
            http://repo.spring.io/snapshot
        
    

You can check GitHub if you need further details with the project. If everyting's fine you should be able to build it with "mvn package".
You must see your war file under target folder. Why a war file? Because Spring Boot supports JSPs only if the project package is war.
 Lets run our code by going under "target" and doing "java -jar boot-toy-project-1.0-SNAPSHOT.war". You should see your hello page if you type "localhost/hello/sezin".

Now we will continue by deploying it on heroku. I assume you already have a heroku user and heroku toolbelt already installed.

Open a command prompt and login to heroku by typing "heroku login". Type your heroku email and password. It says "could not find an existing public key. We try to generate one but get a "could not generate key: 'ssh-keygen' is not recognized" error (under windows 7).


There seems to be a problem.
Open a git bash and lets create an ssh key with 'ssh-keygen -t rsa -C "yourEmail"' command.

Lets login again and here we get "authentication successful".



After that we will try to push and deploy our Spring Boot Project.
Create a file named "Procfile" with the information below under our project folder

 web: java $JAVA_OPTS -jar target/boot-toy-project-1.0-SNAPSHOT.war

There's another way to deploy war files to heroku (heroku deploy:war), but I didn't manage to run my application with it so I'm teaching you what worked for me. :)

Now, create a project with "heroku create" command. We will get "Git remote heroku added".


Open git bash and enter "git push heroku master" under your project directory. Now we will push our code into heroku git and heroku will deploy it to our server.



The last line will show you on which address your site is available. Mine was "http://pure-shelf-8719.herokuapp.com/". I add few strings to test my hello page and go to "http://pure-shelf-8719.herokuapp.com/hello/world". You can see the awesome result below.


Thursday, May 8, 2014

expression language injection attacks with the help of springJspExpressionSupport

Recently, I discovered a nasty place for expression language injection attack in one of my applications. This was directly related to the expression evaluation feature of spring components on jsp.
I was adding a request parameter to a spring form's action and as spring's form component directly evaluates it, you were able to put a ${applicationScope} (or anything on the page) on the request parameter and see the evaluation result on the source code.

First thing to do was setting springJspExpressionSupport to false by editing my web.xml and setting the flag to false.

 
        Enable Spring JSP Expressions
        springJspExpressionSupport
        false
    

The problem with this is the fact that it totally disables Spring's evaluation mechanism which means  ExpressionEvaluationUtils.evaluate() calls won't work anymore. So I had to use an alternative way such as the following code:

ELContext elContext = pageContext.getELContext();
JspApplicationContext jac = JspFactory.getDefaultFactory().getJspApplicationContext(pageContext.getServletContext());
 ValueExpression val = jac.getExpressionFactory().createValueExpression(elContext, exp, resultClass);
return val.getValue(elContext);

Tuesday, April 15, 2014

aboutme rocks

I'm quite lazy about creating a new homepage and aboutme comes to my rescue. It is easy to use and looks plain beautiful. Check my homepage.

Tuesday, April 8, 2014

mongodb default configuration in spring boot

I'm trying to integrate mongodb to my spring boot application. I create a db aptly named "mydb" and was wondering how mongodb classes were able to connect to my database without any configuration and why they were not retrieving my data. Answer to both is of course "default configuration" for mongodb.

You can see mongodb defaults that spring boot uses:

host: localhost
port: 27017
db: test

My mongodb is at localhost:27017, but as I'm using "mydb" instead of "test" no data is retrieved. So I have to override the default configuration by adding
spring.data.mongodb.uri=mongodb://localhost:27017/mydb
to my application.properties file.

Friday, March 21, 2014

problem with displaying jsp on spring boot

I'm currently trying to learn Spring Boot (1.0.0 snapshot) in my spare time. I try to use spring-boot-starter-web for building a sample website but had problems when I try to use jsp for the view part of my mvc. Everything was in place.

  • I had a jsp named "welcome-page.jsp" under "src/main/webapp/WEB-INF/jsp/" 
  • In my controller I was sending the user to "welcome-page". 
  • The path configuration was done under application.properties with
    • spring.view.prefix: /WEB-INF/jsp/
    • spring.view.suffix: .jsp


And yet it was not working. Nothing on logs too, even on debug level.
After some search and several trial/errors, I saw that it is impossible to use embedded tomcat for displaying jsps without adding several dependencies to my main pom. Next to the standard spring-boot-starter-web dependency, I had to add jasper and jstl dependencies as well. So long for leaving dependencies to starter templates.


   
 
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.apache.tomcat.embed
            tomcat-embed-jasper
            provided
        
        
            javax.servlet
            jstl
        
    

Wednesday, February 12, 2014

my google guava presentation

You can check the Google Guava presentation I did for work.