Posts Tagged ‘java’

Xtext codea por vos

noviembre 12, 2013

Buenas. El proyecto final de la carrera de Ing. en  Sistemas que estoy desarrollando es un entorno para enseñar programación orientada a objetos en el que puedo ver los objetos de manera gráfica y darles movimiento y un aspecto.

Es un prototipo todavía, pero con suerte y viento a favor en el mediano plazo va a estar completo,  y quién dice no lo podamos poner a prueba con estudiantes.

Está hecho con Xtext, un framework para desarrollar lenguajes e integrarlos fácilmente a eclipse.

Uno define una gramática, Xtext te genera los elementos para parsear y validar el lenguaje y a partir de ella se puede generar código en el lenguaje que prefiera e incluso construir un intérprete sobre la misma plataforma. HOOPE usa Xtensivamente este framework y otros chiches de la API de eclipse.

Xtext permite generar código java muy fácilmente e integrarlo con las APIs de uso común como JAX-WS o JPA.

En el laburo estoy desarrollando servicios web y tengo que admitir que no siempre es fácil la metodología wsdl-first. Sobre todo porque al que solicita los servicios web le cuesta adaptarse a los wsdl. Pero tampoco es cómodo programar de entrada y anotar con jax-ws. Hay mucho código – andamiaje y puede volverse Vogon Poetry.

Y Xtext andaba en mi cabeza…

Con una gramática muy sencilla:

grammar org.miguelius.ws.Generator with org.eclipse.xtext.xbase.Xbase

generate generator "https://lodemiguel.wordpress.com/ws/WsGenerator"

Service:
	('package' packageName=QualifiedName)?
	('targetNamespace' targetNamespace=STRING)?
	'webservice' name=ValidID '{' operations+=Operation+ '}';

Operation:
	name=ValidID '('
	(params+=FullJvmFormalParameter
	(',' params+=FullJvmFormalParameter)*)?
	')'
	'returns'
	'('
	(returned+=FullJvmFormalParameter
	(',' returned+=FullJvmFormalParameter)*)?
	')';

Como el lenguaje está basado en xbase / jvm, puedo usar un inferrer. El inferrer permite generar código con chequeo de tipos a partir del árbol sintáctico:

   	def dispatch void infer(Service element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
		val requests = new HashMap()
		val responses = new HashMap()
   		// Here you explain how your model is mapped to Java elements, by writing the actual translation code.

   				for (operation : element.operations) {

   						val req = operation.toClass(operation.name + 'Request')
   						acceptor.accept(req).initializeLater[
   							packageName=element.packageName
							for (param : operation.params) {
								members += toField(param.name, param.parameterType)
								val getter = toGetter(param.name, param.parameterType)

								val getterAnnotation=findAnnotation(typeof(javax.xml.bind.annotation.XmlElement),param)
								getterAnnotation.addStringValue("name", param.name)
								getter.annotations+=getterAnnotation

								members += getter
								members += toSetter(param.name, param.parameterType)
							}
   						]
   						requests.put(operation, req)

						req.annotations += findAnnotation(typeof(javax.xml.bind.annotation.XmlRootElement),operation)

   						val resp = operation.toClass(operation.name + 'Response')

						resp.annotations += findAnnotation(typeof(javax.xml.bind.annotation.XmlRootElement),operation)
   						acceptor.accept(resp).initializeLater[
   							packageName=element.packageName

							for (param : operation.returned) {
								members += toField(param.name, param.parameterType)
								val getter = toGetter(param.name, param.parameterType)

								val getterAnnotation=findAnnotation(typeof(javax.xml.bind.annotation.XmlElement),param)
								getterAnnotation.addStringValue("name", param.name)
								getter.annotations+=getterAnnotation

								members += getter
								members += toSetter(param.name, param.parameterType)
							}
   						]
   						responses.put(operation, resp)
				}
   		// An implementation for the initial hello world example could look like this:
   		val wsInterface = element.toInterface(element.name,[])
   		//wsInterface.annotations+=findAnnotation(typeof(javax.jws.WebService),element)
   		acceptor.accept(wsInterface)
   			.initializeLater([
   				packageName=element.packageName

   				val webService = findAnnotation(typeof(javax.jws.WebService),element)
   				webService.addStringValue("name", element.name + "Type")
   				annotations+=webService

   				val soapBinding = findAnnotation(typeof(javax.jws.soap.SOAPBinding),element)
   				soapBinding.addEnumValue("parameterStyle",
   					getTypeForName(javax.jws.soap.SOAPBinding.ParameterStyle, element),
   					'BARE'
   				)
   				annotations+=soapBinding
   				for (operation : element.operations) {

					val responseReference = responses.get(operation).fullName.getTypeForName(element)
					val requestReference = requests.get(operation).fullName.getTypeForName(element)

					val operMethod = operation.toMethod(operation.name, responseReference) [
						val parameter = toParameter(requests.get(operation).fullName.toFirstLower,requestReference)
						val webParam = findAnnotation(typeof(javax.jws.WebParam),operation)
							.addStringValue("name", requests.get(operation).fullName)
							.addStringValue("partName", requests.get(operation).fullName)
						parameter.annotations += webParam
						it.parameters+= parameter
					]
					operMethod.annotations+=findAnnotation(typeof(javax.jws.WebMethod),operation)

   					members += operMethod
   				}
   			])

   	}

