jueves, 23 de febrero de 2012

Spring MVC 3.0 y Maven

For this example I'm using MacBook Pro with Mac OS x 10.7.2, SpringSource Tool Suite  2.8.1 and Maven 2.0

First of all, we have to create a maven project.

Next check the first checkbox to avoid creating the application with a archetype.

The code of the file pom.xml is the following(Notice that I added dependencies and plugins to deploy the app on Jetty)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example.web</groupId>
    <artifactId>SF</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <build>
        <finalName>AplicacionWeb</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>3.0.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

Next you have to run eclipse:eclipse to run the project and download the libraries to your project.

After this, you have to refresh the project. 

Next, create the package com.example.model.
Into this package you have to create the a Java class named Product. This class should implements Serializable. Also, it contains the following code:

package com.example.model;

import java.io.Serializable;

public class Product implements Serializable{
    private static final long serialVersionUID = 1L;
    private String name;
    private Double price;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Double getPrice() {
        return price;
    }
    public void setPrice(Double price) {
        this.price = price;
    }
}

Next, create a package named com.example.service
Into this package create an interface named ProductService.
This interface have two functions.
ListgetAllProducts()       -- To retrieve all the products
void addProduct(Product product)  -- To add a product.

This is the code of the ProductService:
package com.example.service;

package com.example.service;

import java.util.List;

import com.example.model.Product;

public interface ProductService {
    List<Product> getAllProducts();
    void addProduct(Product product);
}

The we have to implement the Interface, hence we create a new package named com.example.impl This package will contain a class named ProductServiceImpl. This is a service class, so it implements the @Service annotation. This is the code for ProductServiceImpl.java

package com.example.impl;

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

import org.springframework.stereotype.Service;

import com.example.model.Product;
import com.example.service.ProductService;
@Service
public class ProductServiceImpl implements ProductService {
    List products=new ArrayList();
   
    public List getAllProducts() {
        return products;
    }
   
    public void addProduct(Product product) {
        products.add(product);
    }
}



Next, we have to create the controller.
Create a package named com.example.controller. Into this package you have to create a Class named ProductController:
package com.example.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.example.model.Product;
import com.example.service.ProductService;

@Controller
@RequestMapping(value="product")// This is also the path of the URL after the App
public class ProductController {
    @Autowired
    private ProductService productService;
  
    /*
     * When a link from the app calls viewAllProducts this function is called.
     * Also the list object is updated with the use of the function addObject and
     * the variable products
     */
    @RequestMapping(value="listProducts",method=RequestMethod.GET)
    public ModelAndView viewAll(){
        ModelAndView mav=new ModelAndView();
        mav.setViewName("list");//The name of the JSP page
        mav.addObject("products",productService.getAllProducts());
        return mav;
    }
  
    /*
     * When a link from the app calls newProduct this function is called.
     * Also the product is added to the current list of products. Also a new empty
     * instance of the object is created.
     */
    @RequestMapping(value="newProduct",method=RequestMethod.GET)
    public ModelAndView newproduct(){
        ModelAndView mav=new ModelAndView();
        mav.setViewName("new");//The name of the JSP page
        mav.addObject("product",new Product());
        return mav;
    }
  
    /*
     * When a link from the app calls newProduct this function is called.
     * Also the product is added to the current list of products. Also a new empty
     * instance of the object is created.
     */
    @RequestMapping(value="addProduct",method=RequestMethod.POST)
    public String add(@ModelAttribute(value="product") Product product){
        productService.addProduct(product);
        return "redirect:listProducts.htm";
    }
}



After this, we have to create the following route of directories webapp/WEB-INF/jsp  into src/main.
Into webapp/WEB-INF we have to create two xml files web.xml and dispatcher-servlet.xml.
web.xml will be configurated to support the Servlet for the use of Springfrmework also its mapping.
This is code for web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

The file dispatcher-server.xml has the springframework configuration to locate the implementation of the services and controllers. Also it is used to specify the directories where the jsp are stored.
This is the source code of dispatcher-server.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:context="http://www.springframework.org/schema/context"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
                             http://www.springframework.org/schema/beans/spring-beans.xsd
                             http://www.springframework.org/schema/context
                             http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.example.controller"/>
<context:component-scan base-package="com.example.impl"/>
<context:annotation-config />     
<bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
          <property name="prefix"><value>/WEB-INF/jsp/</value></property>
          <property name="suffix"><value>.jsp</value></property>
          </bean>    
</beans>


