JDK 9 and JShell

Aún falta mucho tiempo para que Java 9 vea la luz, pero podemos empezar a disfrutar de alguna de sus novedades.

Ahora mismo les presentaré a JShell (conocido como el proyecto kulla). Ahora mismo se lo puede descargar como un archivo .jar y ejecutarlo como el comando java -jar, siempre y cuando se tenga instalado JDK 9. Entiendo que en las últimas versiones de JDK (early access) ya viene dentro del directorio bin (aunque con el proceso de instalación que aquí propongo aún no se encuentra).

JShell es una implementación para Java de lo que se denomina REPEL o Read-Eval-Print-Loop. Básicamente se trata de un programa tipo shell que permite escribir y ejecutar programas. Estos entornos son populares en otros lenguajes como Python o Scala. Es la primera vez que Java adopta oficialmente este entorno y nos permitirá escribir programas Java, sin la necesidad de escribir una clase y el método principal o terminar una sentencia con punto y coma. Aquí más detalles.

Si no quieres instalar JDK9 en tú computador, una solución es utilizar alguna máquina virtual subida en la nube con interfaz Web y de acceso gratuito. Las alternativas que propongo son: koding y codeanywhere, yo uso las dos (con fines de prueba). Ambas son Ubuntu y cuenta con una ventana terminal. El proceso de instalación de JDK9 lo pueden encontrar aquí, aunque en codeanywhere deberán ejecutar un paso adicional previo, que lo pueden encontrar aquí (muestra los comandos para resolver el problema sudo: add-apt-repository: command not found).

Esos son los prerequisitos, ahora la instalación del JShell demanda que nos descarguemos un archivo JAR, que lo podemos encontrar en Adopt OpenJDK: Getting Started Kit clic en el botón Read, seleccionados el idioma y en el menú de la izquierda podrán ver todos los proyectos relacionados con JDK9. En ese menú buscamos kulla (punto 8.5) click ahí y te mostrará una página en donde debes buscar la sección binarios y hacer click en el link Kulla.jar: Adopt OpenJDK Cloudbees Build farm, eso te lleva a una nueva página y debes copiar la URL del link que empieza por kulla-….. y termina en .jar. (Pongo todas las instrucciones ya que el link final puede cambiar con nuevas versiones)

Ahora vas a tú máquina virtual te ubicas en el directorio en donde quieres copiar el jar y ejecutas el comando (en la ventana terminal) wget  <URL copiada anteriormente>. En mi caso fue:

wget https://adopt-openjdk.ci.cloudbees.com/view/OpenJDK/job/langtools-1.9-linux-x86_64-kulla-dev/lastSuccessfulBuild/artifact/kulla--20151108010045.jar

Una vez descargado el archivo, ejecutas en el terminal el comando

java -jar kulla--2....jar

Y podrás hacer cosas cómo estas:

JShell

Un ejemplo del uso de JShell en codeanywhere

Si quieres más ejemplos puedes visitar el siguiente tutorial sobre REPL.

Anuncios

Java Web Development – ¿Alguna novedad?

Desde hace algún tiempo venía buscando un framework Web ligero para Java. En ese proceso encontré algunos frameworks que quiero comentar.

Spark framework – A tiny Java Web framework

Aclaración, Spark framework no tiene relación alguna con Spark de Scala. El primero es un framework para crear aplicaciones Web, mientras que el segundo es para el procesamiento de BigData.

Link

Desde mi punto de vista, su principal característica es la simplicidad y su utilidad está en el desarrollo rápido de servicios REST para prototipos o educación, en cuestión de segundos puedes tener un API Web funcional sin mayor esfuerzo.

Como ya lo mencioné se puede usar en educación para una introducción rápida a REST y Java 8 (lambdas) ya que usa esa característica de Java. Algo de código:

import static spark.Spark.*;

public class HelloWorld {
    public static void main(String[] args) {
        get("/hello", (req, res) -> "Hello World");
    }
}

