Sunday 2 December 2007

Notification area with Scriptaculous

This time I need a notification area in webapp, the idea is a div that appears and disappears.

In Scriptaculous it's easy extend and combine effects, and the first I do is extend an Effect to do the behavior that I'm looking for.

Effect.Notify = function(element) {
element = $(element);
return new Effect.Appear(element,
{ afterFinishInternal: function(effect) {
new Effect.Fade(effect.element,{ delay: 1.6 });
}});
}


The only thing you have to do is create a "div" with style "display: none" and invoke the Effect like this:


new Effect.Notify('mydiv');


Simple and powerful.

Monday 12 November 2007

AjaxForm class for prototype

Some weeks ago an old mate asked to me the best way to send a form in ajax style and put the result in "div". I think the best way is using prototype javascript framework.
For one project I did a AjaxForm class, it based in an Ajax example of Spring Web Flow.

Here the class:

var AjaxForm = Class.create();
AjaxForm.prototype = {
initialize: function(formElementId) {
this.formElementId = formElementId;
Event.observe(formElementId, 'submit', this.handleSubmitEvent.bindAsEventListener(this), false);
},

handleSubmitEvent: function(event){
var formElement = $(this.formElementId);
if (formElement.tagName.toLowerCase() != 'form') {
throw 'Element ' + formElement + ' is not a FORM element!';
}
var method = formElement.method;
if (method == null) {
method = 'get';
}
var url = formElement.action;
if (url == null) {
throw 'No action defined on ' + formElement;
}
try {
Event.stop(event);
showLoadInfo(formElement);
var params = Form.serialize(formElement, true);

var myRequest = new Ajax.Updater(
{ success: formElement.parentNode },
url,
{
method: method,
parameters: params,
evalScripts: true,
onFailure: errFunc
});
} finally {
return false;
}
}
};


To use this class is very simple, you have to wrapper the form with a div, and create a new AjaxForm, like this example:

<div id="wrapperForm">
<form id="myAjaxForm" action="/dosomething">
...
...
</form>
</div>

<script type="text/javascript">
// <![CDATA[
new AjaxForm('myAjaxForm');
// ]]>
</script>


The result of the post is put in div "wrapperForm". It's fantastic because doesn't break the MVC, remember disable decorators or tiles in the result page, because the result is in the div, not in the page.

I have to update the syntax of AjaxForm class to prototype 1.6, but for example is good enought.

Saturday 10 November 2007

Compass or Hibernate Search

Compass and Hibernate Search are two frameworks to provide full text search engine to your apps.
Which one to choose? This is a large discussion between Emmanuel Bernard (Hibernate) and Shay Banon (Compass), my conclusion is that both are really good.
Yeah, both are really good but I have to choose one, and I choose Hibernate Search, here my reasons.
  • I use Hibernate API with JPA annotations and similar API seems more natural, to learn and understand.
  • Minimal configuration. I only have to put two properties in the config.
  • All of my searchable data are in database.
  • I think the Hibernate Search annotations fits better with JPA annotations.
  • And the last, Hibernate Search is in maven repository (Compass no).
If I used Ibatis or JDBC directly, I'd choose Compass.
Maybe, if I had many searchable data, that aren't in database I'd choose Compass too.

Monday 1 October 2007

Saving the last time login with Acegi Security

This time, I'm going to explain how to save the last login time of user with Acegi Security for Spring.
It's really easy, due to Acegi publishes an autentication event in the Spring ApplicationContext (documentation about publish/suscribe events).

I have to create a simple class that implements ApplicationListener.

public class LastLoginListener implements ApplicationListener {

private UserManager userManager;

// getter and setter ...

public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof AbstractAuthenticationEvent) {

if (event instanceof AbstractAuthenticationFailureEvent) {
// log or similar
}

if ( event instanceof AuthenticationSuccessEvent ){
AuthenticationSuccessEvent authenticationSuccessEvent = ( AuthenticationSuccessEvent ) event;
String username = authenticationSuccessEvent.getAuthentication().getName();
User user = userManager.getUserByUsername(username);
user.setLastLogin(new Date());
userManager.saveUser(user);
}

}
}

}


In the method "onApplicationEvent" I listen the event AbstractAuthenticationEvent, that Acegi publishes.
Next, I update the last login time, with the userManager.

The last step is setup my LastLoginListener in security.xml with the other Acegi beans.

<bean id="lastLoginListener" class="net.dahernan.common.security.LastLoginListener">
<property name="userManager" ref="userManager"/>
</bean>