Next, we have to create the JSP pages into webapp/WEB-INF/jsp.
 The information will be displayed with the help of SpringFramework JSTL.
Next, we have to create a JSP named index.jsp to redirect the app to the list of products. So that, create a page named index.jsp at webapp directory with the following code:
<jsp:forward page="product/listProducts.htm"></jsp:forward>


Create a JSP page named as  include.jsp. This page will be used to save the calls to the JSTL libraries. This is the code for include.jsp:
<%@page isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>


Next, create a JSP named list.jsp
This page will display the information of the products in memory.<%@ include file="include.jsp"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Product List</title>
</head>
<body>
<table>
<tr>
<td>Product Name</td>
<td>Price</td>
</tr>
<c:forEach items="${products}" var="product">
<tr>
<td>${product.name}</td>
<td>${product.price}</td>
</tr>
</c:forEach>
</table>
<a href="/SF/product/newProduct.htm">Add New Product</a>
</body>
</html>

Also, create a page named new.jsp This page will add a product to the current list in memory.
<%@ include file="include.jsp"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>New Product</title>
</head>
<body>
<form:form action="addProduct.htm" method="post" commandName="product">
Product Name:<form:input path="name"/>
Price:<form:input path="price"/>
<input type="submit" value="add"/>
</form:form>
</body>
</html>
Run the app with mvn jetty:run
Finally open an Internet browser at http://localhost:8080/SF










martes, 24 de enero de 2012

Jtwitter

For this example I'm using a MacBook Pro with Lion, Netbeans and JDK1.6

First of all you have to create a Twitter app, hence you have to go to dev.twitter.com and log in with your twitter account
Next create a new application with the details related to your app.
Then click on setting and change the Application Type to Read, Write and Access direct messages
 
Then  click on update this twitter application's settings

Create my Access tokens



First of all you need the following libraries
common-codec-1.4.jar http://mirrors.ibiblio.org/pub/mirrors/maven2/commons-codec/commons-codec/1.4/commons-codec-1.4.jar
jtwitter.jar http://www.winterwell.com/software/jtwitter/jtwitter.jar
sign-core-1.2.1.1.jar http://code.google.com/p/oauth-signpost/downloads/detail?name=signpost-core-1.2.1.1.jar

Next create a Web application with Netbeans

In the index.jsp set the following code.
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <form name="form1" action="NewServlet" method="Post">
        User:<input type="textfield" name="user"/><br/>
        Message:<input type="textfield" name="message"/><br/>
        <input type="submit" value="Enviar"/>
        </form>
    </body>
</html>

Next create a Servlet. You may call it NewServlet
with the following code:




package com.ejemplo;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import winterwell.jtwitter.OAuthSignpostClient;
import winterwell.jtwitter.Twitter;

