mercoledì 15 dicembre 2010

FreeMarker and custom parameters on templates

Sometime it's usefull to get some parameters from templates, for example, I use a parameter in an email template to store the subject of this mail.

FreeMarker has a specific directive to do this: ref_directive_ftl but the section about custom parameters don't show how to use this. Here is an example:
Template:
 <#ftl attributes={ "subject": "Registrazione"}>  
 <html>  
      <body>  
           Gentile utente  
.....

This is the java code to read the parameter:
 Template template = cfg.getTemplate(stemplate);  
 String subject = template.getCustomAttribute("subject");  

I spent the last 3 hours to find the correct form of ftl's attributes. I used attributes={ subject: Registrazione} and attributes="{subject: Registrazione}" and I get ris respectively this error:

 freemarker.core.ParseException: Could not evaluate expression: {subject : Registrazione} on line 1, column 18 in it/mail/Registration.html  
 Underlying cause: Variables are not available (certainly you are in a parse-time executed directive). The name of the variable you tried to read: subject in it/mail/Registration.html  
      at freemarker.core.FMParser.HeaderElement(FMParser.java:2831)  
      at freemarker.core.FMParser.Root(FMParser.java:2954)  
      at freemarker.template.Template.<init>(Template.java:149)  

and

 freemarker.core.ParseException: Expecting a hash of attribute names to values here. on line 1, column 18 in it/mail/Registration.html in it/mail/Registration.html  
      at freemarker.core.FMParser.HeaderElement(FMParser.java:2888)  
      at freemarker.core.FMParser.Root(FMParser.java:2954)  
      at freemarker.template.Template.<init>(Template.java:149)  
      at freemarker.cache.TemplateCache.loadTemplate(TemplateCache.java:448)  
      at freemarker.cache.TemplateCache.getTemplate(TemplateCache.java:361)  
      at freemarker.cache.TemplateCache.getTemplate(TemplateCache.java:235)  

Nice FreeMarker!

mercoledì 10 novembre 2010

Accept all SSL certificate (self signed certificate) in Java applications

When a java application tries to connect to a https service, the jvm check the server's certificate in order to test its validity. If you are using a self-signed certificate this maybe a problem. There are at least three way to go beyond this problem but, IMHO, I think the use of this class is the easiest way:

 import java.security.KeyManagementException;  
 import java.security.NoSuchAlgorithmException;  
 import java.security.cert.X509Certificate;  
 import javax.net.ssl.HostnameVerifier;  
 import javax.net.ssl.HttpsURLConnection;  
 import javax.net.ssl.SSLContext;  
 import javax.net.ssl.SSLSession;  
 import javax.net.ssl.TrustManager;  
 import javax.net.ssl.X509TrustManager;  
 public class UnTrustManager {  
      public static void acceptAllCertificates() throws NoSuchAlgorithmException, KeyManagementException {  
           TrustManager[] trustAllCerts = new TrustManager[1];  
           trustAllCerts[0] = new innerUnTrustManager();  
           SSLContext sc = SSLContext.getInstance("SSL");  
           sc.init(null, trustAllCerts, null);  
           HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());  
           HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {  
                public boolean verify(String hostname, SSLSession session) {  
                     return true;  
                }  
           });  
      }  
      public static class innerUnTrustManager implements TrustManager, X509TrustManager {  
           public X509Certificate[] getAcceptedIssuers() {  
                return null;  
           }  
           public void checkServerTrusted(X509Certificate[] certs, String authType)  
                     throws java.security.cert.CertificateException {  
           }  
           public void checkClientTrusted(X509Certificate[] certs, String authType)  
                     throws java.security.cert.CertificateException {  
           }  
      }  
 }  

sabato 9 ottobre 2010

Charset in Content-Type Header and Tomcat/Apache couple

When a resourse is served by Apache httpd via Tomcat, the Content-Type header is filled with the value defined in mime-mapping tag. You can found this value in the default web.xml under TOMCAT_HOME/conf.
For resource like html page the Content-Type header is text/html, regardless of charset encoding that the page was written.
You Apache, by default, is configured with AddDefaultCharset directive (In my Fedora 13 is UTF-8, but may vary between version and distribution you use) that add the charset declaration into Content-Type HTTP Header, if it hasn't one.

The problem:
If you write an HTML page with ISO-8859-1 and set correctly the meta tag into page as:
<meta http-equiv="Content-type" content="text/html; charset=iso-8859-1">
you obtain two different behaviours if your browser get this page directly from Tomcat, or from Apache via mod_jk:
1) If your browser talk directly with Tomcat, it can detect the encoding by meta tag into html page.
2) If you get the page from Apache, this one add the charset declaration into Content-Type HTTP Header with his default value from httpd.conf, then you are serving a iso-8859-1 page but your server declare it ad UTF-8.

