Friday, December 19, 2014

Sending data to CanJS component

Ideally, components should be independent, but sometimes it is needed to send data or call function on component from outside. It is possible to do by using observable like can.Map and listen to events on it from component like:

<script type="text/javascript">
  var observable = new can.Map({val:0});

  $(function() {
    can.Component.extend({
      tag: "my-tag",
      events: {
        "{observable} val": function(param, param2, newval){
          alert(newval);
        }
      }
    });
    $('#myTagDiv').html(can.view.mustache('<my-tag/>'));
  });
</script>



<div id="myTagDiv"></div>
<input type="button" value="Call observable" onclick="observable.attr('val', observable.val+1);">


This way all components will receive observable change event either they are sent from itself, other component or directly from JavaScript.

Wednesday, November 5, 2014

JSON converter is not working in unit tests in Grails

If calling grails.converters.JSON from unit test throws error like:

java.lang.RuntimeException: org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Unconvertable Object of class: my.blog.Post
	at org.codehaus.groovy.grails.web.converters.AbstractConverter.toString(AbstractConverter.java:111)
	at org.codehaus.groovy.runtime.InvokerHelper.format(InvokerHelper.java:616)
	at org.codehaus.groovy.runtime.InvokerHelper.format(InvokerHelper.java:559)


It is easy to fix this error by adding ControllerUnitTestMixin to the test definition like:

@TestMixin(ControllerUnitTestMixin)
@TestFor(BlogService)
class BlogServiceTests {
...


Friday, October 31, 2014

Grails requires restart after changes in domain class

Grails officially supports domain class reloading since version 2, but recently I found problems using it together with MongoDB GORM plugin, because it required application restart after every change to domain class.
So if Hibernate is primary GORM and Mongo is used only for some particular cases, disabling it can be a good option to make development easier.

Friday, October 17, 2014

Adding common methods to Grails domain objects

If you don't want to change your domain hierarchy, but need to add common function to multiple domains without copy/paste, one simple option is to create and implement trait. For example:
class Test implements LogTrait {
  String name
}

trait LogTrait {
  def springSecurityService