Y para ejecutarlo visitar: http://localhost:4567/hello

Vert.x

Link

Vertx es un framework diferente, completo y específico para tareas de alto desempeño muchos lo llegan a comparar con Node.js. Lo que me llamó la atención es su arquitectura, la forma de comunicación que emplea entre los componentes del lado del servidor, el uso de nuevos estándares como WebSockets y finalmente que es políglota se puede usar con Javascript, Java, Ruby, Groovy, Python, Clojure, Ceylon y pronto en Scala.


public class ApiServer extends Verticle {

   @Override
   public void start() {
      HttpServer server = vertx.createHttpServer();
      RouteMatcher routeMatcher = new RouteMatcher();

      routeMatcher.get("/users/", new Handler<HttpServerRequest>() {
         @Override
         public void handle(HttpServerRequest request) {
            request.response().putHeader("content-type", "text/plain");
            request.response().end(String.format("%s[%s]\n", request.path(), request.method()));
         }
      });
   }
}

Y para ejecutarlo se debe visitar: http://localhost:8080/users

Si bien los frameworks anteriores tienen su utilidad yo buscaba algo diferente, algo más orientado al desarrollo de clientes Web que por ejemplo maneje un sistema de Templates.

Ninja Web framework

Link

Completo para mis necesidades, simple, elegante y bastante potente. Desarrollé mi primera aplicación Ninja y me fue muy bien.

Este framework tiene muchas características y su propia filosofía, no existen sesiones manejadas en el servidor y el uso de un grupo de estándares Java perfectamente integrados que hace que el desarrollo sea rápido, orientado a las pruebas y extensible.

Para los relacionados con Scala, Ninja es algo así como un fork de Play y como leí en algún lado sigue en algo la filosofía de Rails de Ruby.

En resumen un framework Web orientado a acciones y no a componentes, que desde mi punto de vista es la tendencia.

Algo de código, así se manejan las rutas en Ninja:


public class Routes implements ApplicationRoutes {

@Inject
NinjaProperties ninjaProperties;

@Override
public void init(Router router) {

///////////////////////////////////////////////////////////////////////
// Login / Logout
///////////////////////////////////////////////////////////////////////
router.GET().route("/login").with(LoginLogoutController.class, "login");
router.POST().route("/login").with(LoginLogoutController.class, "loginPost");
router.GET().route("/logout").with(LoginLogoutController.class, "logout");

...

También existen otros frameworks:

Y poco tiempo después se anunció que la nueva versión de Java EE tendrá un nuevo framework MVC orientado a acciones (así como Ninja), detalles aquí.

JDialog con imagen de fondo

Luego de varias preguntas relacionadas al tema (ubicar una imagen de fondo a un JDialog) me puse a trabajar en el tema y les presento una solución, la misma que sigue lo explicado en el post JFrame con Imagen de Fondo.

El proyecto está estructurado como muestra la imagen a continuación:

Imagen con la estructura del proyecto en NetBeans

Imagen con la estructura del proyecto en NetBeans

La descripción de la misma es la siguiente:

  • El JFrame – FrmPrincipal.java tiene un botón cuya función es mostrar el JDialog.
  • El JDialog – JDiFondo.java, muestra un JPanel
  • Un JPanel – PnlFondoJDialog.java, que muestra la imagen y un botón.

Veamos el código más importante de cada uno de los elementos, empecemos por el JFrame –  FrmPrincipal.java

public class FrmPrincipal extends javax.swing.JFrame {
   /** Creates new form FrmPrincipal */
   public FrmPrincipal() {
      initComponents();
   }

   private void btnMostrarActionPerformed(java.awt.event.ActionEvent evt) {
      int ancho = 300;
      int alto = 300;
      JDiFondo jdiFondo = new JDiFondo(this, true);
      jdiFondo.setSize(ancho, alto);
      jdiFondo.setPreferredSize(new Dimension(ancho, alto));
      jdiFondo.configurar();
      jdiFondo.setVisible(true);
   }
   ...
}

Usamos setSize y jdiFondo.setPreferredSize, el primero nos permite que la imagen y la ventana del JDialog tengan el mismo tamaño, también se invoca la método configurar del JDialog que lo explicaremos más adelante.

Ahora veremos el JDialog – JDiFondo.java

public class JDiFondo extends javax.swing.JDialog {
   /** Creates new form JDiFondo */
   public JDiFondo(java.awt.Frame parent, boolean modal) {
      super(parent, modal);
      initComponents();
   }

   public void configurar(){
      PnlFondoJDialog pnlFondo = new PnlFondoJDialog();
      pnlFondo.setSize(this.getSize());
      this.add(pnlFondo, BorderLayout.CENTER);
      this.pack();
   }
   ...
}

Lo que debemos destacar de está clase es el método configurar, que no existía cuando trabajamos en el post anterior (ubicar la imagen en un JFrame – JFrame con Imagen de Fondo) es necesario éste método por que si ubicamos sus líneas de código en el constructor el panel toma la medida por defecto del JDialog ya que hasta ese momento no le asignamos un tamaño al JDialog (Ver el método btnMostrarActionPerformed del JFrame).

Finalmente el JPanel – PnlFondoJDialog.java este no ha cambiado y sigue el mismo principio que se mencionó en el post: JFrame con Imagen de Fondo.

public class PnlFondoJDialog extends javax.swing.JPanel {
   /** Creates new form PnlFondo */
   public PnlFondoJDialog() {
      initComponents();
   }

   @Override
   public void paintComponent(Graphics g){
      Dimension tamanio = getSize();
      ImageIcon imagenFondo = new ImageIcon(getClass().
      getResource("/los/imagen/DSC00857.jpg"));
      g.drawImage(imagenFondo.getImage(), 0, 0,
      tamanio.width, tamanio.height, null);
      setOpaque(false);
      super.paintComponent(g);
   }
   ...
}

El resultado final lo pueden ver en la siguiente imagen:

Ejemplo de un JDialog con imagen de Fondo

El resultado final

El código completo lo pueden descargar aquí.

Espero que les ayude

Consultas DBpedia con Java – Linked Data

Dentro de la Web semántica, una de las iniciativas que de a poco va ganando relevancia es la Web de datos o también conocida como Linked Data o también como Linked Open Data, aquí una presentación que explica Linked Data, que a través de 4 principios determina la forma en la que los datos deben ser descritos y publicados. Bajo estos preceptos se han generado varios Datasets, uno de ellos es DBpedia que es la versión semántica de la wikipedia. La mayoría de los Dataset poseen mecanismos de consulta que a través de SPARQL nos permiten tener acceso a la información que ahí se publica. Los mecanismos de consulta son servicios Web basados en REST.

En este post mostraremos como realizar consultas a la DBPedia a través de Java. Para ellos usaremos Jersey que es un API que no permite trabajar con servicios REST. Antes de pasar a realizar cualquier explicación les describiré brevemente la aplicación, el objetivo de la aplicación es encontrar el país al cual pertenece un punto cardinal expresado en latitud y longitud. Para ello vamos a realizar la siguiente consulta:

SELECT ?pais ?lat ?long WHERE {
?pais rdf:type <http://dbpedia.org/ontology/Country>.
?pais geo:lat ?lat FILTER (datatype(?lat) = xsd:float && (?lat-0.2273363048115043) < 0.005 && (-0.2273363048115043-?lat) < 0.005).
?pais geo:long ?long FILTER (datatype(?long) = xsd:float && (?long-78.892578125) < 0.005 && (-78.892578125-?long) < 0.005)
}

Para ejecutar la consulta y ver los resultados click aquí. Podemos ver en la consulta que estamos consultando los países (rdf:type <http://dbpedia.org/ontology/Country) que tenga sus valores de latitud y longitud como números tipos float (datatype(?lat) = xsd:float  y datatype(?long) = xsd:float) y ademas calculamos la diferencia en la latitud y longitud de cada país con los valores que los obtenemos de alguna manera (yo los obtuve con google maps). Si bien este método no es el mejor ha sido el que relativamente a funcionado mejor y según leí en algún lugar es una recomendación de la dbpedia.

Actualización 19/08/2010: La consulta anterior no dio buenos resultados por lo que busqué otras formas de consultar el país y encontré dos. La primera y que uso es invocando a un servicio, obviamente REST, CountryCode / reverse geocoding cuyo detalle lo pueden encontrar aquí – GeoNames. La segunda opción es usar Google Maps con su clase GClientGeoCoder y su método getLocations, detalles aquí. Que tiene su contraparte con la librería de Maps en GWT.

Con la consulta ya estructurada es hora de armar la URL del servicio que consumiremos. La URL tiene la siguiente forma: http://dbpedia.org/sparql?default-graph-uri=<valor>&query=<consulta>&output=<tipo_salida>

Para el ejemplo los valores son (para <consulta> el valor es la consulta SPARQL que les mostré anteriormente):

<valor> = http://dbpedia.org

<tipo_salida> = json

Veamos el código Java del programa


import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import javax.ws.rs.core.MediaType;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
/**
*
* @author jorgaf
*/

public class ClienteDBpedia {
   public static final String WS_URL_DBPEDIA = "http://dbpedia.org/sparql";
   public static void main(String[] args) {
      String defaultGraph = "http://dbpedia.org";
      String qry = "SELECT ?nombre ?tGobierno ?capital ?area ?moneda "
                + "?imagen ?descripcion\n WHERE { \n"
                + "?pais rdf:type <http://dbpedia.org/ontology/Country>. \n"
                + "OPTIONAL{?pais dbpprop:areaKm ?area.\n"
                + "?pais dbpprop:currencyCode ?moneda.\n"
                + "?pais dbpedia-owl:capital ?capital}.\n"
                + "OPTIONAL{?gobierno rdf:type <http://dbpedia.org/class/yago/FormsOfGovernment>.\n"
                + "    ?pais dbpedia-owl:governmentType ?tipoGobierno FILTER (?tipoGobierno = ?gobierno)}.\n"
                + "?pais rdfs:label ?nombre FILTER langMatches( lang(?nombre), \"ES\" ).\n"
                + "OPTIONAL{?gobierno rdfs:label ?tGobierno FILTER langMatches(lang(?tGobierno), \"ES\")}.\n"
                + "?pais rdfs:label ?nombreEng FILTER (langMatches( lang(?nombreEng), \"EN\" ) && ?nombreEng = \"Ecuador\"@en).\n"
                + "?pais dbpedia-owl:abstract ?descripcion FILTER (langMatches( lang(?descripcion), \"ES\" )).\n"
                + "?pais dbpedia-owl:thumbnail ?imagen\n"
                + "}";
      String salida = "&output=json";
      String url = "";
      try {
         defaultGraph = URLEncoder.encode(defaultGraph, "UTF-8");
         qry = URLEncoder.encode(qry, "UTF-8");
      } catch (UnsupportedEncodingException ex) {}

      Client client = new Client();
      url = WS_URL_DBPEDIA + "?default-graph-uri=" + defaultGraph
         + "&query=" + qry + salida;
      WebResource resource = client.resource(url);
      String result = resource.accept("application/sparql-results+json").
         get(String.class);
   try {
      procesar(result);
   } catch (JSONException ex) {}
 }

 private static void procesar(String res) throws JSONException{
    JSONObject result = new JSONObject(res).getJSONObject("results");
    JSONArray bindings = result.getJSONArray("bindings");
    JSONObject pais;
    JSONObject lat, lon;

    for (int i = 0; i < bindings.length(); i++) {
       pais = bindings.getJSONObject(i).getJSONObject("pais");
       lat = bindings.getJSONObject(i).getJSONObject("lat");
       lon = bindings.getJSONObject(i).getJSONObject("long");
       System.out.printf("País: %s Lat: %s Lon: %s\n",
       pais.get("value"),
       lat.get("value"),
       lon.get("value"));
    }
  }
}

Podemos ver como es necesario codificar los valores de las default-graph-uri, query y output. El programa muestra también como trabajar con información en formato JSON que fue el valor que le asignamos para la salida, vea le método procesar para ver como se pueden obtener los datos. La salida que se obtiene son las siguientes:

{ "head": { "link": [], "vars": ["pais", "lat", "long"] },
"results": { "distinct": false, "ordered": true, "bindings": [
{ "pais": { "type": "uri", "value": "http://dbpedia.org/resource/Gabon" }        , "lat": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "0.3833333253860474" }        , "long": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "9.449999809265137" }},
{ "pais": { "type": "uri", "value": "http://dbpedia.org/resource/Kenya" }        , "lat": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "-1.266666650772095" }        , "long": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "36.79999923706055" }},
{ "pais": { "type": "uri", "value": "http://dbpedia.org/resource/S%C3%A3o_Tom%C3%A9_and_Pr%C3%ADncipe" }        , "lat": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "0.3333333432674408" }        , "long": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "6.733333110809326" }},
{ "pais": { "type": "uri", "value": "http://dbpedia.org/resource/Rwanda" }        , "lat": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "-1.943883299827576" }        , "long": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "30.05945014953613" }},
{ "pais": { "type": "uri", "value": "http://dbpedia.org/resource/Royal_Audience_of_Quito" }        , "lat": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "-0.25" }        , "long": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "-78.58333587646484" }},
{ "pais": { "type": "uri", "value": "http://dbpedia.org/resource/Ecuador" }        , "lat": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "-0.1500000059604645" }        , "long": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "-78.34999847412109" }},
{ "pais": { "type": "uri", "value": "http://dbpedia.org/resource/Somalia" }        , "lat": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "2.033333301544189" }        , "long": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#float", "value": "45.34999847412109" }} ] } }