To fix this mismatch you can follow two ways:
1) Modity the Tomcat's mime-mapping declaration (in default web.xml or overraid the default mapping in you web.xml):
   <mime-mapping>  
    <extension>html</extension>  
    <mime-type>text/html; charset=utf-8</mime-type>  
   </mime-mapping>  
   <mime-mapping>  
<extension>css</extension> <mime-type>text/css; charset=utf-8</mime-type> </mime-mapping> <mime-mapping>
<extension>js</extension> <mime-type>text/javascript; charset=utf-8</mime-type> </mime-mapping>
2) Change default charset in Apache httpd. Note that this work only for content-type either text/plain or text/html, and AddCharset and AddType directives to force this value in other file type (say .js or .css) don't work for resourses came from mod_jk (from tomcat).

I prefer the first way for two reasones: the know limitation explained on second point and the major liberty of personalization of web.xml configuration (you can serve, as example, from the same virtual host html page from two different webapps with different charser).

Reference:
AddDefaultCharset
AddCharset

venerdì 17 settembre 2010

openXReports broken on OpenX v.2.8.5

If you get this error generating Campaign Delivery Report on OpenX:

 Fatal error: Class 'DataObjects_Campaigns' not found in /var/www/openx/plugins/reports/oxReportsStandard/liveCampaignDeliveryReport.class.php on line 251  