Sunday 16 September 2007

Tip: Put result in session in Spring Web Flow

So, another tip with Spring Web Flow. Sometimes it's necessary put a result of bean-action in scope session, but in SWF 1.X doesn't have this feature, but you can make a simple action to do the work.

First, the flow definition:

<action-state id="saveProject">
<bean-action bean="projectManager" method="save">
<method-arguments>
<argument expression="flowScope.project" />
</method-arguments>
<method-result name="project" scope="request"/>
</bean-action>
<transition on="success" to="putInSession" />
</action-state>

<action-state id="putInSession">
<action bean="putInSessionAction">
<attribute name="sessionKey" value="project" />
</action>
<transition on="success" to="finish"/>
</action-state>


I call a bean-action "saveProject" and I put the result in request with key "project". Next, I execute the action "putInSession" and I set the attribute "sessionKey" with the value of the key "project", this mean thay the object to save in session is in the request with this key.

With this convention, here the Action implementation:

public class PutInSessionAction implements Action{

public Event execute(RequestContext context) throws Exception {

String key = (String) context.getAttributes().get("sessionKey");
Object value = context.getRequestScope().get(key);
context.getExternalContext().getSessionMap().put(key, value);

return new Event(this, "success");
}

}


This simple Action gets the object from the request and puts in session.

Sunday 2 September 2007

Tip: Output a success message in a subflow in Spring Web Flow

In Ajax applications is common output a success or error message (like Google Mail interface). With Spring Web Flow I can define subflows to do commons things and reuse parts of the application but if I want to output a success message, the natural way it's to define a view state.

This tip shows other way to output a message.

I have a subflow to add a new company.

<start-state idref="enterCompanyData"/>

<view-state id="enterCompanyData" view="people/ajax/company_add">
<render-actions>
<action bean="formAction" method="setupForm" />
</render-actions>
<transition on="submit" to="saveCompany">
<action bean="formAction" method="bindAndValidate" />
</transition>
</view-state>

<action-state id="saveCompany">
<bean-action bean="companyManager" method="save">
<method-arguments>
<argument expression="flowScope.company" />
</method-arguments>
</bean-action>
<transition on="success" to="finish">
<set attribute="message" value="'company.addCompany.success'" />
</transition>
</action-state>

<end-state id="finish">
<output-mapper>
<mapping source="requestScope.message" target="message" />
</output-mapper>
</end-state>


When I save a company in the action state "saveCompany", I set an atttibute named "message" with a value of String 'company.addCompany.success' (with a single quotes, otherwise the expression language thinks that is a Java Bean), this value is a key for i18n.

In the end state "finish", I have to map the attribute message to the output.

Next, in the root flow, I have to capture the message and put in the flash scope.

<subflow-state id="companyAdd" flow="company-add-flow"> 
<attribute-mapper>
<output-mapper>
<mapping source="message" target="flashScope.message"/>
</output-mapper>
</attribute-mapper>
<transition on="finish" to="companyList" />
</subflow-state>


Putting the message in the flash scope, allow to view the message until next event.

And the last step is show the message in JSP, you have to include this code, in all view states.

<c:if test="${not empty message}">
<fmt:message key="${message}"/>
</c:if>

Saturday 25 August 2007

Appfuse and the cost to start a new project

Long time ago that I use appfuse for my web applications projects, it's fantastic (thanks Matt).
Appfuse 2.0 is based in maven, and is one of the best improvements, this change add modularity to appfuse, the code of appfuse is in various modules (jars and wars). With this changes it loose some scope about what appfuse does and I have to run "mvn appfuse:fullsource" to view all source, and customize some classes.