Mientras que la salida ya procesada es la siguiente:


País: http://dbpedia.org/resource/Gabon Lat: 0.3833333253860474 Lon: 9.449999809265137
País: http://dbpedia.org/resource/Kenya Lat: -1.266666650772095 Lon: 36.79999923706055
País: http://dbpedia.org/resource/S%C3%A3o_Tom%C3%A9_and_Pr%C3%ADncipe Lat: 0.3333333432674408 Lon: 6.733333110809326
País: http://dbpedia.org/resource/Rwanda Lat: -1.943883299827576 Lon: 30.05945014953613
País: http://dbpedia.org/resource/Royal_Audience_of_Quito Lat: -0.25 Lon: -78.58333587646484
País: http://dbpedia.org/resource/Ecuador Lat: -0.1500000059604645 Lon: -78.34999847412109
País: http://dbpedia.org/resource/Somalia Lat: 2.033333301544189 Lon: 45.34999847412109

Hasta aquí no existe complicación alguna, pero lamentablemente y no sé porqué algunas veces el programa no funciona y presenta una excepción 406 Not Acceptable Actualización 19/08/2010: el problema anterior se resolvió cambiando la línea: resource.accept(MediaType.APPLICATION_JSON).get(String.class) por resource.accept(“application/sparql-results+json”).get(String.class); . La única forma de que trabaje es copiando la URL a la barra de dirección del navegador y luego de un par de intentos funciona en el navegador y luego en el programa Java. Si alguno de ustedes me puede ayudar con alguna solución se los agradeceré mucho.