Esto está en lenguaje xtend y no soy un especialista (dicho con más que pena que gloria). Admite sendos refactors, por ejemplo mejorar los dispatches del método infer. El pseudcódigo se muy sencillo:

  1. Generar una clase Request y Response por objeto con los parámetros de cada una con sus anotaciones JAXB
  2. Generar una interfaz para el Servicio y anotarla con JAX-WS
  3. Agregar las operaciones y anotarlas con JAX-WS

Esto me genera las clases java y la SEI. Heredo de la interfaz y tengo definido el servicio.

De esta manera, me puedo sentar con el cliente y definir un servicio de una manera comprensible para ambas partes y sin ahondar en detalles.

Supongamos que queremos hacer un servicio web para registrar posts que reciba un título y el contenido y me devuelva el ID del post y la URL.


webservice PostService {

RegistrarPost
(String Titulo, String Cuerpo)
returns
(Integer PostID, String URL)

BuscarPostPorID
(Integer PostID)
returns
(String Titulo, String Cuerpo)

}

Esto construye la interfaz PostService, con los métodos RegistrarPost y BuscarPostPorID. A su vez construye las clases RegistrarPostRequest y RegistrarPostResponse y otro par para BuscarPostPorID. Todo con sus anotaciones y listo para nuestra implementación de JAX-WS lo publique.

Con relativamente poco código tenemos un DSL para generar Web Services en java de manera declarativa y accesible a quién conoce el dominio.

Estoy trabajando en agregar tipos compuestos y listas.

Como sea ya tenemos la primer experiencia con Xtext en protoducción.

¡Hasta la próxima!

Anuncios

recolector de basura

abril 28, 2012

bueno, señores, este, no tan joven, finalmente cayó…

todo objeto que uno hace en java, a menos que algo anormal pase en el medio, tiene como destino final el recolector de basura…

ahora entendiendo la naturaleza de los objetos que la jvm espera…

¿qué es esto de los servlets?

enero 12, 2012

Mi inmersión al mundo java web ocurrió hace unos años ya, pero recuerdo que yo andaba medio perdido con muchos nombres nuevos y con poca idea de cómo se hacían las cosas por ese alocado lugar.

Hoy un poco más cascado puedo ordenar algunas ideas y contar un poco lo que aprendí.

Antes que nada responden a una especificación como casi todo en java.

Un servlet es un componente java que permite generar contenido dinámico y que corre en el contexto de contenedor de servlets. Los servlets que usamos para programar web son los HTTP Servlets. Estos corren en un contenedor -que es parte de un servidor web o de un servidor de aplicaciones y que se encarga de manejar la comunicación con el cliente usando el modelo de Petición / Respuesta. Un ejemplo de contenedor de servlets es apache tomcat.

El contenedor suele tener un archivo descriptor de despliegue: el archivo WEB-INF/web.xml.

En este archivo mapeamos las URL con los servlets que vamos creando, configuración de la sesión y otras cosas como definición de filtros y etc.

A diferencia de otras tecnologías, donde se crea todo un proceso por cada solicitud del cliente, un servlet corre en un hilo. Esto genera menos carga para el servidor, por lo que se supondría que es más rápido.

El contendor maneja su ciclo de vida, que empieza llamando al método init(ServletConfig) e inicializa nuestro servlet. Por cada petición que recibe, invoca al método service(ServletRequest, ServletResponse). Finalmente destroy() es invocado cuando el contenedor decide descargarlo y es el momento para liberar recursos.

Los HttpServlet en particular nos abstraen de manejar qué mensaje HTTP implementando el método service y dejándonos a nosotros implementar los distintos mensajes como GET, POST, DELETE y PUT mediante doGet, doPost, doDelete y doPut. Estos a su vez reciben como parámetro los objetos de clase HttpServletRequest y HttpServletResponse. El servlet trabajará con el contexto provisto por el Request y escribirá en el Response los resultados de su ejecución.

En el próximo capítulo vamos a implementar un servlet muy sencillo que recibe una frase y cuenta la cantidad de palabras. Este implementa los métodos de HTTP, POST y GET. Si no recibe nada para contar,  explica el uso y provee un form, si recibe algo directamente muestra el resultado.

¡Hasta la próxima!

agotando las últimas horas de 2011

diciembre 30, 2011

Qué calor que hace! Al fin parece diciembre.

Bueno, lector que pasás por acá, este es un post de cierre de año. Año curioso. En la facu me cambiaron de plan, lo que significó cursar física 2, cosa que por suerte ya pasó y ya quedó afirmada la aprobación en un acta de la facu. Remando y con un par de golpes conseguí el 13/12/11 el título intermedio de Analista Universitario de Sistemas, título que me viene bien laboralmente, aunque no estaba en mis planes originales al ingresar a la facu.