Although appfuse do hard work to start, always is unavoidable make some changes to start, for example in last project I have to:
  • Update Jetty maven plugin for scan patterns.
  • Customize some Appfuse classes.
  • Customize some i18n features.
  • Add Spring Web Flow.
  • Customize CSS and Layout.
  • Delete struts-menu (with a simple menu.jsp it's enough for me).
  • Update some dependencies and resources.
  • Add some maven plugins like compress javascript and export database.
Some tasks are due to appfuse doesn't support a feature yet, and some are due to my personal requirements but the cost to start a new project it's too high yet.

Wednesday 15 August 2007

Playing with Inkscape

This is two samples that I have created with excelent ilustration software Inkscape.

I have followed some tutorials from Inkscape Tutorials and some screencast. It's really easy create simple and elegant icons.

The design isn't incompatible with backend development

Saturday 4 August 2007

Are social networks useful?

In other post I said that networks like delicious, had changed my habits in internet. I have read some entries about the wonderful Linkedin and Facebook, and I have decided to test them.

First, I have tested Facebook and tried to do contacts. I don't trust to give my email password, and I searched contacts manually but I don't felt lucky, not found any friend.

Next, Linkedin. I searched contacts who had worked with me and I found four contacts, but today no one has added me to his network, I don't believe that they really use Linkedin. If somebody wants to add me to his network this is my profile in Linkedin.

In general, the I don't have good impressions about this networks. The interface of this sites it's too complicated, there are too many options. I prefer the minimalist of delicious, maybe when I have more contacts, it could be useful, but nowadays the best network is my delicious network.

Saturday 23 June 2007

Holidays

I have three weeks!!!. One week to travel, and two weeks to be with my friends, go to the beach and whatever I want.
Goodbye work!!!

Sunday 10 June 2007

My Web 2.0 favorite apps

One thing I like to do is test Web 2.0 applications. Ajaxian is in my favorite feeds. But there are three applications that change my habits in the Web.

  • Delicious. All that things that could be interesting I save in delicious. And my network is one of best source of really interesting things.
  • Google Reader. Previously I used to read my feeds in Thunderbird at home and work, and I had to mark as a read many many feeds in both sites. Google Reader it's very useful with two clicks on firefox I have a new feed, and I share my starred items.
  • Last.fm. Usually, I listen many music at work, and last.fm help me to find new groups, and share with my friends. My profile tells me who are my favorite groups now. The Killers and Coldplay, are winning.

Saturday 2 June 2007

JSR 181 Web Service

In the last post I have used simple Web Service to test Spring-WS. Now I'm going to explain the implementation of this service.
The service is based in XFire and JSR 181 annotations.

First, the Book class, that represent the model.

package net.dahernan.model;

public class Book {

protected String title;
protected String isbn;
protected String author;
protected Double price;

// ... getters and setters
}


Next, the BookService class (yeah a class not an interface).

package net.dahernan.service;

import java.util.ArrayList;
import java.util.List;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;

import net.dahernan.model.Book;

@WebService
public class BookService {

protected Book getMockBook(){
Book book = new Book();
book.setAuthor("Matt Raible");
book.setTitle("Spring Live");
book.setIsbn("12345");
book.setPrice(12.22);
return book;
}

protected List getMockBooks(){
List result = new ArrayList();
Book book = new Book();
book.setAuthor("Matt Raible");
book.setTitle("Spring Live");
book.setIsbn("12345");
book.setPrice(12.22);
result.add(book);

book = new Book();
book.setAuthor("Martin Fowler");
book.setTitle("Planning Extreme Programming");
book.setIsbn("12346");
book.setPrice(18.00);
result.add(book);
return result;
}

@WebMethod
@WebResult(name="Book")
public Book findBook(@WebParam(name="isbn")String isbn) {
Book book = this.getMockBook();
book.setIsbn(isbn);
return book;
}

@WebMethod
@WebResult(name="Books")
public List getBooks() {
return getMockBooks();
}

}


The class is annotated with @WebService. The first two methods are Mocks, and "getBooks" and "findBooks" are the methods exposed in service.

It's good practice annotate the result with @WebResult and the parameters with @WebParams to obtain an human readable WSDL.

Finally, the services.xml to configure my POJO.

<beans>
<service xmlns="http://xfire.codehaus.org/config/1.0">
<name>BookService</name>
<namespace>http://dahernan.net/BookService</namespace>
<serviceClass>net.dahernan.service.BookService</serviceClass>
<serviceFactory>#jsr181ServiceFactory</serviceFactory>
</service>

<bean id="config"
class="org.codehaus.xfire.aegis.type.Configuration">
<property name="defaultExtensibleElements" value="false" />
<property name="defaultExtensibleAttributes" value="false" />
<property name="defaultNillable" value="false" />
<property name="defaultMinOccurs" value="1" />
</bean>

<bean name="jsr181ServiceFactory"
class="org.codehaus.xfire.annotations.AnnotationServiceFactory">
<constructor-arg ref="xfire.transportManager" index="0" />
<constructor-arg ref="config" index="1"
type="org.codehaus.xfire.aegis.type.Configuration" />
</bean>

</beans>


The generated WSDL looks like a contract-first WSDL ;)

Sunday 27 May 2007

Web Service client with Spring-WS and DuckTyping