Espero que les ayude y les sirva como base para futuros trabajos.

JavaFX by Examples

Una de las formas de aprender es revisando aplicaciones de ejemplo desarrolladas por otras personas, siempre y cuando las estudiemos, las entendamos y muchas veces tomando prestadas algunas características de las mismas.

Cuando los ejemplos se encuentran clasificados según el nivel de conocimiento o el tipo de contenido que presenta la tarea de aprender se convierte una experiencia bastante agradable y motivadora. Esto sucede con una serie de ejemplos que se encuentra en JFXtras Commnuty Site. Como mencionan en su sitio “El objetivo del proyecto JFXtras Samples es suministrar programas JavaFX de ejemplo de calidad, para aprendices y exploradores del lenguaje. Por favor siéntase libre de navegar por los ejemplos y reutilizar cualquier código en tus aplicaciones (todas las licencias son comercialmente amistosas) y contribuye con la comunidad con cualquier ejemplo adicional”.

De lo que entiendo algunos ejemplos son obtenidos desde algunos libros, tales como: JavaFX in Action, Essential JavaFX, JavaFX Developer’s Guide, etc. El link directo hacia los ejemplos es el siguiente JFXtras Samples.

Espero que sea de su ayuda.

Combinando JavaFX y Swing

Como ya lo mencionó Charles Ditzel en su post What’s Wrong With JavaFX and What Needs Fixing? una de las falencias de JavaFX es la ausencia de ciertos controles (ejemplo: árboles y tablas), ésta debilidad se acrecienta cuando lo comparamos con Swing que cuenta con muchos más. (Para ver una lista de los componentes JavaFX visiten: Top 5 most Important Features in JavaFX 1.2).

