Thursday, January 19, 2017

Install MS SQL Server on Debian Jessie (through Docker)

Recently Microsoft released some previews of the Linux version of SQL Server.

At present the supported Linux distributions are only Red Hat Enterprise Linux 7.2, Ubuntu 16.04 and SUSE Linux Enterprise Server v12 SP2.

Installing it in other distributions (I'm using Debian Jessie) can be successful, but surely more difficult.

An alternative in these cases is using a Docker container.

Microsoft provides a Docker image for the server part, so running the server is as simple as typing the following command:
docker run -e 'ACCEPT_EULA=Y' \
    -e 'SA_PASSWORD=<yourstrong Passw0rd>' \
    -p 1433:1433 -v <host directory>:/var/opt/mssql \
    -d microsoft/mssql-server-linux
More difficult is the installation of SQL Server Tools, needed for connecting and querying the server. In this case Microsoft doesn't provide a Docker image, so you can only install them on the supported platforms.

Fortunately we can build a docker image by ourself.

Using the following Dockerfile:
FROM ubuntu:16.04
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y curl apt-transport-https debconf-utils apt-utils
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
RUN curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list | tee /etc/apt/sources.list.d/msprod.list
RUN echo mssql-tools mssql-tools/accept_eula boolean Y|debconf-set-selections
RUN echo msodbcsql msodbcsql/accept_eula boolean true|debconf-set-selections
RUN apt-get update && ACCEPT_EULA=Y apt-get install -y mssql-tools unixodbc-dev-utf16
RUN ln -sfn /opt/mssql-tools/bin/sqlcmd-13.0.1.0 /usr/bin/sqlcmd 
RUN ln -sfn /opt/mssql-tools/bin/bcp-13.0.1.0 /usr/bin/bcp
RUN locale-gen en_US en_US.UTF-8
RUN locale-gen it_IT it_IT.UTF-8
RUN dpkg-reconfigure locales
Build the docker image:
docker build -t mssql-tools:latest .
And run it typing:
docker run -it mssql-tools:latest /bin/bash
Now in this container you can user the MS SQL Tools for connecting to the running server:
sqlcmd -S <ms sql server container IP> -U SA -P '<yourstrong Passw0rd>'
For finding the IP of the container running the SQL Server, you can type the following command on your host:
docker inspect mssql-server|grep IPAddress

Monday, February 4, 2013

Using PostgreSQL in Java without JDBC

JDBC is the Java starndard API for accessing relational databases. There is any good reason for not using it, directly or through a higher-level API/framework (Hibernate, JPA, etc.)? Usually not, but if you feel you need, probably it's a good reason.

My own reason is related to pgpool-II and its parallel mode. As far as I know (please write to me if I'm wrong), pgpool's parallel mode doesn't support the PostgreSQL extended query sub-protocol. Unfortunately the PostgreSQL JDBC Driver can use only that protocol. Even setting the JDBC Driver for using the V2 protocol doesn't solve the problem because other issues in the communication with pgpool.

The only solution I found is not using JDBC, but accessing PostgreSQL through the libpq C library. Of course I need to do it in Java, so I wrapped the libpq library in Java classes, using the SWIG tool.

You'll find the code of my experiments in this Github repository.

Let's go through the full process.

  1. Install SWIG, downloading from here, or using the correct package of your OS. I use Debian, so I just needed to install the swig package:
    apt-get install swig
    
  2. Prepare a SWIG interface file, describing the C functions you want to wrap. If you want to wrap a whole library, this task could be very simple, as you can simply include the C header files:
    pqswig.i:
    %module pq
    %{
    #include "/usr/include/postgresql/libpq-fe.h"
    %}
    
    %include "/usr/include/postgresql/libpq-fe.h"
    
  3. Use the SWIG command for generating the Java wrapper classes and the C SWIG wrapper functions:
    swig -java \
        -package com.benfante.experiments.libpqwrapper.swig \
        -outdir \
        ../../../generated/java/com/benfante/experiments/libpgwrapper/swig \
        pqswig.i
    In the same directory you'll find the pqswig_wrapper.c file. In the indicated path (../../../generated/java/com/benfante/experiments/libpgwrapper/swig, change it following your needs) you'll find the Java wrapper classes.
  4. Compile the pqswig_wrapper.c file:
    gcc -c pqswig_wrap.c -I /usr/lib/jvm/java-6-sun/include -I /usr/lib/jvm/java-6-sun/include/linux
  5. Build the dynamic library:
    ld -G pqswig_wrap.o -o libpqswig.so -lpq
  6. Copy (or link) the libpqswig.o file into a directory of the java.library.path. For example, copy it into the /usr/lib directory:
    cp libpqswig.so /usr/lib/
    That's all. Of course the previous steps are for a Linux OS. If you are using a different OS, read the SWIG documentation and FAQs (in particular the SharedLibraries section).
Now you can execute code like the following:
package com.benfante.experiments.libpgwrapper;

import com.benfante.experiments.libpqwrapper.swig.ConnStatusType;
import com.benfante.experiments.libpqwrapper.swig.ExecStatusType;
import com.benfante.experiments.libpqwrapper.swig.SWIGTYPE_p_pg_conn;
import com.benfante.experiments.libpqwrapper.swig.SWIGTYPE_p_pg_result;
import com.benfante.experiments.libpqwrapper.swig.pq;

public class App {

    public static void main(String[] args) {
        System.out.println(System.getProperty("java.library.path"));
        System.loadLibrary("pqswig");
        System.out.println("PQ Library Version: " + pq.PQlibVersion());
        SWIGTYPE_p_pg_conn connection = connectToPostgres("localhost", "5432", "test", "test", "test");

        SWIGTYPE_p_pg_result res = selectAllPerson(connection);

        printTuples(res);

        pq.PQclear(res);

        pq.PQfinish(connection);
    }

    private static SWIGTYPE_p_pg_conn connectToPostgres(String host, String port, String db, String username, String password) {
        SWIGTYPE_p_pg_conn connection = pq.PQconnectdb("postgresql://" + username + ":" + password + "@" + host + ":" + port + "/" + db);
        if (pq.PQstatus(connection) != ConnStatusType.CONNECTION_OK) {
            System.out.println("Connection to database failed: " + pq.PQerrorMessage(connection));
            exitNicely(connection);
        }
        return connection;
    }

    private static SWIGTYPE_p_pg_result selectAllPerson(SWIGTYPE_p_pg_conn connection) {
        SWIGTYPE_p_pg_result res = pq.PQexec(connection, "SELECT * FROM person");
        if (pq.PQresultStatus(res) != ExecStatusType.PGRES_TUPLES_OK) {
            System.out.println("SELECT failed: " + pq.PQerrorMessage(connection));
            pq.PQclear(res);
            exitNicely(connection);
        }
        return res;
    }

    private static void exitNicely(SWIGTYPE_p_pg_conn connection) {
        pq.PQfinish(connection);
        System.exit(0);
    }

    private static void printTuples(SWIGTYPE_p_pg_result res) {
        int nTuples = pq.PQntuples(res);
        int nFields = pq.PQnfields(res);
        for (int i = 0; i < nFields; i++) {
            System.out.printf("%-15s|", pq.PQfname(res, i));
        }
        System.out.println("");
        for (int i = 0; i < nTuples; i++) {
            for (int j = 0; j < nFields; j++) {
                System.out.printf("%-15s|", pq.PQgetvalue(res, i, j));
            }
            System.out.println("");
        }
    }
}

Saturday, November 14, 2009

My Devoxx 2009

Devoxx banner
The following is my schedule for the Devoxx conference. In red the presentations I will attend. If you would like to suggest me other presentations you would like to hear about from me, send me a line and I will try to attend them.

Sunday, August 9, 2009

Build or simply compile?

With Parancoe I already have a very productive environment for the development of my applications. I can have unit tests on most of the code, so I rarely need a full build and redeploy.

But sometimes it would be nice (and necessary) to just code and try the result in the browser. With JavaRebel you can do this simply compiling the new code, without the need of a full build and redeploy of your application.

For example, in my current parancoe-based project, I modified a method in the the HomeController, and some code (even adding a new method) in the UserProfileBo class.

Then I just recompiled the project, in 3 seconds:


NetBeans: Executing 'mvn -Dnetbeans.execution=true compiler:compile'
NetBeans: JAVA_HOME =/usr/lib/jvm/java-6-sun
Scanning for projects...
Searching repository for plugin with prefix: 'compiler'.
------------------------------------------------------------------------
Building minimark Web Application
task-segment: [compiler:compile]
------------------------------------------------------------------------
[compiler:compile]
Compiling 2 source files to /home/lucio/MyWorks/minimark/minimark/target/classes
------------------------------------------------------------------------
BUILD SUCCESSFUL
------------------------------------------------------------------------
Total time: 3 seconds
Finished at: Sun Aug 09 08:14:56 CEST 2009
Final Memory: 18M/144M
------------------------------------------------------------------------


When I refreshed the page in the browser, the log of my Tomcat showed:


JavaRebel: Reloading class 'com.benfante.minimark.controllers.HomeController'.
JavaRebel-Spring: Reconfiguring bean 'homeController' [com.benfante.minimark.controllers.HomeController]
JavaRebel: Reloading class 'com.benfante.minimark.blo.UserProfileBo'.
JavaRebel-Spring: Reconfiguring bean 'userProfileBo' [com.benfante.minimark.blo.UserProfileBo]


Notice the classes not only have been reloaded, but also the spring-managed annotation-configured beans have been reconfigured.

The configuration of JavaRebel (in this case) is very easy.

In my Maven pom.xml:



org.zeroturnaround
javarebel-maven-plugin


generate-rebel-xml
process-resources

generate






The Tomcat configuration is:


CATALINA_OPTS="-XX:PermSize=32m -XX:MaxPermSize=200m -Xmx256m -Dfile.encoding=UTF-8 -noverify -javaagent:/home/lucio/local/javarebel-2.0/javarebel.jar -Drebel.spring_plugin=true"

Monday, May 25, 2009

Gregorio


Gregorio
Inserito originariamente da Lucio Benfante
Un benvenuto a Gregorio, fratellino di Carlo e Silvia, che gli fanno tanti auguri e non vedono l'ora che arrivi a casa.

Sì, al momento è tranquillo come appare, speriamo continui così

Tuesday, May 5, 2009

Mutable authorities with Spring Security and CAS

Recently I worked on an application with the following requisite:

The logged user must select its current role among the roles for which he's authorized.


A simple requisite, and (apparently) it's easy to implement it with Spring Security: write an UserDetails class in which you can select the returned authority(ies). For example:


public class LoggedUserWithSelectableRole extends User {
private GrantedAuthority currentAuthority;

public LoggedUserWithSelectableRole(String username, String password,
boolean enabled, GrantedAuthority[] authorities) throws IllegalArgumentException {
super(username, password, enabled, authorities);
}

public void setCurrentAuthority(GrantedAuthority currentAuthority) {
this.currentAuthority = currentAuthority;
}

@Override
public GrantedAuthority[] getAuthorities() {
if (Arrays.asList(super.getAuthorities()).contains(currentAuthority)) {
return new GrantedAuthority[] {currentAuthority};
} else {
return new GrantedAuthority[0];
}
}

public GrantedAuthority[] getAllAuthorities() {
return super.getAuthorities();
}
}


Now you can select an authority for the logged user (for example, in a controller):


@RequestMapping
public String selectRole(@RequestParam(value = "role") int role) {
LoggedUserWithSelectableRole user =
(LoggedUserWithSelectableRole) SecurityContextHolder.getContext().
getAuthentication().getPrincipal();
user.setCurrentAuthority(user.getAllAuthorities()[role]);
return "redirect:/";
}


Unfortunately this is not sufficient, as the authorities used by Spring Security for checking the user authorization are not (usually) stored in the principal object, but it the Authentication object.

It would be nice to write something like:


/* WARNING: The method setAuthorities doesn't exist */
SecurityContextHolder.getContext().getAuthentication().
setAuthorities(user.getAuthorities());


But the Authentication token is mostly immutable, so the setAuthorities doesn't exist. Worst, in the AbtractAuthenticationToken class, the base class of most of the token implementations, the authorities attribute is private, so you can't easily implement by yourself an alternative token implementation extending the original token class.

In our application we are using CAS. The only solution I found (as far as I know...please send me a line if you see a better solution) was to extend the CasAuthenticationToken, provinding a costructor for coping an existing token (of course of the same type):


public class UpdatableCasAuthenticationToken extends CasAuthenticationToken {

private final int keyHash;

public UpdatableCasAuthenticationToken(CasAuthenticationToken token, GrantedAuthority[] authorities) {
super("BOH", token.getPrincipal(), token.getCredentials(), authorities, token.getUserDetails(), token.getAssertion());
this.keyHash = token.getKeyHash();
}

@Override
public int getKeyHash() {
return this.keyHash;
}

}


As you can see, we also need to hide attributes and override methods not modifiable through the constructor of the base class.

Now I can substitute the original token with the modified one:


@RequestMapping
public String selectRole(@RequestParam(value = "role") int role) {
LoggedUserWithSelectableRole user =
(LoggedUserWithSelectableRole) SecurityContextHolder.getContext().
getAuthentication().getPrincipal();
user.setCurrentAuthority(user.getAllAuthorities()[role]);
SecurityContextHolder.getContext().setAuthentication(
new UpdatableCasAuthenticationToken(
(CasAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(),
user.getAuthorities()));
return "redirect:/";
}


As CAS ha no concerns with the user roles, I think CasAuthenticationToken should provide a way for updating authorities, and maybe the authorites attribute of AbstractAuthenticationToken should be declared as protected.

Sunday, March 8, 2009

Cantucci

Oggi ho provato un nuovo "algoritmo" culinario: i cantucci. Ok, siamo un po' fuori stagione...ma non si può mica sempre aspettare Natale, no? :)

La ricetta originale l'ho presa da sito Misya.info, con gli opportuni adattamenti.

Partiamo dagli ingredienti:Ingredienti per i cantucci
  • 270g di farina "0"

  • 200g di zucchero

  • un cucchiaino abbondante di lievito in polvere

  • un bacello di vaniglia

  • due uova intere

  • 150g di mandorle

Sbattere le uova.Uova da sbattereI "diti" dei cantucci
I "diti" dei cantucciAggiungere la farina, lo zucchero, il lievito, il contenuto del bacello di vaniglia e un pugno di mandorle.Impastare fino ad ottenere un impasto abbastanza sodo, eventualmente aggiungendo un po' di farina se dovesse risultare troppo appiccicoso.

Aggiungere la scorza dell'arancia e le mandorle. Formare due "diti" su una teglia ricoperta da carta da forno.


Tagliare i "diti"Cuocere in forno per circa 30 minuti a 180°C.

Tagliare i diti diagonalmente per formare i cantucci.

Infornare per un'altra quindicina di minuti, per far asciugare bene anche l'interno.
Mangiare. :P
I cantucci sono prontiI miei cantucci

Saturday, January 3, 2009

Tiles 2, a cheaper configuration

In a previous post I described how to use Tiles 2 in a Parancoe/Spring MVC project. What is really irritating for me in Tiles is its configuration file, a long list of almost identical XML fragments. Moreover that configuration rarely needs to be changed, so it's in practice useless, and just a waste of time (and effort) during the development.

If your application, as usually, has a main layout, and only few pages adopt a specific layout, I think there could be an easy and pleasant solution.

I defined a new view class (CheapTilesView) that can be used with an UrlBasedViewResolver:


<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.parancoe.plugin.tiles.CheapTilesView"/>
</bean>


Now the Tiles configuration file could be simply:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
<definition name="template.main" template="/WEB-INF/tiles/templates/main.jsp">
<put-attribute name="header" value="/WEB-INF/jsp/header.jsp"/>
<put-attribute name="menu" value="/WEB-INF/jsp/menu.jsp"/>
<put-attribute name="footer" value="/WEB-INF/jsp/footer.jsp"/>
</definition>
</tiles-definitions>


(compare with the configuration of the previous post)

All the omitted definitions are automatically created at runtime using the URL. For example, if the URL is admin/conf and a definition with that name doesn't already exist in your configuration file, the CheapTilesView class will generate (at runtime) this for you:


<definition name="admin/conf" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/admin/conf.jsp"/>
</definition>


So in you configuration file you only need to write the definitions of your (usually few) pages with a specific layout.

The conventions used by the CheapTilesView can be customized passing some attributes to the view resolver. The following are the default values:


<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.parancoe.plugin.tiles.CheapTilesView"/>
<property name="attributesMap">
<map>
<entry key="org.parancoe.plugin.tiles.CheapTilesView.DEFAULT_TEMPLATE" value="template.main"/>
<entry key="org.parancoe.plugin.tiles.CheapTilesView.DEFAULT_ATTRIBUTES" value="main"/>
<entry key="org.parancoe.plugin.tiles.CheapTilesView.DEFAULT_PREFIX" value="/WEB-INF/jsp/"/>
<entry key="org.parancoe.plugin.tiles.CheapTilesView.DEFAULT_SUFFIX" value=".jsp"/>
</map>
</property>
</bean>


The class is available in the Parancoe svn repository. Very soon it will be released as a Parancoe plugin. Stay tuned.

Tuesday, December 30, 2008

JavaDay 2009 a Roma

Il giorno 24 Gennaio 2009 parteciperò al JavaDay 2009 a Roma.

Se ti interessa fare due chiacchiere a proposito dei prossimi sviluppi di Parancoe, Scarabocio o JSlideShare, contattami durante la mia presentazione sull'uso dei controller annotati in Spring 2.5, o mandami una mail.


Javaday Roma III Edizione


Se vi interessa fare il viaggio insieme o cenare assieme la sera antecedente al JavaDay, trovate le informazioni qui: http://javadayroma.wikispaces.com/Treno

Thursday, December 11, 2008

Using Tiles 2 in a Prancoe project

First of all add the Tiles dependency to your pom.xml:


<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-core</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-jsp</artifactId>
<version>2.1.0</version>
</dependency>


Specify the places of the Tiles configurations and the Tiles view resolver in your parancoe-servlet.xml file:


<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles/defs/default.xml</value>
</list>
</property>
</bean>

<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
<!-- Default values for prefix and suffix
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
-->
</bean>


Add the /WEB-INF/tiles/defs/default.xml file with the definitions of your views:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>

<definition name="template.main" template="/WEB-INF/tiles/templates/main.jsp">
<put-attribute name="header" value="/WEB-INF/jsp/header.jsp"/>
<put-attribute name="menu" value="/WEB-INF/jsp/menu.jsp"/>
<put-attribute name="footer" value="/WEB-INF/jsp/footer.jsp"/>
</definition>

<definition name="login" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/login.jsp"/>
</definition>

<definition name="admin/conf" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/admin/conf.jsp"/>
</definition>

<definition name="admin/index" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/admin/index.jsp"/>
</definition>

<definition name="admin/logs" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/admin/logs.jsp"/>
</definition>

<definition name="admin/spring" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/admin/spring.jsp"/>
</definition>

<definition name="admin/users/list" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/admin/users/list.jsp"/>
</definition>

<definition name="admin/users/edit" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/admin/users/edit.jsp"/>
</definition>

<definition name="message" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/message.jsp"/>
</definition>

<definition name="genericError" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/genericError.jsp"/>
</definition>

<definition name="accessDenied" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/accessDenied.jsp"/>
</definition>

<definition name="welcome" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/welcome.jsp"/>
</definition>

<definition name="404" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/404.jsp"/>
</definition>

<definition name="500" extends="template.main">
<put-attribute name="main" value="/WEB-INF/jsp/500.jsp"/>
</definition>

</tiles-definitions>


Add the template in /WEB-INF/tiles/templates/main.jsp:


<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<%@ include file="/WEB-INF/jsp/common.jspf" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<%@ include file="/WEB-INF/jsp/head.jspf" %>
</head>
<body>
<div id="nonFooter">
<tiles:insertAttribute name="header"/>
<div id="content">
<div id="content_main">
<tiles:insertAttribute name="main"/>
</div>
<tiles:insertAttribute name="menu"/>
</div>
</div>
<tiles:insertAttribute name="footer"/>
</body>
</html>


Now You can simplify your JSP pages, removing from them all the layout-related parts. For example the welcome page (/WEB-INF/jsp/welcome.jsp) was:


<%@ include file="common.jspf" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<%@ include file="head.jspf" %>
</head>
<body>
<div id="nonFooter">
<jsp:include page="header.jsp"/>
<div id="content">
<div id="content_main">
<c:choose>
<c:when test="${requestScope.lang eq 'it'}">
Questa è l'applicazione template per il framework
<a href="http://wwww.parancoe.org">Parancoe</a>.<br />
<br />
Da questo punto di partenza puoi iniziare a costruire la
tua nuova applicazione, sfruttando tutti i benefici che
derivano dall'uso di Parancoe.<br />
<br />
Per maggiori informazioni visita il sito di Parancoe:<br />
<br />
<a href="http://wwww.parancoe.org">http://wwww.parancoe.org</a>.<br />
</c:when>
<c:otherwise>
This is the template application of the
<a href="http://wwww.parancoe.org">Parancoe</a> framework.<br />
<br />
From this starting point you can build your own application,
with all benefits of the using of the Parancoe Framework.<br />
<br />
For more infos, visit the Parancoe framework Web site:<br />
<br />
<a href="http://wwww.parancoe.org">http://wwww.parancoe.org</a>.<br />
</c:otherwise>
</c:choose>
</div>
<jsp:include page="menu.jsp"/>
</div>
</div>
<jsp:include page="footer.jsp"/>
</body>
</html>


Now it's just:


<%@ include file="/WEB-INF/jsp/common.jspf" %>
<c:choose>
<c:when test="${requestScope.lang eq 'it'}">
Questa è l'applicazione template per il framework
<a href="http://wwww.parancoe.org">Parancoe</a>.<br />
<br />
Da questo punto di partenza puoi iniziare a costruire la
tua nuova applicazione, sfruttando tutti i benefici che
derivano dall'uso di Parancoe.<br />
<br />
Per maggiori informazioni visita il sito di Parancoe:<br />
<br />
<a href="http://wwww.parancoe.org">http://wwww.parancoe.org</a>.<br />
</c:when>
<c:otherwise>
This is the template application of the
<a href="http://wwww.parancoe.org">Parancoe</a> framework.<br />
<br />
From this starting point you can build your own application,
with all benefits of the using of the Parancoe Framework.<br />
<br />
For more infos, visit the Parancoe framework Web site:<br />
<br />
<a href="http://wwww.parancoe.org">http://wwww.parancoe.org</a>.<br />
</c:otherwise>
</c:choose>

Thursday, November 13, 2008

Building an AJAX chat with Parancoe and DWR

The AJAX integration through DWR 3 is not the main feature in Parancoe, but it's easy and funny. Let's see how simple is building a Web chat.

Starting from a project generated with Maven using the Parancoe Web Archetype, you need to add the Parancoe DWR Plugin to the dependencies in your pom.xml:


<dependency>
<groupId>org.parancoe</groupId>
<artifactId>parancoe-plugin-dwr</artifactId>
<version>2.0.2</version>
</dependency>


Then add the /dwr/* pattern to the mapping of the parancoe servlet in your web.xml.

Now DWR is ready to be used in your application. You check it building and deploying your application, and pointing your browser to <your_base_address>/dwr/index.html. You should see the DWR Test Page.

Then add a class with methods (a single method in this example) that will be invoked through AJAX:


package com.mycompany.testapp.ajax;

import org.directwebremoting.Browser;
import org.directwebremoting.annotations.RemoteMethod;
import org.directwebremoting.annotations.RemoteProxy;
import org.directwebremoting.ui.dwr.Util;
import org.springframework.stereotype.Component;

@Component
@RemoteProxy(name = "chat")
public class Chat {

@RemoteMethod
public void send(final String nickname, final String message) {
Browser.withCurrentPage(new Runnable() {
public void run() {
Util.addRows("chatLog", new String[][]{{nickname, message}});
}
});
}
}


Simple, isn't it? ...but powerful. When invoked that method will add a row to the table with id chatLog, in all browsers that are visualizing that page.

Let's see the page chat.jsp in which that method is invoked:


<%@ include file="WEB-INF/jsp/common.jspf" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html>
<head>
<%@ include file="WEB-INF/jsp/head.jspf" %>
<script src="${cp}/dwr/interface/chat.js" type="text/javascript"/>
<script src="${cp}/dwr/engine.js" type="text/javascript" />
<script src="${cp}/dwr/util.js" type="text/javascript" />
<title>Parancoe DWR chat</title>
</head>
<body>
<h1>DWR Chat</h1>

<table id="chatLog">
<thead>
<tr><th>Nickname</th><th>Message</th></tr>
</thead>
<tbody> </tbody>
</table>

<form id="chatForm" method="post" action="/sendMessage">
Nickname: <input id="nickname" type="text" /><br/>
Say: <input id="say" type="text" /><br/>
<input type="submit">
</form>

<script type="text/javascript">
function bindUI() {
$('chatForm').observe('submit', chatSubmit);
}

function chatSubmit(event) {
event.stop();
chat.send($F('nickname'), $F('say'));
}

dwr.engine.setActiveReverseAjax(true);
document.observe('dom:loaded', bindUI);
</script>
</body>
</html>


In your parancoe-servlet.xml file add the following configuration for enabling the active reverse AJAX in DWR:






Build and deploy your application. Open multiple windows of your browser(s) to <your_base_address>/chat.jsp, and start chatting:



Have fun with Parancoe!

Saturday, November 8, 2008

Parancoe 2.0

Last week the Parancoe Team (me and other smart people :) ) released the version 2.0 of the Parancoe meta-framework. With this release Parancoe achieved a great level of maturity.

In the next weeks, starting with this post, I will demonstrate how easy and pleasant is to develop applications with Parancoe.

First demonstration! :) How difficult is to start a new project with Parancoe? No difficult at all. Install Maven and type the following command:

mvn archetype:create -DarchetypeGroupId=org.parancoe \
-DarchetypeArtifactId=parancoe-webarchetype \
-DarchetypeVersion=2.0.1 \
-DgroupId=com.mycompany \
-DartifactId=testApp \
-DpackageName=com.mycompany.testapp

It will generate a new complete project ready for your next development. I repeat, complete, the new application is already working, you can build and deploy it on your application server and use it. You'll see a simple layout, administrative tasks, debug information in page (when deployed in development mode), user authentication and authorization, user management.

With a good IDE :) the start-up task is even easier. Watch this my previous, still valid, screen-cast.

Don't miss to read the new Parancoe Reference Guide, both in HTML and in PDF.

Have fun!

Monday, July 21, 2008

PDF Unencrypting

Updated 07/29/2008: added the copy of the bookmarks (index) from the original document.


Usually, when you buy a PDF book, it's encrypted and protected by a password. No problem, I agree with authors and publishers that need to protect their work, even if this technique is a very poor protection.

Unfortunately usually some portable readers, like my PRS-505, don't have encryption/password support, so you can't upload those PDFs on them.

So you need to unencrypt the PDF for reading it on the device, a perfectly legal operation if you legally bought the book.

The easiest way to unencrypt a PDF should be to use the pdftk command line tool:

pdftk abook.pdf input_pw your_password_here output abook_unencrypted.pdf

Unfortunately it always emits this error:

Error: Failed to open PDF file:
abook.pdf
OWNER PASSWORD REQUIRED, but not given (or incorrect)

Of course the password was correct and I tried with different combinations of input/owner/user password parameters. I think it's a bug of pdftk (version 1.41).

So I wrote a small Java program for unecrypting my files:

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.SimpleBookmark;
import java.io.FileOutputStream;
import java.io.IOException;

public class Unencrypt {
public static void main( String[] args )
throws IOException, DocumentException {
String inFile = args[0];
String outFile = args[1];
String password = args[2];
PdfReader pdfReader = new PdfReader(inFile, password.getBytes());
Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileOutputStream(outFile));
document.open();
for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
PdfImportedPage importedPage = copy.getImportedPage(pdfReader, i);
copy.addPage(importedPage);
}
copy.setOutlines(SimpleBookmark.getBookmark(pdfReader));
document.close();
pdfReader.close();
}
}
For executing it, download this file, and type:

java -cp bpdf.jar com.benfante.bpdf.Unencrypt \
abook.pdf abook_unencrypted.pdf \
your_password_here

*WARNING*: I'm not responsible of the use you can do of this code. It's not intended as a tool for infringing copyrights, just for reading PDFs you legally owns on devices that don't support encrypting.

Friday, July 18, 2008

Pattern matching

Lo so, è un oszvnrioseae baanle, ma sepsso il nstoro celvelro fiouznna mtolo mliego di qlsaauisi cotemupr. Ad emspeio, a meno che il vrosto clevlreo non aibba qlachue pomeblra, dsvtoere eesrse peatentertfme in gdaro di lrggeee qeusto tteso, anhce se le lrtetee dllee plraoe, a parte la pirma e l'ulmita, snoo sttae messe alla rnfiusa. Quetso adcace perhcè qnaduo lgeaimgo in rtlaeà non psatemiro aioetntzne alle sngiole ltrteee, ma alla porala nel suo clspemoso.

Se volete giocare a ricombinare le parole di vostri testi, provate questo piccolo programmino che ho scritto:


Scarica questo file se vuoi dare un'occhiata ai sorgenti (rilasciati sotto Apache License, Version 2.0).

Questa e molte altre informazioni, e alcuni suggerimenti di miglioramento delle proprie capacità di apprendimento, le potete trovare in un interessante libro che sto leggendo: "Pragmatic Thinking and Learning" di Andy Hunt.

Update 08-14-2008: I just finished to read this book, of course on my PRS-505. It's a great book, a must-to-read if you need to be a continuous learner. And if you are in the IT business, of course you need to be. I'm a self-employed, mostly home-based, consultant and developer: the "Manage Focus" chapter is illuminating, and very helpful for trying to enhance the productivity of my work environment. In general the book is perfect for acquiring consciousness of your learning paths and deficiencies, with a lot of good tips for improving yourself. What I bought from the book? At present, I started writing "Morning Pages"; I already have a two monitor desktop, and as a Linux user I'm already used to virtual desktop; limiting "down" time and being conscious of it; caring of distractions; trying a better deliberate reading and acquiring of information.

Tuesday, July 8, 2008

Reading PDFs on a PRS-505

Update 07/28/2008: maybe the conversion PDF to LRF is obsolete on the PRS-505. With this firmware update the PDFs are rendered much much better (but still not better than the following conversion).




Since some months I'm an happy user of a Sony Portable Reader System (PRS-505).


It's a fantastic device, and actually I can comfortably read digital articles and books, instead of burning my eyes in front of a lightly monitor.

I can even use it with Linux, thanks to Calibre.

The PRS-505 can natively read PDF files, but the rendering is not always appropriate, and it's very difficult to read long text without headaches. So, I usually convert them from PDF to LRF.

Look at the result. On the left the original PDF. On the right the same page in the resulting LRF.


The conversion is very easy. You mainly need Ghostscript, for embedding all fonts in the PDF, and the pdflrf converter.

I wrote a simple script for easily run them with the correct parameters:

#!/bin/sh
# pdflrf_converter.sh by Lucio Benfante

gs -dSAFER -dNOPLATFONTS -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
-dCompatibilityLevel=1.4 -dPDFSETTINGS=/printer \
-dCompatibilityLevel=1.4 -dMaxSubsetPct=100 \
-dSubsetFonts=true -dEmbedAllFonts=true \
-sOutputFile=$1.embedding -f $1

pdflrf -r --rotation="0" --colors=8 -i $1.embedding -o $1.lrf

rm $1.embedding

Launch it with passing your PDF file as its single parameter:
pdflrf_converter.sh myBook.pdf

Please let me know if it's useful for you, or if you could find a better set of parameters for gs/pdflrf.

Thursday, March 20, 2008

Start a new Web project with the Parancoe Web meta-framework and NetBeans 6.1

Starting new Web project using the Parancoe meta-framework is very easy and fast. Even more if you are using a good IDE. Watch at this screencast, in which I create a new project with Parancoe and NetBeans 6.1.










Download the screen cast at the maximum resolution.

Monday, November 19, 2007

Next conferences

Lot of conferences I'll attend and present in this end-of-the-year.

In chronological order:
I hope to meet you in at least one of them.

Monday, October 15, 2007

JavaDay in Turin

Next Saturday I'll speak at the JavaDay in Turin.

My presentation will show that the following code can be a fully functional Data Access Object (DAO):

Note, not any other code or configuration to write, just that interface: NO code...NO bugs...more FUN! :)

See you in Turin...

(If you can't...look at the Parancoe site)

Monday, September 3, 2007

JUG Events

Estate abbastanza produttiva...sole, mare, spiaggia, ombrellone...e sviluppo di JUG Events!

Cos'è JUG Events? E' soprattutto la scusa per sperimentare con Parancoe, quindi principalmente con Hibernate/JPA, Spring, Spring MVC e Maven. Ma anche con JCaptcha, JavaMail, Velocity, Plextile, e chi più ne ha, più ne metta.

A parte la sperimentazione, che comunque ha portato nuove idee e sviluppo per Parancoe, l'applicazione può essere utile, quindi l'ho messa online a disposizione dei JUG che vorranno usarla:

www.jugevents.org

Se invece volete studiarne i sorgenti, li trovate nel repository Subversion di Parancoe.

Aggiornamento: JUG Events ha ora un proprio progetto separato per lo sviluppo su Google Code. jugevents.googlecode.com

Friday, July 27, 2007

Iterare il non iterabile in Java

Vi è mai capitato di avere un contenitore di oggetti, che però non sia implementato come Collection? A me purtroppo sì.

Abbondanti esempi li si trova nella libreria XOM. In tale libreria, ad esempio, il metodo Element.getChildElements() restituisce un oggetto Elements, che non è una Collection, ma ha semplicemente i metodi get(index) e size().

L'unico modo per iterare sugli elementi in esso contenuti è scrivere qualcosa del genere:

for(int i=0; i < elements.size(); i++) {
Element element = elements.get(i);
}

Dato che non implementa l'interfaccia Iterable, ad esempio, non si può usare il comodo "enhanced for" del JDK 5 per scrivere:

for(Element element: elements) {
// etc...
}

Per superare tale problema ho scritto la classe Iterabletor, che aggiunge ad una qualunque classe l'interfaccia e le capacità di un Iterable. Si può quindi scrivere:

Potete scaricare tutto il codice dal mio sito, nella mini-libreria Utilities.

Maggiori dettagli in questo post nel sito del JUG Padova.