You can repair it adding the red line below on OPENX_PATH/plugins/reports/oxReportsStandard/liveCampaignDeliveryReport.class.php:

 .  
 .  
 .  
 require_once LIB_PATH . '/Extension/reports/ReportsScope.php';  
 require_once MAX_PATH . '/lib/OA/Dll.php';  
 require_once MAX_PATH . '/lib/max/Dal/DataObjects/Campaigns.php';  
 /**  
  * A plugin to generate a report showing conversion tracking information,  
  * for the supplied date range. The report contains a single worksheet:  
  *  
 .  
 .  
 .  

martedì 14 settembre 2010

Google Maps Suggestion with YUI Library Example

This is an example of use Google Maps Suggestion, api version 3, in your site using YUI library.
The main problem was about to connect the query of ScriptNodeDataSource with his handler response, infact the callback that google maps returns not allow in his name the square bracket...
To test you can use wget. The first one is how google like callback name:


[dometec@precision2 tmp]$ wget -q -O - "http://www.google.com/maps/suggest?cp=20&hl=it&num=5&q=sapr&callback=callback" && echo
callback&&callback({suggestion:[{query:"Sapri, Italia",interpretation:{term:[{start:0,.......


The second one is how yui's ScriptNodeDataSource object named callback parameter:

[dometec@precision2 tmp]$ wget -q -O - "http://www.google.com/maps/suggest?cp=20&hl=it&num=5&q=sapr&callback=callback[1]" && echo
{suggestion:[{query:"Sapri, Italia",interpretation:{term:[{start:0,end:5,fea.............

In the last call the callback parameter in the response is absent, evaporated! :S
The "patch" is to overwrite the generateRequestCallback of ScriptNodeDataSource object to set an appropriate name and write your own callback function that refresh the AutoComplete widget.



dsScriptNode.generateRequestCallback = function () { return "&callback=callbackGMapsSuggestion"; };
...
callbackGMapsSuggestion = function (queryResult) {
  var r = {};
  r.results = queryResult.suggestion;
  //oAC is the instance of YUI AutoComplete widget
  oAC.handleResponse(null, r, null);
};


The complete HTML Test Page http://dev.zonablog.net/mapsuggestion.html:
 <html>  
      <head>  
           <title>Google Maps Suggestion with YUI Library Example</title>  
           <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
           <link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/2.8.1/build/logger/assets/skins/sam/logger.css">  
           <link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/2.8.1/build/fonts/fonts-min.css" />  
           <link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/2.8.1/build/autocomplete/assets/skins/sam/autocomplete.css" />  
           <script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/yahoo-dom-event/yahoo-dom-event.js"></script>  
           <script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/dragdrop/dragdrop-min.js"></script>  
           <script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/json/json-min.js"></script>  
           <script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/connection/connection-min.js"></script>  
           <script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/get/get-min.js"></script>  
           <script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/animation/animation-min.js"></script>  
           <script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/datasource/datasource-min.js"></script>  
           <script type="text/javascript" src="http://yui.yahooapis.com/2.8.1/build/autocomplete/autocomplete-min.js"></script>  
           <style type="text/css">  
                #myAutoComplete {  
                  width: 15em;  
                  padding-bottom: 2em;  
                }  
           </style>  
           <script type="text/javascript">  
                var dsScriptNode;  
                var oAC;  
                function init() {  
                     dsScriptNode = new YAHOO.util.ScriptNodeDataSource("http://www.google.com/maps/suggest?cp=20&hl=it&num=5&&");  
                     dsScriptNode.generateRequestCallback = function () { return "&callback=callbackGMapsSuggestion"; };  
                     dsScriptNode.responseSchema = { fields: ["query"] };  
                  oAC = new YAHOO.widget.AutoComplete("myInput", "myContainer", dsScriptNode);  
                  oAC.prehighlightClassName = "yui-ac-prehighlight";  
                  oAC.useShadow = true;  
                  oAC.generateRequest = function (sQuery) { return "q=" + sQuery; };  
                };  
                callbackGMapsSuggestion = function (queryResult) {  
                     var r = {};  
                     r.results = queryResult.suggestion;  
                     oAC.handleResponse(null, r, null);  
                };  
                YAHOO.util.Event.onDOMReady(init);  
           </script>  
      </head>  
      <body class="yui-skin-sam">  
           <h1>Google Maps Suggestion with YUI Library Example</h1>  
           <label for="myInput">Enter a location:</label>  
           <div id="myAutoComplete">  
                <input id="myInput" type="text">  
                <div id="myContainer"></div>  
           </div>  
      </body>  
 </html>  

Enjoy :)

martedì 7 settembre 2010

Merge PDF File with Ghostscript

Use this command to merge PDF fil using Ghostscript:

 $ gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=Merged.pdf 1.pdf 2.pdf 3.pdf 

sabato 4 settembre 2010

MySql and watch for data changes from shell

This is an useful command that I use where I need to watch data changes in a mysql table:


 watch -n 1 "echo \"select * from fnbl_user;\" | mysql --password=yourpassword --database=funambol"
I use the feauture of mysql client program that accept statements from standard input.
This command execute the select query from the specified table every second.

venerdì 3 settembre 2010

The magic Java Remote Debug string

When you have to debug an application with your prefered editor (like Eclipse :)), you can launch the java application with this string, don't worry if it is in local host or remote host:

 java ... -Xrunjdwp:transport=dt_socket,address=20118,server=y,suspend=n ...

and connect to server for debugging on port specified in address parameter.

The transport parameter specify what type of communication you are using to connect to the server, if you specify dt_socket, you have to set the server parameter to y. The JVM will stay listening on all network interface of server.

The last parameter (suspend) tell to the JVM if it have to wait the first connection from your IDE before start (y) or not (n).

venerdì 27 agosto 2010

Install Trac on Linux Fedora 13

Hands on how to install Trac on Fedora 13.

From root, install Trac and fcgid module for apache:
# yum install trac 
# yum install mod_fcgid

Create a test project, I take /tmp/test as my project folder:
# trac-admin /tmp/test initenv

And try it: start the server and navigate to http://localhost:8000/:
# tracd --port 8000 /tmp/test

It work, I hope :)
Create the folter for apache:
# trac-admin /srv/trac/zonablog deploy /tmp/test2
# mv /tmp/test2/htdocs/  /tmp/test/
# mv /tmp/test2/cgi-bin/ /tmp/test/
# rm -rf /tmp/test2
# chown apache.apache -R *

Edit this file /etc/httpd/conf.d/trac.conf.
Comment all content or remove and insert the row below:
 <Directory /tmp/test/>  
  Order allow,deny                                                                                      
  Allow from all                                                                                       
 </Directory>  
 ScriptAlias /trac/ /tmp/test/cgi-bin/trac.fcgi/  
 DefaultInitEnv TRAC_ENV /tmp/test/  

Move your logo image in /tmp/test/htdocs/logo.jpg
And modifi the /tmp/test/conf/trac.ini in section [header_logo]:
[header_logo]
...
src = site/logo.jpg*
...

Restart apache:
# /etc/init.d/httpd restart

navigate to http://localhost/trac

I hope you have saved some time :)
Domenico

mercoledì 25 agosto 2010

Install memcached and memcache PHP extension on Linux Fedora 13

From root, install memcached server and start it:
# yum install memcached  
# /etc/init.d/memcached start  
install php pear and memcache extension:
# yum install php-devel  
# yum install php-pear  
# echo "extension=memcache.so" > /etc/php.d/memcache.ini  
restart apache
# /etc/init.d/httpd start  
and test with php page that you can found in the memcache's distribution http://pecl.php.net/package/memcache (attention that you have to modify the php source to redefine you memcached server instance $MEMCACHE_SERVERS[] = 'localhost:11211';)

martedì 24 agosto 2010

Enable log SQL and SLOW SQL on MySQL

Open /etc/my.cnf and under [mysqld] section insert:

 [mysqld]
...
 # * Logging and Replication  
 #  
 # Both location gets rotated by the cronjob.  
 # Be aware that this log type is a performance killer.  
 log = /var/lib/mysql/log/sql.log  
 log_slow_queries = /var/lib/mysql/log/sql.slow.log  
 long_query_time = 2  

And restart mysqld instance.