Para cubrir de cierta forma ésta debilidad, es posible utilizar dentro de una aplicación JavaFX componentes Swing; también se lo puede hacer en sentido contrario, en una aplicación Swing usar JavaFX, pero a través del hacking lo que no garantiza que siga funcionando en versiones posteriores. Para conocer más visiten: How to use JavaFX in Your Swing aplicaciones. Ésta característica, la capacidad de JavaFX de soportar componentes Swing, ha sido explotada en el JavaOne en las conocidas sesiones “Extreme GUI Make Over”, en donde se hace un cambio extremo a una aplicación Swing, ésta vez, para las mejoras se ha utilizado JavaFX dando como resultado una aplicación hibrida entre JavaFX y Swing.

Amy Fowler ha colaborado en el cambio extremo de GUI y ha elaborado un post resumen, en el cual muestra una lista de 10 + 1 pasos necesarios para incluir controles Swing dentro de una aplicación JavaFX. Los 10 pasos son los siguientes:

  • Tocar las bases del lenguaje
  • Descargar el SDK JavaFX
  • Crear un proyecto en NetBeans
  • Crear el “Stage”
  • Definir el layout
  • Embeber los componentes Swing
  • Enganchar los Listeners
  • Agregar efectos
  • Agregar movimiento
  • Hacer tus conclusiones

Para leer el post completamente lee el post: Insider’s Guide to Mixing Swing and JavaFX

JDeveloper ganador como producto de excelencia

Dentro del Great Indian Developer Summit 2008, JDeveloper ha resultado ganador dentro de la categoria “Entornos de Desarrollo”. En una parte del texto se dice:

“Eclipse y Oracle JDeveloper pelearon cabeza a cabeza en ésta categoría. Sin embargo el jurado en consenso señaló a Oracle JDeveloper 11g Preview como el IDE más completo”

Todos reconocemos la importancia de la India dentro del desarrollo de software y ésto para mi parecer es un gran reconocimiento que se le hace a JDeveloper, que desde hace algún tiempo viene cosechando varios premios y reconocimientos.

Como ya se a dicho varias veces ésta es una herramienta desconocida, pero de gran potencial, que no solamente funciona de manera satisfactoria con la base de datos Oracle, sino que permite trabajar con otras bases de datos, otros frameworks y si mal no recuerdo ya tiene desde hace algún tiempo un plugin para la construcción de aplicaciones PHP (que recién NetBeans lo anuncia para su próxima versión 6.5)

Creo que la falta de documentación y no los típicos “How to” han colaborado para el “rechazo” de la herramienta.