Aprendí algo de computación gráfica y de administración de recursos humanos. Me tengo que poner pillo con la investigación operativa de acá a los primeros días de febrero para recuperarla, que me quedo colgando.

Hice un curso de metodologías de desarrollo seguro, dictado por Cristian Borghello. Es curioso, pero cada vez más veo la necesidad de aplicar metodologías a esto de programar, pero por otro lado las urgencias o tal vez la falta de disciplina de uno, hacen que uno termine a mitad de camino. Es algo que le pasa mucho a quién escribe, sabe que es lo correcto, pero por alguna razón no llega a ponerlo en marcha.

¡Scala es un bodrio! Java 7 llegó tarde y con pocas cosas divertidas. Al parece Java 8 la va a romper. A quien ande en esta no tan noble profesión del desarrollo web en java le recomiendo Como funciona tomcat. El libro explica como funcionan las versiones 4 y 5 del servidor planteando el diseño como si lo quisieramos programar de nuevo.

Recomiendo encaresidamente el libro Kryptonita de Leonardo Oyola. La cosa es más o menos así, el nafta super no es como nosotros. Evidentemente vino de otro lado, pero por razón terminó viviendo entre nosotros. Hay quien dice que si hubiera terminado en otros lados, como en una granja en arkansas, hoy sería el super hombre -no, el de nietzche y sus seguidores folkloristas alemanes, no!-, ese que se para por sobre todos y lucha por la justicia y los mercados. Como sea nuestro nafta súper tuvo un percance, y cayó en la guardia del Paroissien. Un nochero (doctor que cubre guardias por otro a un costo humano muy elevado) tendrá que mantenerlo con vida, mientras sus super amigos lo cuidan del horror… el horror…

Como sea el libro del párrafo anterior es el libro del año.

Con esto de la investigación operativa me dio curiosidad la película esa de la mente brillante, acerca del matemático Nash. creo que también podría haberse llamado “una película intrascendente”. Más allá del drama personal del compañero Nash, el personaje de russel crowe no pasa el test de turing.

Ciudadano Kane la rompe. Matt Groenning le debe mucho.

Creo que el blog del año es (aunque no de este para el autor, pero sí para mí que llegué tarde, pa’variar) es realismo socialista del dibujante Galliano. En el blog, el dibujante publica sus obras (no, no faltó una s) y se ve que el pibe tiene oficio. Yo creo que dejaría a Nik en la lona si a la nación se copase con el cinismo de izquirdas. Pero la nación es una mierda y nik seguirá en la delincuencia de cuello blanco. Soberbia la serie Lenin y vos!

Bueno, yo estoy contento. Muy vago con esto del blog. Pero como todos los años me propongo darle un poco de vida.

Aflojen con la quiniela! Los números también pueden ser el más grande ejercicio para la cabeza.

Ahora me voy a ver a Almafuerte.

Feliz año, lector!

eScalando

mayo 20, 2011

Hace un tiempo ya que estoy trabajando con java. También me tocó pasarlo con alguna materia de la facu.

Java está bien, pero lo pone a uno poco más charlatán de lo que debería. Y no lo digo por los debates acerca si sigue sirviendo o no, si tipado o no, si interpretado o …

Hay muchas cosas que se vuelven repetitivas. Si uno quiere evitar código redundante, tiene que empezar a fabricar clases para cubrir estos baches. Esas clases hacen más ruido del que deberían hacer (eso que la literatura anglo parlante llama boiler plate code).

Hay por ahí un lenguaje que se llama Scala, que ya tiene sus años y que estoy usándolo para probar. Los vendedores de elixhir sostienen que es la felicidad en tu java virtual machine. Scala es la contracción de SCAlable LAnguage.

Del nombre surgen dos interpretaciones, una por el rendimiento del equipo y la paralelización del código al favorecer estructuras inmutables, y la otra interpretación es por el rendimiento del lenguaje según el programador. En scala podés programar objetos y funcional, o muy para un lado o muy para el otro, todo depende del palo del que vengás. Ahora a medida que vas aprendiendo, vas aplicando mejor el paradigma que te conviene y tu código es más claro. También promete facilidad para generar tus lenguajes de dominio específico, que es casualmente una curiosidad que me pica desde que me enteré que existía LISP y todo eso de extender el lenguaje.

Me parece interesante eso de que el lenguaje “te deje” entrar con tu estilo y que vayás aprendiendo, manteniendo tu JVM abajo. Creo que eso tiene gancho para el ambiente profesional y académico.

Así que para ahí voy.

Como ya tengo algo de programación funcional (haskell mediante) encima, no me parece tan raro.

Como regalo al peregrino le dejo una función escrita en scala y un par de líneas para probarla:

def funcionUltraConocida(n: Int) = (2 to n).foldLeft (1) (_ * _)
def esLaRespuesta = 42.equals(_)
esLaRespuesta (funcionUltraConocida(7) / funcionUltraConocida(5))

¡Suerte! Hoy tengo parcial de física 2 y está bastante complicado.