This week I have tested Spring-WS, I'm interesting in Xpath support and I have done a simple client of BookService.
The BookService is a test of JSR 181 with XFire (perhaps I'll explain the implementation in other post).

One example of SOAP request/response:

SOAP Request:

<ns1:findBook xmlns:ns1="http://dahernan.net/BookService">
<ns1:isbn>12567</ns1:isbn>
</ns1:findBook>


SOAP Response:

<ns1:findBookResponse xmlns:ns1="http://dahernan.net/BookService">
<ns1:Book>
<author xmlns="http://model.dahernan.net">Matt Raible</author>
<isbn xmlns="http://model.dahernan.net">12567</isbn>
<price xmlns="http://model.dahernan.net">12.22</price>
<title xmlns="http://model.dahernan.net">Spring Live</title>
</ns1:Book>
</ns1:findBookResponse>


So, let's see the Spring-WS Client:

public class BookServiceClient {

private static final String MESSAGE =
"<ns1:findbook ns1="\"http://dahernan.net/BookService\"">" +
"<ns1:isbn>12567</ns1:isbn>" +
"</ns1:findbook>";

private WebServiceTemplate webServiceTemplate;

private XPathExpression xpathExp;

// ... getters and setters

public String getAuthor() {
StreamSource source = new StreamSource(new StringReader(MESSAGE));
DOMResult result = new DOMResult();
webServiceTemplate.sendAndReceive(source, result);
String author = xpathExp.evaluateAsString(result.getNode());

return author;
}


It's based in WebServiceTemplate (I like the Spring templates :), and XPathExpresion, the request is constant.
The response, first I build a DOM with response and next I evaluate the XPath Expresion.

And the Spring wiring.

<bean id="bookServiceClient" class="net.dahernan.example.BookServiceClient">
<property name="webServiceTemplate" ref="webServiceTemplate"/>
<property name="xpathExp" ref="xpathExp"/>
</bean>

<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<property name="defaultUri" value="http://localhost:8080/xfire_test/services/BookService"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.http.HttpUrlConnectionMessageSender"/>
</property>
</bean>

<bean id="xpathExp" class="org.springframework.xml.xpath.XPathExpressionFactoryBean">
<property name="expression" value="/ns1:findBookResponse/ns1:Book/dh:author"/>
<property name="namespaces">
<props>
<prop key="ns1">http://dahernan.net/BookService</prop>
<prop key="dh">http://model.dahernan.net</prop>
</props>
</property>
</bean>


The last step, is do a small test.

public class BookServiceClientTest extends AbstractDependencyInjectionSpringContextTests{

protected static Logger logger = Logger.getLogger(BookServiceClientTest.class);

protected String[] getConfigLocations() {
return new String [] {"ws-beans.xml"};
}

public void testClient(){
BookServiceClient client = (BookServiceClient) this.applicationContext.getBean("bookServiceClient");
String author = client.getAuthor();
logger.info("Author: " + author);
}

}


All, without stubs, It looks like great.

Wednesday 16 May 2007

Things that I'd like to test

Now I'm testing Mule, because I'm interesting in ESB (it's fantastic I hope spend some time writing a post about Mule). And when I'm tired, I read about Scrum and Agile.

There are a lot of things that I'd like to test but I don't have enough time. Here a bunch of things:
My delicious network and my feeds make that the list grows. I have to spend some time in an idea that make me rich.

Sunday 6 May 2007

Arid Framework or Simplifying Spring XML

Chris Richardson (author of Pojos in Action) in his blog tell us about Simplifying Spring XML with Arid Framework. This is a very interesting idea, and it's on the same line as actual trends about "Convention over Configuration".

This approach to the problem, it's based in autowire and custom namespace in Spring 2.0 XML.

I don't like especially autowire by type, it's useful for test proposes, but when you have two classes that implements the same interface, you must disabled. I see beginners developers crash with this, many times in test classes.

Another very useful thing about classic Spring XML, it's that you have a mirror of the architecture. You can use Spring IDE or another tool to see the real architecture, not an obsolete UML diagram. With annotations or conventions it's more difficult to see the architecture.

In my humble opinion, with expert developers Arid framework and other solutions about Convention over Configuration can be fantastic, but with beginners the best approach is the classic style.

Thursday 19 April 2007

First entry

This is my new blog, nowadays my old blog is for archive . I open this blog for two reasons, the first one, and the most important, is to improve my english, I have a poor english and I think this blog can help me.

And the second reason is because I still have something to tell about Java, Maven, Spring, SOA, Agile and me.