  def afterInsert() {
    log.info(this as JSON)
  }
}
Nice bonus is that events and injected services work just fine as it would be in original class.


Friday, September 5, 2014

Script that logs time to JIRA from Git commit messages

If you need to report work time in JIRA and native comment hashes are not suitable for you, there is simple Groovy script that does the same and can be adjusted to particular scenario or configuration:

@GrabResolver(name='test', root='https://maven.atlassian.com/content/groups/public/')
@Grab( group ='com.atlassian.jira.plugins', module = 'jira-soapclient', version = '4.4' )
@Grab(group='org.eclipse.jgit', module='org.eclipse.jgit', version='3.3.2.201404171909-r')

import com.atlassian.jira.rpc.soap.client.JiraSoapServiceServiceLocator
import com.atlassian.jira.rpc.soap.client.RemoteWorklog
import groovy.transform.TailRecursive
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.revwalk.RevWalk
import org.eclipse.jgit.storage.file.FileRepositoryBuilder
import java.text.SimpleDateFormat
import static java.util.Calendar.*

@TailRecursive
static Set<RevCommit> subcommits(RevCommit commit, int start, RevWalk walk, def all) {
  if (commit.commitTime > start) {
    all << commit
    commit.parents.collect{ walk.parseCommit(it) }.each {
      subcommits(it, start, walk, all)
    }
  }
  return all
}

Repository repository = new FileRepositoryBuilder().setGitDir(new File(args[3])).setMustExist(true).build()
RevWalk walk = new RevWalk(repository)

def formattime = new SimpleDateFormat('yyyy-MM-dd')
formattime.setTimeZone(TimeZone.getTimeZone("UTC"))
Date start = formattime.parse(args[4])
Date end = formattime.parse(args[5])

def all = subcommits(walk.parseCommit(repository.resolve("HEAD")), start.time / 1000L as int, walk, new HashSet())
def mine = all.findAll{ it.authorIdent.name == args[6] && it.fullMessage =~ /^PRJ-[0-9]+/ }

def actual = mine.min{ it.commitTime }

def tasks = (start..end).findAll{!(it[DAY_OF_WEEK] in [SUNDAY, SATURDAY])}.collect {date ->
  actual = mine.find{ date.time / 1000L <= it.commitTime && (date + 1).time / 1000L > it.commitTime } ?: actual
  [date:date, task:(actual.fullMessage =~ /(PRJ-[0-9]+)/)[0][1]]
}

if (args[0] == 'test') {
  tasks.each { println "${it.date} - ${it.task}" }
} else if (args[0] == 'prod') {
  def jiraSoapService = new JiraSoapServiceServiceLocator().getJirasoapserviceV2(new URL('http://jira.com/rpc/soap/jirasoapservice-v2'))
  String token = jiraSoapService.login(args[1], args[2])
  tasks.each { jiraSoapService.addWorklogAndRetainRemainingEstimate(token, it.task, new RemoteWorklog(timeSpent: "8h", startDate:it.date.toCalendar())) }
}



It uses a bunch of command line parameters - first is either prod or test; test just prints tasks, prod sends them to JIRA. There is an example CLI command:

groovy gittotempo.groovy prod jirauser jirapassword c:\work\project\.git 2014-08-01 2014-08-31 gituser

Friday, August 15, 2014

Disable pretty printing of JSON in Grails

It is easy to print any object as JSON in Grails
[key:'value'] as JSON

But it gives human readable, nice, multiline formatted version of JSON with indents. If that is not needed, it is easy to switch it off, like:
new JSON([key:'value']).toString(true)
Much uglier, but does the job.

Tuesday, July 22, 2014

CanJS execute code on component initialization

I didn't found it described anywhere, but it works for me. If you need to execute code after component initialization, you can add init method to scope and it is executed after component is created.

    scope: {
      init: function() {
        runme();
      }
    }

Thursday, July 3, 2014

Updating model elements of CanJS component scope

CanJS scope is simple map and when you need to retrieve new element from server the easiest way seems just to assign new model to property, like:

  scope.attr('todos', new Todo.List({date:val}));

This is easy and works, but not best solution, as values blink on screen. This is because initial list is empty and values are added after they are loaded, so more smooth and reactive (bazinga!) way to do it, will be by model's findAll method callback, like:

  Todo.findAll({date:val}, function(todos){ scope.attr('todos', todos) });

Additional benefit of this approach is that you can use new values for whatever you might need besides displaying them.

Thursday, June 12, 2014

CanJS is not calling Mustache function when value is updated

Mustache can map not only specific values to template, but also results of the functions, which is sometimes handy. There is example.

But recently, when I was using this feature inside of CanJS template, it only rendered results for the first time and did nothing when values were changing. This was not working properly:

  can.Component.extend({
    tag: "sum",
    scope: {
      model: new can.Model({x: 2, y:3}),
      result: function() {
        return this.model.x * this.model.y;
      }
    },
    template: '<input can-value="model.x">*<input can-value="model.y">={{result}}'
  });

As I found out, problem was that it was missing proper value invocation and simply calling values via attr method fixes the problem.
This works fine:

  can.Component.extend({
    tag: "sum",
    scope: {
      model: new can.Model({x: 2, y:3}),
      result: function() {
        return this.model.attr('x') * this.model.attr('y');
      }
    },
    template: '<input can-value="model.x">*<input can-value="model.y">={{result}}'
  });

Wednesday, June 4, 2014

Accessing multiple objects from CanJS events in components

CanJS components have nice and easy way to access context object from event, just as parameter:

{{#books}}
  <input type="button" can-click="add" />
{{/books}}

add: function(book) {
  books.add(book);
}

But what if you need also parent object, or object from some other hierarchy. To do it, CanJS can bind DOM objects to any data, and in components this is usually context. Just add special property {{data '...'}} to DOM element in your Mustache template, for example:

{{#shelves}}
  <h1>{{name}}</h1>
  <div {{data 'shelf'}}>
    {{#books}}
      <input type="button" can-click="add" {{data 'book'}} />
    {{/books}}
  </div>
{{/shelves}}

And you can access all objects like:

add: function(context, el) {
  var book = el.data('book');
  var shelf = el.parent().data('shelf');
  shelf.add(book);
}

Thursday, May 29, 2014

Grabing JavaScript libraries via WebJars in Spring Boot

WebJars is nice and familiar way to work with JavaScript dependencies from Java projects. Spring Boot supports it, and it is pretty easy to add them for Groovy projects, just with good old Grab annotation, like:

@Grab("org.webjars:canjs:2.0.2")

Then all CanJS files become available under /webjars/canjs/2.0.2/. If not sure, list of files can be looked up at WebJars website.

Friday, May 9, 2014

Chaining jQuery promises in for cycle

JQuery has nice support for promises, but some stuff is not obvious and recently I just stuck with one particular problem: I had to prepare a bunch of closures in for cycle and added them to deferred object which was resolved afterwards. All of them had to be executed strictly one after another, but there are ajax calls so I cann't do it old fashioned way, since sinchronous ajax is weird.
So I did this:

function doPromise(someVar) {
  return function() {
    return $.ajax({ type: 'POST', url: 'http://myurl', success: doStuff, error: panic});
  }
};
function start() {
  var promise = $.Deferred();
  for (var i=0;i<10;i++) {
    promise.then(doPromise(i) );
  }
  promise.resolve();
};


And I was expecting it being called one after another, which was not the case and all of them fired simultaniously. As I found out finally, all thens are equal and I had to add them, not to original promise, but dirrectly to each other, which is a little confusing to me, but works. So this is the correct code for my case:

function start() {
  var original = $.Deferred();
  var promise = original;
  for (var i=0;i<10;i++) {
    promise = promise.then(doPromise(i) );
  }
  original.resolve();
};


Wednesday, April 30, 2014

Launching Spring Boot in Groovy with Grab

Since launch of Spring Boot I was wondering why it needs separate CLI, especially for Groovy where there is already Grab. Of course CLI provides some additional features, like reloading and out of the box dependencies, but why no one runs Boot with vanilla Groovy? So I tried it myself, and it looks like problem is that there is conflict with default Groovy libs, because standard installation includes servlet-api-2.4.jar which does not work with current Tomcat or Jetty, and as there is no anything like fork mode in Grails, there is only one way to avoid it - not to load this jar (delete it or use custom load conf).

Otherwise this works fine for me:

@Grab("org.springframework.boot:spring-boot-starter-web:1.0.2.RELEASE")
@Grab("org.springframework.boot:spring-boot-starter-actuator:1.0.2.RELEASE")
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.web.bind.annotation.*

@RestController
@EnableAutoConfiguration
class ThisWillActuallyRun {

  @RequestMapping("/")
  String home() {
    "Hello World!"
  }
}
SpringApplication.run(ThisWillActuallyRun, args)


Tuesday, April 15, 2014

IllegalStateException Method on class was used outside of a Grails application

After upgrade to 2.3 and running Geb functional UI tests, they started to fail with error:

java.lang.IllegalStateException: Method on class [my.Test] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.
       at my.Test.currentGormStaticApi(Test.groovy)
       at my.Test.$static_methodMissing(Test.groovy)
       at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
       at groovy.lang.MetaClassImpl.invokeStaticMissingMethod(MetaClassImpl.java:1372)
       at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1360)
       at groovy.lang.ExpandoMetaClass.invokeStaticMethod(ExpandoMetaClass.java:1123)
       at org.codehaus.groovy.runtime.callsite.StaticMetaClassSite.call(StaticMetaClassSite.java:50)
       at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
       at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
       at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)


After some pretty painful investigation, I found out that problem is when running tests with new fork mode properties, and is easy to solve by removing these options from BuildConfig.groovy:

grails.project.fork = [
    test: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, daemon:true],
    run: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false],
    war: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false],
    console: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256]
]

Thursday, April 3, 2014

MeteorJS like application in Grails

MeteorJS is new web framework that combines server-side and client-side programming into one, leaving mostly just client-side. I am defenitely not expert with tool and just seen demo on their homepage, but WOW effect is sure impressive. It suppose to kill all Rails and server-side development in general. Thank god I am full-stack developer, but anyway I am scared.

General idea behind this framework is autogenerating all server-side code, leaving mostly just configuration. Similar feature was recently introduced in Grails, so I was wondering - is it possible to create something similar to MeteorJS in Grails. And there is my experience.

Basically, it needs autogenerated REST, Javascript ORM and server push. REST is Grails feature since version 2.3; for client-side ORM I picked CanJS as it looks most similar to Meteor; for server push in Grails I picked spring-websocket plugin (because it is first result in Google, why else?). Unfortunately, spring-websocket is M1 and it relies on Spring 4, so Grails is 2.4M1 too, so it is not production safe, but MeteorJS is 0.8.0 now too, so we are even.

Application idea is simple TODO app. You can find full source here. There is defenitely some boilerplate code as it is not plugin, but I think in general it is pretty similar to MeteorJS example. It consists of 3 meaningful components: view, controller and domain object.

View is Mustache template, and is pretty straightforward if you are familiar with CanJS:

<h1>test</h1>
<table>
{{#todos}}
  <tr>
    <td>{{description}}</td><td><input type="checkbox" can-value="done"></td>
    <td><input type="button" value="Delete" can-click="delete"></td>
    </tr>
{{/todos}}
</table>

Description
<input type="text" can-value="description">
<input type="button" can-click="add" value="Add">

Controller is CanJS component with ORM definition:

var Todo = can.Model({
  findAll: function(id)   {return $.get('/grails-meteor-example/todos.json/')},
  findOne: function(id)   {return $.get('/grails-meteor-example/todos.json/'+id)},
  create:  function(data) {return $.post('/grails-meteor-example/todos.json/', data)},
  update:  function(id)   {return $.ajax({type: 'PUT',    url: '/grails-meteor-example/todos.json/'+id })},
  destroy: function(id)   {return $.ajax({type: 'DELETE', url: '/grails-meteor-example/todos/'+id, contentType: 'application/json' })}
}, {});

can.Component.extend({
  tag: "todos",
  template: can.view("todos.mustache"),
  scope: {
    todos: new Todo.List({}),
    description: can.compute(''),
    add: function() {
      new Todo({'description':this.description(), 'done':false}).save();
      this.description('');
    },
    delete: function(todo) {
      todo.destroy();
    }
  },
  events: {
    "{todo} change": function(){
      this.scope.attr('todos', new Todo.List({}));
    }
  }
});

$(document).ready(function() {
  $("body").html( can.view.mustache("<todos></todos>"));
});


Domain is Grails domain object mapped as REST controller:

package org.grmeteor

import grails.rest.Resource

@Resource(uri='/todos')
class Todo {
  String description
  boolean done
}


View is totally similar to MeteorJS. Controller is similar, but also contains ORM definition and server push event. Both could be easily autogenerated with Grails plugin, but at least push can be also left for practical applications (probably, you will not want to have notification with millions of parallel users). Domain is pure Grails overhead, but it would probably still be needed for SQL backends in MeteorJS (and hey, those server-side devs want to eat too!).

Of course there are other files too, like server push sender and client side HTML container for CanJS, but these are mostly static and sure can be easily hidden by plugin. So only part that is missing to make Grails MeteorJS-cool is plugin itself, which even if not for practical cases could be nice to have for WOW effect and MVPs.

Wednesday, April 2, 2014

Grails REST redirect after DELETE with jQuery

If you do delete from AJAX request (directly or via framework), sometimes Grails REST controller redirects response to index method, which when done with DELETE method leads to 405 HTTP error.
This happens because of incorrect content type in request. To fix it, contentType needs to be explicitly set in request, like:

$.ajax({
    url: '/todos/'+id,
    type: 'DELETE',
    contentType: 'application/json'
  })

Thursday, March 20, 2014

CanJS incorrectly places elements in table row

After rendering this HTML in CanJS, 'tests' elements got placed before table and not after previous cell as it is supposed to be:

<thead>
  <tr>
    <th>Test</th>
    <th><input type="button" value="Test"></th>
    {{#tests}}
      <th>{{name}}</th>
    {{/tests}}
  </tr>
</thead>

Problem was that input tag was not closed, which is usually fine with HTML, but confuses CanJS. After closing it, everything was working as expected.

Monday, February 24, 2014

Setting different JAVA_HOME for Gradle in IntelliJ IDEA

There are a lot of different options to set JDK folder in Gradle, but in IntelliJ the only option that worked for me was adding this line:

gradle.java.home=C:/Program Files/Java/jdk1.8.0/

into idea.properties file.

Thursday, February 13, 2014

Storing sessions in Redis with Spring Boot

Tomcat has nice support to use Redis for session replication with this awesome library. However Spring Boot launches embedded Tomcat, so there is no traditional XML configuration, it is still super easy to change default manager to use Redis for session replication, just define containerCustomizer bean, like:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class App {
  public App() {
  }

  @Bean
  public EmbeddedServletContainerCustomizer containerCustomizer(){
    return factory -> {
      TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) factory;
      containerFactory.addContextValves(new RedisSessionHandlerValve());
      containerFactory.setTomcatContextCustomizers(Arrays.asList(context -> {
        context.setSessionTimeout(30);
        context.setManager(new RedisSessionManager(){{
          setHost("redis.server.com");
        }});
      }));
    };
  }

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

(this is syntax with new shiny Java 8 lambdas, but with few additional boring types it should compile in old Javas too).

Tuesday, February 11, 2014

Grails dies in the middle of Jenkins jobs after update

If you have upgraded recently and facing problem when job suddenly dies in the middle of test execution, like:

19:20:39  | Running 277 unit tests... 156 of 277
19:20:53  Build step 'Execute shell' marked build as failure
19:20:54  Description set: 

Most probably it is because since version 2.2 test-app, run-app, run-war runs in fork mode and Jenkins has some fancy zombie process detection that kills spawned processes it does not like.
Quick solution is to disable fork in test environment or you can refer my previous post about hiding such processes.

Monday, February 3, 2014

No such property error in Cucumber specs with Geb

It is common to write Geb specs directly referencing page elements like:
  to LoginPage
  loginField << login
  passwordField << password
  loginButton.click()

But if you try doing same with Cucumber step files, you will get exception, like:
No such property: loginField for class: steps.Login_steps
groovy.lang.MissingPropertyException: No such property: loginField for class: steps.Login_steps
 at steps.Login_steps$_run_closure2.doCall(Login_steps.groovy:42)
 at ✽.When user enters login and password(Login.feature:7)

This is because page object is not bound and you should reference it explicitly, like:
  to LoginPage
  page.loginField << login
  page.passwordField << password
  page.loginButton.click()


Friday, January 31, 2014

Sending ActiveMQ messages from Groovy

Didn't found it in Google, so there is quick example how to send JMS message from Groovy script using Grab:


@Grab(group='org.apache.activemq',module = 'activemq-all', version='5.5.0')

import org.apache.activemq.ActiveMQConnectionFactory
import javax.jms.Session

new ActiveMQConnectionFactory(brokerURL: 'tcp://localhost:61616').createConnection().with {
  start()
  createSession(false, Session.AUTO_ACKNOWLEDGE).with {
    createProducer().send(createQueue("queue"), createTextMessage("test"))
  }
  close()
}