public class NewServlet extends HttpServlet {
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String JTWITTER_OAUTH_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxx";
        String JTWITTER_OAUTH_SECRET = "XXXXXXXXXXXXXXXXXX";
        String JTWITTER_ACCESS_TOKEN = "yyyyyyyyyyyyyyyyyyyyyyyyyy";
        String JTWITTER_ACCESS_TOKEN_SECRET = "YYYYYYYYYYYYYYY";
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            out.println("Your Message was sent");
            OAuthSignpostClient oauthClient = new OAuthSignpostClient(JTWITTER_OAUTH_KEY, JTWITTER_OAUTH_SECRET, JTWITTER_ACCESS_TOKEN, JTWITTER_ACCESS_TOKEN_SECRET);
            Twitter twitter = new Twitter(request.getParameter("user"), oauthClient);
            String fecha = (new Date()).toString();
            twitter.updateStatus(request.getParameter("message") + fecha);
        } catch (Exception ex) {
            out.println(ex.getMessage());
            ex.printStackTrace();
        } finally {
            out.close();
        }
    }

    //
    /**
     * Handles the HTTP GET method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP POST method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }//

}

Replace xxxxx with Consumer key
Replace XXXX with Consumer secret
Replace yyyyy with  Access token
Replace YYYY with Access token secret

Finally upload you application to a webserver and run the app


martes, 22 de noviembre de 2011

An example of Weka and Java Persistence API

For this example I'm using MacBook Pro with Lion, Netbeans 6.9, MySQL Database.
First of all, we have to create a database in MySQL to retrieve the data. You can use the following script:


CREATE DATABASE IF NOT EXISTS exampleWeka;
USE exampleWeka;
DROP TABLE IF EXISTS weather;
CREATE TABLE  weather (
    id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
    outlook varchar(10),
    temperature varchar(10),
    humidity varchar(10),
    windy varchar(10),
    play varchar(10)
);
insert into weather(outlook,temperature,humidity,windy,play)values('sunny','hot','high','FALSE','no');
insert into weather(outlook,temperature,humidity,windy,play)values('sunny','hot','high','TRUE','no');
insert into weather(outlook,temperature,humidity,windy,play)values('overcast','hot','high','FALSE','yes');
insert into weather(outlook,temperature,humidity,windy,play)values('rainy','mild','high','FALSE','yes');
insert into weather(outlook,temperature,humidity,windy,play)values('rainy','cool','normal','FALSE','yes');
insert into weather(outlook,temperature,humidity,windy,play)values('rainy','cool','normal','TRUE','no');
insert into weather(outlook,temperature,humidity,windy,play)values('overcast','cool','normal','TRUE','yes');
insert into weather(outlook,temperature,humidity,windy,play)values('sunny','mild','high','FALSE','no');
insert into weather(outlook,temperature,humidity,windy,play)values('sunny','cool','normal','FALSE','yes');
insert into weather(outlook,temperature,humidity,windy,play)values('rainy','mild','normal','FALSE','yes');
insert into weather(outlook,temperature,humidity,windy,play)values('sunny','mild','normal','TRUE','yes');
insert into weather(outlook,temperature,humidity,windy,play)values('overcast','mild','high','TRUE','yes');
insert into weather(outlook,temperature,humidity,windy,play)values('overcast','hot','normal','FALSE','yes');
insert into weather(outlook,temperature,humidity,windy,play)values('rainy','mild','high','TRUE','no');
commit;



Then you can download Weka. I downloaded the version 3.4.19 from  http://sourceforge.net/projects/weka/files/weka-3-4/3.4.19/weka-3-4-19.zip/download. Then you have to extract the file and add weka.jar to the libraries of your EJB project

Then you have to create an Enterprise Application project in Netbeans.




Add MySQL library to the EJB Project.

Add the library weka.jar to the EJB project. I'm using the version available at:http://sourceforge.net/projects/weka/files/weka-3-7/3.7.5/weka-3-7-5-monolithic.jar/download

After this, create a Datasource to the database created above.

Create an Entity class to use the weather table.

Create a Session bean with remote interface.

Create the following utility class in the package com.example.ejb.util of the EJB project



package com.example.ejb.util;

import com.example.ejb.entity.Weather;
import java.util.List;
import weka.classifiers.trees.J48;
import weka.core.Attribute;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;

public class UtilWeka {
    static Instances instances = null;

    private static FastVector createAttributes(boolean classification) {
        FastVector fvWekaAttributes = new FastVector(9);
        FastVector fvOutlook = new FastVector(3);
        fvOutlook.addElement("sunny");
        fvOutlook.addElement("overcast");
        fvOutlook.addElement("rainy");
        Attribute outlook = new Attribute("outlook", fvOutlook);
        fvWekaAttributes.addElement(outlook);

        FastVector fvTemperature = new FastVector(3);
        fvTemperature.addElement("hot");
        fvTemperature.addElement("mild");
        fvTemperature.addElement("cool");
        Attribute temperature = new Attribute("temperature", fvTemperature);
        fvWekaAttributes.addElement(temperature);

        FastVector fvHumidity = new FastVector(2);
        fvHumidity.addElement("high");
        fvHumidity.addElement("normal");
        Attribute humidity = new Attribute("humidity", fvHumidity);
        fvWekaAttributes.addElement(humidity);

        FastVector fvWindy = new FastVector(2);
        fvWindy.addElement("TRUE");
        fvWindy.addElement("FALSE");
        Attribute windy = new Attribute("windy", fvWindy);
        fvWekaAttributes.addElement(windy);


        if(!classification){
        FastVector fvPlay = new FastVector(2);
        fvPlay.addElement("no");
        fvPlay.addElement("yes");
        Attribute play = new Attribute("play", fvPlay);
        fvWekaAttributes.addElement(play);
        }

        return fvWekaAttributes;
    }

    private static Instances generateInstances(List list) {
        FastVector fvAttributes = createAttributes(false);
        Instances instances = new Instances("Rel", fvAttributes, 5);
        instances.setClassIndex(instances.numAttributes() - 1);
        for (Weather weather : list) {
            Instance iExample = new Instance(5);
            iExample.setValue((Attribute) fvAttributes.elementAt(0), weather.getOutlook());
            iExample.setValue((Attribute) fvAttributes.elementAt(1), weather.getTemperature());
            iExample.setValue((Attribute) fvAttributes.elementAt(2), weather.getHumidity());
            iExample.setValue((Attribute) fvAttributes.elementAt(3), weather.getWindy());
            iExample.setValue((Attribute) fvAttributes.elementAt(4), weather.getPlay());
            instances.add(iExample);
        }
        return instances;
    }

    private static Instance generateWeatherInstance(Weather weather) {
        FastVector fvAttributes = createAttributes(true);
        Instances instances = new Instances("Rel", fvAttributes, 9);
        instances.setClassIndex(instances.numAttributes() - 1);



        Instance iExample = new Instance(9);
        iExample.setValue((Attribute) fvAttributes.elementAt(0), weather.getOutlook());
        iExample.setValue((Attribute) fvAttributes.elementAt(1), weather.getTemperature());
        iExample.setValue((Attribute) fvAttributes.elementAt(2), weather.getHumidity());
        iExample.setValue((Attribute) fvAttributes.elementAt(3), weather.getWindy());
       // iExample.setValue((Attribute) fvAttributes.elementAt(4), weather.getPlay());

        instances.add(iExample);

        return instances.firstInstance();
    }

    public static void initJ48Tree(List list) {
        instances=generateInstances(list);
        try {
            J48 j48 = new J48();
            instances.setClassIndex(instances.numAttributes() - 1);
            j48.buildClassifier(instances);
            System.out.println(j48.toString());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void classifyInstanceJ48(Weather weather) {
        double val=0;
        try {
            J48 j48 = new J48();
            instances.setClassIndex(instances.numAttributes() - 1);
            j48.buildClassifier(instances);
            val=j48.classifyInstance(generateWeatherInstance(weather));
            if(val==1){
                System.out.println("We can play");
            }else{
                System.out.println("We can't play");
            }
           
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
 

Change SessionBean to: 


package com.example.ejb.session;

import com.example.ejb.entity.Weather;
import com.example.ejb.util.UtilWeka;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import weka.core.Instances;

@Stateless
public class SessionBean implements SessionBeanRemote {

    @PersistenceContext
EntityManager em;
Instances instances =null;
    public void initWeatherData() {
        Query query=em.createNamedQuery("Weather.findAll");
        UtilWeka.initJ48Tree((List)query.getResultList());
}

    public void classifyJ48(Weather weather) {
        UtilWeka.classifyInstanceJ48(weather);
    }
   
}
 


Modify the client with an injection to the Session Bean.

package mavenwekaapp;

import com.example.ejb.entity.Weather;
import com.example.ejb.session.SessionBeanRemote;
import javax.ejb.EJB;

public class Main {
    @EJB
    private static SessionBeanRemote sessionBean;


    public static void main(String[] args) {
        sessionBean.initWeatherData();
        Weather wheater=new Weather();
        wheater.setHumidity("normal");
        wheater.setOutlook("overcast");
        wheater.setTemperature("hot");
        wheater.setWindy("FALSE");
        sessionBean.classifyJ48(wheater);
    }
}



Run the Enterprise Project.


These are functions,which implement ID3 and NBTree algorithms.
public static void initId3Tree(List list) {
        instances=generateInstances(list);
        try {
            Id3 id3 = new Id3();
            instances.setClassIndex(instances.numAttributes() - 1);
            id3.buildClassifier(instances);
            System.out.println(id3.toString());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void classifyInstanceId3(Weather weather) {
        double val=0;
        try {
            Id3 id3 = new Id3();
            instances.setClassIndex(instances.numAttributes() - 1);
            id3.buildClassifier(instances);
            val=id3.classifyInstance(generateWeatherInstance(weather));
            if(val==1){
                System.out.println("We can play");
            }else{
                System.out.println("We can't play");
            }
           
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }



    public static void initNBTree(List list) {
        instances=generateInstances(list);
        try {
            NBTree nbTree = new NBTree();
            instances.setClassIndex(instances.numAttributes() - 1);
            nbTree.buildClassifier(instances);
            System.out.println(nbTree.toString());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void classifyInstanceNBTree(Weather weather) {
        double val=0;
        try {
            NBTree nbTree = new NBTree();
            instances.setClassIndex(instances.numAttributes() - 1);
            nbTree.buildClassifier(instances);
            val=nbTree.classifyInstance(generateWeatherInstance(weather));
            if(val==1){
                System.out.println("We can play");
            }else{
                System.out.println("We can't play");
            }
           
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }






jueves, 17 de noviembre de 2011

How to use Facebook Graph API with Javascript

For this example I'm using: MacBook Pro with Lion(10.7.1) as operative system, Netbeans 7.0 and a Facebook account.

This is a quick example of Facebook Graph API. This code allows Facebook users to publish information in their walls, retrieve friends and send message to their friends. To test this code you have to create a Facebook application in https://developers.facebook.com/apps
I named the application as TestGraphAPI:
Enter the captcha value:

Then you have to register the URL of your application, pg: http://localhost:8080/TestGraphAPI.
I created a web java application in Netbeans and pasted the following code in the index jsp page:

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Facebook Example</title>
    </head>
    <body>
        <div id="fb-root">
            <script type="text/javascript">

                window.fbAsyncInit = function() {
                    FB.init({appId: 'XXXXXXXXXXXXXXX', status: true, cookie: true, xfbml: true});
                    FB.getLoginStatus(function(response) {
                        if (response.session!=null) {
                            alert("Welcome, you have been logged to Facebook");
                        }else{
                            alert("To use this application you have to be logged at Facebook");
                     
                        }
                    });
                };
                (function() {
                    var scriptFacebook = document.createElement('script');
                    scriptFacebook.type = 'text/javascript';
                    scriptFacebook.src = document.location.protocol +
                        '//connect.facebook.net/en_US/all.js';
                    scriptFacebook.async = true;
                    document.getElementById('fb-root').appendChild(scriptFacebook);
                }());
         
                function obtenerAmigos(){
                    document.getElementById("imagenes").innerHTML="Click on the images to send a message<br/>";
                    FB.api('/me/friends',function(response){
                        for(i=0;i<response.data.length;i++){
                            document.getElementById("imagenes").innerHTML+="<img src='https://graph.facebook.com/"+response.data[i].id+"/picture' onclick='enviarMensaje(\""+response.data[i].id+"\",\""+response.data[i].name+"\")'/>";
                        }
                    });
                }
         
                function escribirMuro(){
                    var mensaje=prompt("What is your message?");
                    FB.api('/me/feed', 'post', { message: mensaje }, function(response) {
                        if (!response || response.error) {
                            alert('A problem ocurred');
                        } else {
                            alert('The message was sent to your wall');
                        }
                 
                    });
                }
             
                function enviarMensaje(id,name){
                    var mensaje=prompt("Enter the message to "+name);
                    FB.api('/'+id+'/feed', 'POST', { message: mensaje }, function(response) {
                        if (!response || response.error) {
                            alert('A problem ocurred');
                        } else {
                            alert('The message was sent to '+name);
                        }
                    });
                 
                }
             
            </script>
        </div>
    <fb:login-button autologoutlink="true" scope="email,status_update,publish_stream,sms"></fb:login-button><br/>
    <input type="button" value="Post on your wall" onclick="escribirMuro()"/>
    <input type="button" value="Get Friends" onclick="obtenerAmigos()"><br/>
    <div id="fb-root">
        <div id="imagenes">

        </div>
    </div>
</body>
</html>

Finally replace the APP ID in XXXXXXXXXXXXXXX





and test the application.

martes, 28 de junio de 2011

Bridge Struts to Portlet



For this example I'm using Eclipse Helios, Liferay 6.06 and Ubuntu(Also, you may use Netbeans 7.0 for the Struts Project).

First of all, you need a Struts proyect. I created a project with the following tutorial:http://netbeans.org/kb/docs/web/quickstart-webapps-struts.html.
Also, I uploaded this project at http://www.megaupload.com/?d=9EJND8KQ

Download the project.
Extract it.

Now, we have to create a new Portlet App with Eclipse.







Replace the content of src directory of your Portlet project with the directory src/java content of MyStrutsApp.



Copy the libraries of WEB-INF/lib with the libraries of MyStrutsApp/build/web/WEB-INF/lib



Delete commons-logging-1.0.4.jar, standard-1.0.2 and jstl-1.0.2

Next, copy struts tld files to WEB-INF/tld directory of your Portlet Project.
You may download the tld files from:http://www.megaupload.com/?d=TFVCGMM2




Also, copy struts-config.xml,tiles-defs.xml,validation.xml,validator-rules.xml from MyStrutsApp/web/WEB-INF to WEB-INF/ of your Portlet Project



Next, copy the files index.jsp, login.jsp, success.jsp of /MyStrutsApp/web in Bridge-portlet/docroot



After that, copy the libraries jstl.jar and standard.jar to Bridge-portlet/docroot/WEB-INF/lib. The libraries are uploaded in:http://www.megaupload.com/?d=MWJ0BFRQ

And refresh your Eclipse project.


Next open liferay-plugin-package.properties. Click source. Replace the code with the following code:
name=Bridge
module-group-id=liferay
module-incremental-version=1
tags=
short-description=
change-log=
page-url=http://www.liferay.com
author=Liferay, Inc.
licenses=LGPL

portal-dependency-jars=\
antlr.jar,\
commons-beanutils.jar,\
commons-collections.jar,\
commons-digester.jar,\
commons-fileupload.jar,\
commons-io.jar,\
commons-lang.jar,\
commons-validator.jar,\
jcommon.jar,\
jfreechart.jar,\
oro.jar,\
portals-bridges.jar,\
struts.jar

portal-dependency-tlds=\
struts-bean.tld,\
struts-bean-el.tld,\
struts-html.tld,\
struts-html-el.tld,\
struts-logic.tld,\
struts-logic-el.tld,\
struts-nested.tld,\
struts-tiles.tld,\
struts-tiles-el.tld

Replace liferay-portlet.xml with the following code:

<?xml version="1.0"?>
<!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 6.0.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_6_0_0.dtd">

<liferay-portlet-app>

<portlet>
<portlet-name>Bridge</portlet-name>
<portlet-url-class>com.liferay.portal.apache.bridges.struts.LiferayStrutsPortletURLImpl</portlet-url-class>
<use-default-template>true</use-default-template>
<restore-current-view>true</restore-current-view>
</portlet>
<role-mapper>
<role-name>administrator</role-name>
<role-link>Administrator</role-link>
</role-mapper>
<role-mapper>
<role-name>guest</role-name>
<role-link>Guest</role-link>
</role-mapper>
<role-mapper>
<role-name>power-user</role-name>
<role-link>Power User</role-link>
</role-mapper>
<role-mapper>
<role-name>user</role-name>
<role-link>User</role-link>
</role-mapper>
</liferay-portlet-app>

After that, change portlet.xml to:
<?xml version="1.0"?>

<portlet-app
version="2.0"
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
>

<portlet>
<portlet-name>Bridge</portlet-name>
<display-name>Bridge Sample</display-name>
<portlet-class>org.apache.portals.bridges.struts.StrutsPortlet</portlet-class>
<init-param>
<name>ServletContextProvider</name>
<value>com.liferay.util.bridges.struts.LiferayServletContextProviderWrapper</value>
</init-param>
<init-param>
<name>ViewPage</name>
<value>/portlet_action/login</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>Bridge</title>
<short-title>NewPortlet</short-title>
<keywords></keywords>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>
</portlet-app>


Change struts-config.xml to:
<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_3.dtd">


<struts-config>
<form-beans>
<form-bean name="LoginForm" type="com.myapp.struts.LoginForm" />

</form-beans>

<global-exceptions>

</global-exceptions>

<global-forwards>
<forward name="welcome" path="/Welcome.do" />
</global-forwards>

<action-mappings>
<action path="/bridge_struts_portlet/view" forward="portlet.sample_struts_portlet.view" />

<action name="LoginForm" path="/login" scope="request"
type="com.myapp.struts.LoginAction" validate="false">
<forward name="success" path="/success.jsp" />
<forward name="failure" path="/login.jsp" />
</action>
<action path="/Welcome" forward="/welcomeStruts.jsp" />
</action-mappings>

<controller
processorClass="org.apache.portals.bridges.struts.PortletTilesRequestProcessor" />

<message-resources parameter="com/myapp/struts/ApplicationResource" />

<plug-in className="org.apache.struts.tiles.TilesPlugin">
<set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" />
<set-property property="moduleAware" value="true" />
<set-property property="definitions-parser-validate"
value="true" />
</plug-in>

<!-- ========================= Validator plugin ================================= -->
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" />
</plug-in>

</struts-config>


Next, change tiles-def.xml to:
<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">

<tiles-definitions>
<definition name="portlet.bridge_struts_portlet.view" >
<put name="portlet_content" value="/portlet/bridge_struts_portlet/view.jsp" />
</definition>
</tiles-definitions>

After that, open web.xml. Change the code to:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Bridge-portlet</display-name>
<servlet>
<servlet-name>PortletActionServlet</servlet-name>
<servlet-class>com.liferay.util.bridges.struts.LiferayPortletServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>PortletActionServlet</servlet-name>
<url-pattern>/portlet_action/*</url-pattern>
</servlet-mapping>
<jsp-config>
<taglib>
<taglib-uri>http://struts.apache.org/tags-bean</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://portals.apache.org/bridges/struts/tags-portlet-html</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-portlet-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://struts.apache.org/tags-logic</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-logic.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://struts.apache.org/tags-nested</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-nested.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://struts.apache.org/tags-tiles</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-tiles.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>

Now, change the code of login.jsp to:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://portals.apache.org/bridges/struts/tags-portlet-html" prefix="html" %>

<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%@ taglib uri="http://struts.apache.org/tags-nested" prefix="nested" %>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<html:form action="/login">
<table border="0">
<tbody>
<tr>
<td colspan="2">
<bean:write name="LoginForm" property="error" filter="false"/>
</td>
</tr>
<tr>
<td><bean:message key="data.name"/></td>
<td><html:text property="name" /></td>
</tr>
<tr>
<td><bean:message key="data.email"/></td>
<td><html:text property="email" /></td>
</tr>
<tr>
<td></td>
<td><html:submit value="Login" /></td>
</tr>
</tbody>
</table>
</html:form>
</body>
</html>

Next, change the code of success.jsp to:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://portals.apache.org/bridges/struts/tags-portlet-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login Success</title>
</head>
<body>
<c:out value="${title}"/>
<h1>Congratulations!</h1>
<p>You have successfully logged in.</p>
<p>Your name is: <bean:write name="LoginForm" property="name" />.</p>
<p>Your email address is: <bean:write name="LoginForm" property="email" />.</p>


<logic:messagesPresent message="true">
<html:messages message="true" id="msg">
<bean:write name="msg" ignore="true"/>
</html:messages>

</logic:messagesPresent>



</body>
</html>


After that, open the file loginAction.java. Set the following code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.myapp.struts;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

/**
*
* @author santiago
*/
public class LoginAction extends org.apache.struts.action.Action {

/* forward name="success" path="" */
private static final String SUCCESS = "success";
private final static String FAILURE = "failure";


@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {

// extract user data
LoginForm formBean = (LoginForm)form;
String name = formBean.getName();
String email = formBean.getEmail();


ActionMessages actionMessages = new ActionMessages();
actionMessages.add(ActionMessages.GLOBAL_MESSAGE,
new ActionMessage("errors.cancel"));
saveMessages(request, actionMessages);


// perform validation
if ((name == null) || // name parameter does not exist
email == null || // email parameter does not exist
name.equals("") || // name parameter is empty
email.indexOf("@") == -1) { // email lacks '@'

formBean.setError();
return mapping.findForward(FAILURE);
}
request.setAttribute("title", "This is Test");
return mapping.findForward(SUCCESS);

}


}

Run the project.




The messages don't show in the screen. We have to replace the class MessageTag of apache. To replace the class, you have to create a new package(org.apache.struts.taglib.html) . Into the package create the class named MessagesTag with the following apache struts taglib code:

/*
* $Id: MessagesTag.java 471754 2006-11-06 14:55:09Z husted $
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.struts.taglib.html;

import org.apache.struts.Globals;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.taglib.TagUtils;
import org.apache.struts.util.MessageResources;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

import java.util.Iterator;

/**
* Custom tag that iterates the elements of a message collection. It defaults
* to retrieving the messages from <code>Globals.ERROR_KEY</code>, but if the
* message attribute is set to true then the messages will be retrieved from
* <code>Globals.MESSAGE_KEY</code>. This is an alternative to the default
* <code>ErrorsTag</code>.
*
* @version $Rev: 471754 $ $Date: 2005-11-08 23:50:53 -0500 (Tue, 08 Nov 2005)
* $
* @since Struts 1.1
*/
public class MessagesTag extends BodyTagSupport {
/**
* The message resources for this package.
*/
protected static MessageResources messageResources =
MessageResources.getMessageResources(Constants.Package
+ ".LocalStrings");

/**
* Iterator of the elements of this error collection, while we are
* actually running.
*/
protected Iterator iterator = null;

/**
* Whether or not any error messages have been processed.
*/
protected boolean processed = false;

/**
* The name of the scripting variable to be exposed.
*/
protected String id = null;

/**
* The servlet context attribute key for our resources.
*/
protected String bundle = null;

/**
* The session attribute key for our locale.
*/
protected String locale = Globals.LOCALE_KEY;

/**
* The request attribute key for our error messages (if any).
*/
protected String name = Globals.ERROR_KEY;

/**
* The name of the property for which error messages should be returned,
* or <code>null</code> to return all errors.
*/
protected String property = null;

/**
* The message resource key for errors header.
*/
protected String header = null;

/**
* The message resource key for errors footer.
*/
protected String footer = null;

/**
* If this is set to 'true', then the <code>Globals.MESSAGE_KEY</code>
* will be used to retrieve the messages from scope.
*/
protected String message = null;

public String getId() {
return (this.id);
}

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

public String getBundle() {
return (this.bundle);
}

public void setBundle(String bundle) {
this.bundle = bundle;
}

public String getLocale() {
return (this.locale);
}

public void setLocale(String locale) {
this.locale = locale;
}

public String getName() {
return (this.name);
}

public void setName(String name) {
this.name = name;
}

public String getProperty() {
return (this.property);
}

public void setProperty(String property) {
this.property = property;
}

public String getHeader() {
return (this.header);
}

public void setHeader(String header) {
this.header = header;
}

public String getFooter() {
return (this.footer);
}

public void setFooter(String footer) {
this.footer = footer;
}

public String getMessage() {
return (this.message);
}

public void setMessage(String message) {
this.message = message;
}

/**
* Construct an iterator for the specified collection, and begin looping
* through the body once per element.
*
* @throws JspException if a JSP exception has occurred
*/
public int doStartTag() throws JspException {
// Initialize for a new request.
processed = false;

// Were any messages specified?
ActionMessages messages = null;

// Make a local copy of the name attribute that we can modify.
String name = this.name;

if ((message != null) && "true".equalsIgnoreCase(message)) {
name = Globals.MESSAGE_KEY;
}

try {
messages =
TagUtils.getInstance().getActionMessages(pageContext, name);
} catch (JspException e) {
TagUtils.getInstance().saveException(pageContext, e);
throw e;
}

// Acquire the collection we are going to iterate over
this.iterator =
(property == null) ? messages.get() : messages.get(property);

// Store the first value and evaluate, or skip the body if none
if (!this.iterator.hasNext()) {
return SKIP_BODY;
}

// process the first message
processMessage((ActionMessage) iterator.next());

if ((header != null) && (header.length() > 0)) {
String headerMessage =
TagUtils.getInstance().message(pageContext, bundle, locale,
header);

if (headerMessage != null) {
TagUtils.getInstance().write(pageContext, headerMessage);
}
}

// Set the processed variable to true so the
// doEndTag() knows processing took place
processed = true;

return (1);
}

/**
* Make the next collection element available and loop, or finish the
* iterations if there are no more elements.
*
* @throws JspException if a JSP exception has occurred
*/
public int doAfterBody() throws JspException {
// Render the output from this iteration to the output stream
if (bodyContent != null) {
TagUtils.getInstance().writePrevious(pageContext,
bodyContent.getString());
bodyContent.clearBody();
}

// Decide whether to iterate or quit
if (iterator.hasNext()) {
processMessage((ActionMessage) iterator.next());

return (1);
} else {
return (SKIP_BODY);
}
}

/**
* Process a message.
*/
private void processMessage(ActionMessage report)
throws JspException {
String msg = null;

if (report.isResource()) {
msg = TagUtils.getInstance().message(pageContext, bundle, locale,
report.getKey(), report.getValues());

if (msg == null) {
String bundleName = (bundle == null) ? "default" : bundle;

msg = messageResources.getMessage("messagesTag.notfound",
report.getKey(), bundleName);
}
} else {
msg = report.getKey();
}

if (msg == null) {
pageContext.removeAttribute(id);
} else {
pageContext.setAttribute(id, msg);
}
}

/**
* Clean up after processing this enumeration.
*
* @throws JspException if a JSP exception has occurred
*/
public int doEndTag() throws JspException {
if (processed && (footer != null) && (footer.length() > 0)) {
String footerMessage =
TagUtils.getInstance().message(pageContext, bundle, locale,
footer);

if (footerMessage != null) {
TagUtils.getInstance().write(pageContext, footerMessage);
}
}

return EVAL_PAGE;
}

/**
* Release all allocated resources.
*/
public void release() {
super.release();
iterator = null;
processed = false;
id = null;
bundle = null;
locale = Globals.LOCALE_KEY;
name = Globals.ERROR_KEY;
property = null;
header = null;
footer = null;
message = null;
}
}

Run again the project