Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Friday, September 17, 2010

Force JPA load Identity ID after Insert

When you have an ID into your Entity Classe from Database and that is Identity, if you do an insert action the ID of this Entity isn't reloaded by default with the ID that was generated by Database, through JPA.

A sample of an ID of Identity kind:

@Id
@Basic(optional = false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "Id")
private Integer id;


To refresh the ID value with the ID that was generated by the Database on insert action, you need put more this below in your AbstractFacade.Create(EntityClass):

getEntityManager().flush();
getEntityManager().refresh(entity);


  • getEntityManager().flush() - Will do the commit to Database execute the insert action.

  • getEntityManager().refresh(entity) - Will refresh the entity object with a new ID that was inserted.


Full sample of the AbstractFacade.java:

package org.test.ejb;

import java.util.List;
import javax.persistence.EntityManager;

public abstract class AbstractFacade {
private Class entityClass;

public AbstractFacade(Class entityClass) {
this.entityClass = entityClass;
}

protected abstract EntityManager getEntityManager();

public void create(T entity) {
getEntityManager().persist(entity);
getEntityManager().flush();
getEntityManager().refresh(entity);
}

public void edit(T entity) {
getEntityManager().merge(entity);
}

public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}

public T find(Object id) {
return getEntityManager().find(entityClass, id);
}

public List findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}

public List findRange(int[] range) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0]);
q.setFirstResult(range[0]);
return q.getResultList();
}

public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
}


If you publish your JPA Create action in a Web Services, you will need return to client side an Entity instance to client know what is the new ID. Cause the Entity instance of the Client side can't be refresh with changes inside Server.
Like:

@WebMethod(operationName = "create")
public BusinessEntity create(@WebParam(name = "businessEntity")
BusinessEntity businessEntity) {
ejbRef.create(businessEntity);
return businessEntity;
}


Wednesday, September 15, 2010

Web Service - A cycle is detected in the object graph. This will cause infinitely deep XML...

When a Web Service that uses an EJB that exposes an Entity Class and this Entity Class makes relationships with another Entity Class, may be you will receives this error:

Caused by: javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: org.test.data.Business[id=1] -> org.test.data.BusinessType[id=1] -> org.test.data.Business[id=1]]
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:269)
at com.sun.xml.bind.v2.runtime.BridgeImpl.marshal(BridgeImpl.java:100)
at com.sun.xml.bind.api.Bridge.marshal(Bridge.java:141)
at com.sun.xml.ws.message.jaxb.JAXBMessage.writePayloadTo(JAXBMessage.java:317)
... 35 more
Caused by: com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: org.test.data.Business[id=1] -> org.test.data.BusinessType[id=1] -> org.test.data.Business[id=1]
at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:248)
at com.sun.xml.bind.v2.runtime.XMLSerializer.pushObject(XMLSerializer.java:537)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:631)
at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:65)
at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:168)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:155)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:152)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:65)
at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:168)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:155)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:264)
... 38 more



To this error above you can found solutions saying to use this interface:
  • com.sun.xml.internal.bind.CycleRecoverable


NetBeans recognize this package and not mark like an error. But on compile time this package does not exist to compiler side. Perhaps you will receive this error when compiles:


/home/eduveks/project/wstest/src/org/test/data/Business.java:8: package com.sun.xml.internal.bind does not exist
import com.sun.xml.internal.bind.CycleRecoverable;


On my view this error is a bug of NetBeans that recognizes this package when isn't a valid package to Java compiler. To test this bug you only need put this "import com.sun.xml.internal.bind.CycleRecoverable;" into any Java file and you will see that NetBeans don't says nothing and accept as well, but if you "Clean and Build" the error will show up.

The correct package is (without .internal):


import com.sun.xml.bind.CycleRecoverable;


To uses that package path above you need add it:

Project Properties -> Libraries -> "Add Library...", select JAXB 2.2 and "Add Library".

A sample how to implements the com.sun.xml.bind.CycleRecoverable:

    > Business.java

package org.test.data;

import com.sun.xml.bind.CycleRecoverable;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlIDREF;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.test.data.adapter.IntegerAdapter;

@Entity
@Table(name = "Business")
@NamedQueries({
@NamedQuery(name = "Business.findAll", query = "SELECT b FROM Business b"),
@NamedQuery(name = "Business.findById", query = "SELECT b FROM Business b WHERE b.id = :id"),
@NamedQuery(name = "Business.findByNome", query = "SELECT b FROM Business b WHERE b.name = :name"),
public class Business implements Serializable, CycleRecoverable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "Id")
private Integer id;
@Basic(optional = false)
@Column(name = "Name")
private String name;
@JoinColumn(name = "BusinessTypeId", referencedColumnName = "Id")
@ManyToOne(optional = false)
private BusinessType businessType;

public Business() {
}

public Business(Integer id) {
this.id = id;
}

public Business(Integer id, String name) {
this.id = id;
this.name = name;
}

@XmlID
@XmlJavaTypeAdapter(value = IntegerAdapter.class, type = String.class)
public Integer getId() {
return id;
}

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

public String getName() {
return name;
}

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

@XmlIDREF
public BusinessType getBusinessType() {
return businessType;
}

public void setBusinessType(BusinessType businessType) {
this.businessType = businessType;
}

@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Business)) {
return false;
}
Business other = (Business) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "org.test.data.Business[id=" + id + "]";
}

@Override
public Object onCycleDetected(Context cntxt) {
System.out.println("CycleRecoverable.onCycleDetected # ".concat(this.toString()));
Business n = new Business();
n.setId(this.getId());
return n;
}
}


    > BusinessType.java

package org.test.data;

import com.sun.xml.bind.CycleRecoverable;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlIDREF;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.test.data.adapter.IntegerAdapter;

@Entity
@Table(name = "BusinessType")
@NamedQueries({
@NamedQuery(name = "BusinessType.findAll", query = "SELECT bt FROM BusinessType bt"),
@NamedQuery(name = "BusinessType.findById", query = "SELECT bt FROM BusinessType bt WHERE bt.id = :id"),
@NamedQuery(name = "BusinessType.findByName", query = "SELECT bt FROM BusinessType bt WHERE bt.name = :name")})
public class BusinessType implements Serializable, CycleRecoverable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "Id")
private Integer id;
@Basic(optional = false)
@Column(name = "Name")
private String name;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "BusinessType")
private Collection businessCollection;

public BusinessType() {
}

public BusinessType(Integer id) {
this.id = id;
}

public BusinessType(Integer id, String name) {
this.id = id;
this.name = name;
}

@XmlID
@XmlJavaTypeAdapter(value = IntegerAdapter.class, type = String.class)
public Integer getId() {
return id;
}

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

public String getName() {
return name;
}

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

@XmlIDREF
public Collection getBusinessCollection() {
return businessCollection;
}

public void setBusinessCollection(Collection businessCollection) {
this.businessCollection = businessCollection;
}

@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof BusinessType)) {
return false;
}
BusinessType other = (BusinessType) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "org.test.data.BusinessType[id=" + id + "]";
}

@Override
public Object onCycleDetected(Context cntxt) {
System.out.println("CycleRecoverable.onCycleDetected # ".concat(this.toString()));
BusinessType n = new BusinessType();
n.setId(this.getId());
return n;
}
}


You need mark the IDs with @XmlID(only before the get method, before the variable declaration don't works):

@XmlID
@XmlJavaTypeAdapter(value = IntegerAdapter.class, type = String.class)
public Integer getId() {
return id;
}

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


And mark all Collection relationships methods with @XmlIDREF(only before the get method, before the variable declaration don't works):

    > BusinessType.java

@XmlIDREF
public Collection getBusinessCollection() {
return businessCollection;
}

public void setBusinessCollection(Collection businessCollection) {
this.businessCollection = businessCollection;
}


Sample of the IntegerAdapter.java:

package org.test.data.adapter;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class IntegerAdapter extends XmlAdapter {

@Override
public Integer unmarshal(String v) {
return Integer.parseInt(v);
}

@Override
public String marshal(Integer v) {
return v.toString();
}
}



Monday, September 28, 2009

Process ID

Quando se faz um serviços Unix em Java para poder fazer os scripts de stop, kill, etc, é preciso o PID (número do processo), então para tal é preciso gerar um arquivo que contém esta informação.

Portanto este código faz exatamente isto, gera um arquivo com o PID da aplicação Java:

java.io.BufferedWriter bw = null;
try {
bw = new java.io.BufferedWriter(new java.io.OutputStreamWriter(new java.io.FileOutputStream("my.pid")));
String pidInfo = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
bw.write(pidInfo.substring(0, pidInfo.indexOf('@')));
} finally {
if (bw != null) bw.close();
}

Friday, June 19, 2009

Jetty e Web Services com JAX-WS

O Jetty é um poderoso servidor web, disto não há dúvidas, mas no que toca a web services paira uma nuvem negra, não há muita documentação e nem integração com IDEs.

Depois de pesquisar um pouco vi que era possível integrar com o JAX-WS.

Não encontrei nenhuma explicação detalhada de como fazer, e que explicasse também a parte do cliente, então resolvi fazer o download do JAX-WS e ver os exemplos e a documentação, e a conclusão que cheguei segue abaixo.

Levando em consideração que já tem o Jetty configurado e rodando, no meu caso foi a versão 6 e com o JDK 6.

Fazer o download do JAX-WS no meu caso foi a versão 2.1.7 em:

https://jax-ws.dev.java.net/

Descompactar e em jaxws-ri/docs/UsersGuide.html#3.1_Server da para ver alguma explicação de como fazer.

Copiar todos os jars que estão na pasta lib do JAX-WS para a pasta lib/ext do Jetty.

Agora no seu projeto web criar as seguintes classes de exemplo (também estão em jaxws-ri/samples/fromjava/src), aqui dei alguma melhoria nas anotações:

-> fromjava/server/AddNumbersImpl.java:

package fromjava.server;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
import javax.annotation.Resource;
@WebService
public class AddNumbersImpl {
@Resource
private WebServiceContext context;
@WebMethod(operationName = "add")
public int addNumbers(@WebParam(name = "first") int number1, @WebParam(name = "second") int number2) throws AddNumbersException {
// SERVLET - IF NEED SERVLET RESOURCES. For example to do session control.
MessageContext messageContext = context.getMessageContext();
ServletContext servletContext = (ServletContext)messageContext.get(MessageContext.SERVLET_CONTEXT);
HttpServletRequest servletRequest = (HttpServletRequest)messageContext.get(MessageContext.SERVLET_REQUEST);
HttpServletResponse servletResponse = (HttpServletResponse)messageContext.get(MessageContext.SERVLET_RESPONSE);
// --
if (number1 < 0 || number2 < 0) {
throw new AddNumbersException("Negative number cant be added!",
"Numbers: " + number1 + ", " + number2);
}
return number1 + number2;
}
}

-> fromjava/server/AddNumbersException.java:

package fromjava.server;
public class AddNumbersException extends Exception {
String detail;
public AddNumbersException (String message, String detail) {
super (message);
this.detail = detail;
}
public String getDetail () {
return detail;
}
}

Acrescentar no web.xml:

<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<description>JAX-WS endpoint - fromjava</description>
<display-name>fromjava</display-name>
<servlet-name>fromjava</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>fromjava</servlet-name>
<url-pattern>/addnumbers</url-pattern>
</servlet-mapping>

E junto com o web.xml criar o arquivo sun-jaxws.xml:

<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'>
<endpoint
name='fromjava'
implementation='fromjava.server.AddNumbersImpl'
url-pattern='/addnumbers'/>
</endpoints>

Feito isto, é rodar o Jetty e ver o WSDL:

http://localhost:8080/WSTester/addnumbers?WSDL

Onde o WSTester é o nome do seu projeto.

Agora temos que criar as classes para chamar o web service, para isto o JAX-WS trás o bin/wsimport, no meu caso como estou no Linux vou usar o .sh, caso esteja no Windows é só usar o .bat, criar as pastas src e dest dentro da pasta do JAX-WS.

$ chmod +x bin/wsimport.sh
$ mkdir dest
$ mkdir src
$ bin/wsimport.sh -d dest -s src http://localhost:8080/WSTester/addnumbers?WSDL

O wsimport vai gerar o código das classes para invocar o web service na pasta src, e as classes compiladas em dest.

Eu peguei na pasta src/fromjava e copiei para o um outro projeto de aplicação do tipo consola em Java. Assim pode chamar o web service:

TestAddNumbers.java:

package javaapplicationWSTester;
import fromjava.server.*;
public class TestAddNumbers {
public static void main(String[] args) throws AddNumbersException_Exception {
int result = new AddNumbersImplService().getAddNumbersImplPort().add(3, 5);
System.out.println(result);
}
}

O processo é simples, ter a classe do web service, configurar no web.xml e no sun-jaxws.xml, gerar as classes de invocação com o wsimport e boa :P

Monday, June 9, 2008

GlassFish vs Apache

Gastei um tempinho para desvendar certos mistérios por trás desta configuração e contornar alguns problemas.

Para configurar segui o post do Jean-Francois Arcand's e da Amy Roh's.

Então vamos lá!

Primeiro no Apache, instalar o mod_jk:

apt-get install libapache2-mod-jk

Configurar o conteúdo do arquivo /etc/apache2/mods-available/jk.load:

# Modulo do mod_jk
LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so
# Arquivo de configuração
JkWorkersFile /etc/apache2/mod_jk_worker.properties
# Arquivo de log
JkLogFile /var/log/apache2/mod_jk.log
# Nível de detalhe dos logs [debug/error/info]
JkLogLevel debug
# Formato das mensagens de log
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
# JkOptions indica para enviar SSL KEY SIZE
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
# JkRequestLogFormat define o formato dos requests no Log
JkRequestLogFormat "%w %V %T"
# Envia todos jsp para o GlassFish
JkMount /*.jsp worker1
# Envia todos os acessos ao meu projeto web para o GlassFish
JkMount /WebApplication/* worker1

Na última linha, o WebApplication se refere ao nome do nosso projeto no GlassFish, coloque aqui o nome do teu projeto no GlassFish.

Agora falta configurar o /etc/apache2/mod_jk_worker.properties, com este conteúdo:

# Define 1 worker usando ajp13
worker.list=worker1
# Define as propriedades do worker1 (ajp13)
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009
worker.worker1.lbfactor=50
worker.worker1.cachesize=10
worker.worker1.cache_timeout=600
worker.worker1.socket_keepalive=1
worker.worker1.socket_timeout=300

Agora vamos ao GlassFish...

No Glassfish configurar as seguintes opções da JVM:

$GLASSFISH_HOME/bin/asadmin create-jvm-options -Dcom.sun.enterprise.web.connector.enableJK=8009

E também:

$GLASSFISH_HOME/bin/asadmin create-jvm-options -Dcom.sun.enterprise.web.connector.enableJK.propertyFile=/etc/apache2/mod_jk_worker.properties

Para confirmar se ficou bem configurado, verifique o arquivo:

$GLASSFISH_HOME/domains/domain1/config/domain.xml

Procurar neste arquivo por:

<jvm-options>-Dcom.sun.enterprise.web.connector.enableJK=8009</jvm-options>
<jvm-options>-Dcom.sun.enterprise.web.connector.enableJK.propertyFile=/etc/apache2/mod_jk_worker.properties</jvm-options>

Fazer o download do apache-tomcat-5.5.16.zip, e pegar o tomcat-ajp.jar, só serve o jar desta versão, os das versões superiores não funcionam, provocam o seguinte erro no GlassFish:

Caused by: java.lang.NoSuchMethodError: org.apache.coyote.Response.getContentLengthLong()J

Depois do download, procurar o tomcat-ajp.jar dentro do zip:

apache-tomcat-5.5.16/server/lib/tomcat-ajp.jar

E copiar este jar para dentro do GlassFish:

$GLASSFISH_HOME/lib/

Também são precisos os jars commons-modeler e commons-logging, que podem ser adquiridos aqui:

http://commons.apache.org/downloads/index.html

Modeler:
http://commons.apache.org/downloads/download_modeler.cgi

Logging:
http://commons.apache.org/downloads/download_logging.cgi

Copiar estes dois jars também para dentro do:

$GLASSFISH_HOME/lib/

Feito isto, é preciso reiniciar o Apache e o GlassFish, e agora deverá estar funcionando através do Apache:

http://localhost/WebApplication

Assim através do Apache da para acessar os projetos publicados no GlassFish!

O porto 8009 que configuramos para o JK não tem nada haver com o porto web do GlassFish, o mod JK usa um protocolo próprio para comunicar com o Tomcat/AJP, e o GlassFish o que faz é inicia um novo porto usando o JK do Tomcat para poder comunicar com o mod_jk no Apache, e para testar se este porto esta funcionando pode-se usar o telnet e ver se conecta:

telnet localhost 8009

Futuramente pretendo investigar sobre Load Balancing usando o Apache e Glassfish e espero falar sobre isto.

Friday, March 28, 2008

Que tal uma sintaxe em Portugues?


IMPORTANTE: O conteúdo deste post é sempre atualizado para a última versão do CajuScript.


Exemplo de uma sintaxe em Português usando o CajuScript.

Faça o download do CajuScript.

Na mesma pasta em que esta o jar do CajuScript crie o arquivo "carregaSintaxePortugues.cj", com o seguinte conteúdo:

[CODE]
$java.util.regex

syntaxPT = org.cajuscript.Syntax()
syntaxPT.setIf(Pattern.compile("^[\\s+s|s]e\\s*([\\s+|[\\s*\\(]].+)\\s*faz"))
syntaxPT.setElseIf(Pattern.compile("^[\\s+o|o]u\s+se\\s*([\\s+|[\\s*\\(]].+)\\s*faz"))
syntaxPT.setElse(Pattern.compile("^[\\s+o|o]u\\s+senao\\s+fa[z\\s+|z]$"))
syntaxPT.setIfEnd(Pattern.compile("^[\\s+f|f]i[m\\s+|m]$"))
syntaxPT.setLoop(Pattern.compile("^[\\s+e|e]nquanto\\s*([\\s+|[\\s*\\(]].+)\\s*faz"))
syntaxPT.setLoopEnd(Pattern.compile("^[\\s+f|f]i[m\\s+|m]$"))
syntaxPT.setTry(Pattern.compile("^[\\s+t|t]enta\\s*([\\s+|[\\s*\\(]].+)\\s*faz"))
syntaxPT.setTryCatch(Pattern.compile("^[\\s+p|p]ega\\s+o\\s+err[o\\s+|o]$"))
syntaxPT.setTryFinally(Pattern.compile("^[\\s+f|f]inalment[e\\s+|e]$"))
syntaxPT.setTryEnd(Pattern.compile("^[\\s+f|f]i[m\\s+|m]$"))
syntaxPT.setFunction(Pattern.compile("^[\\s+f|f]uncao\\s*([\\s+|[\\s*\\(]].+)\\s*faz"))
syntaxPT.setFunctionEnd(Pattern.compile("^[\\s+f|f]i[m\\s+|m]$"))
syntaxPT.setNull(Pattern.compile("nulo"))
syntaxPT.setReturn(Pattern.compile("retorna"))
syntaxPT.setImport(Pattern.compile("importa\\s+"))
syntaxPT.setRootContext(Pattern.compile("raiz\\."))
syntaxPT.setContinue(Pattern.compile("continua"))
syntaxPT.setBreak(Pattern.compile("para"))
syntaxPT.setOperatorOr(Pattern.compile("[\\s+|)\\s*]ou[\\s+|(\\s*]"))
syntaxPT.setOperatorAnd(Pattern.compile("[\\s+|)\\s*]e[\\s+|(\\s*]"))

org.cajuscript.CajuScript.addGlobalSyntax("PT", syntaxPT)

$"exemploSintaxePortugues.cj"
[/CODE]

E também o arquivo "exemploSintaxePortugues.cj", com o seguinte conteúdo:

[CODE]
caju.syntax: PT

importa java.lang

// IF = SE
x = 10
se x < 10 e x > 0 faz
System.out.println("X menor que 10!")
ou se x > 10 e x ! 10 faz
System.out.println("X maior que 10!")
ou se x = 10 ou x ! 0 faz
System.out.println("X igual 10!")
ou senao faz
System.out.println("X menor que 1!")
fim

// LOOP = ENQUANTO
x = 0
enquanto x < 100 e x >= 0 faz
System.out.println(x)
x += 1
se x = 10 faz
para
ou senao faz
continua
fim
fim

// FUNCTION = FUNCAO
x = 5
funcao addWithX(v1, v2) faz
retorna raiz.x + v1 + v2
fim
x = addWithX(10, 20)
System.out.println("X = "+ x)

// TRY/CATCH = TENTA/PEGA
tenta e faz
"".substring(0, -1)
pega o erro
System.out.println("Erro: "+ e.getMessage())
finalmente
System.out.println("Finalmente...")
fim

System.out.println("\n\nSyntax em portugues executada com sucesso!\n")

Thread.sleep(10000)
[/CODE]

Agora é só executar com o comando:

[CODE]
java -jar cajuscript.jar carregaSintaxePortugues.cj
[/CODE]

Pronto! :P

Não convêm usar acentos na sintaxe, por que pode dar alguns problemas de encoding ao transportar o arquivo por vários sistemas operacionais, como do linux para o windows. Mas quem não arrisca não petisca.

Toda sugestão é bem vinda.

Sunday, January 13, 2008

NetBeans 6 vs OpenSuse 10.3

Se tiver problemas com OpenSuse 10.3 para rodar o NetBeans 6, o bug-buddy acusando um bug e parando a execução logo na inicialização. Então vou explicar como instalar o JDK 6 e o NetBeans 6 no OpenSuse 10.3 e resolver este problema.

Instalação JDK 6:
- Em java.sun.com abrir o link para o Java SE, depois fazer o download do JDK 6 Update 4 versão para Linux o que tem a extenção .rpm.bin:
jdk-6u4-linux-x64-rpm.bin
- Dar permissões de execução para o arquivo:
chmod +x jdk-6u4-linux-x64-rpm.bin
- Executar:
./jdk-6u4-linux-x64-rpm.bin
- Vai ser criado no mesmo diretório varios arquivos *.rpm, para instalar execute:
sudo /sbin/yast2 -i jdk-6u4-linux-amd64.rpm
- O JDK 6 será instalado em:
/usr/java/jdk1.6.0_04
- E também terá estes atalhos para o jdk:
/usr/java/latest
/usr/java/default

Instalação NetBeans 6:
- Em www.netbeans.org faça o download do NetBeans 6 versão Linux, eu usei a versão "All".
- Dar permissões de execução para o arquivo:
chmod +x netbeans-6.0-linux.sh
- Eu instalei em /opt, caso queira instalar ai também faça assim:
sudo mkdir /opt/netbeans-6.0
sudo chmod a+rwx /opt/netbeans-6.0
sudo mkdir /opt/glassfish-v2
sudo chmod a+rwx /opt/glassfish-v2
- Agora execute o arquivo de instalação do NetBeans 6, e escolha a pasta de instalação, se for no /opt/netbeans-6.0 escolha esta pasta e o GlassFish também /opt/glassfish-v2, e eu coloquei em JDK /usr/java/latest.
- Será criado atalhos no desktop e nos programas.
- Execute...

Caso de Error, do bug-buddy, como aconteceu no meu caso, ele pode ser removido, não vai fazer falta, para o remover execute:
sudo zypper rm bug-buddy

Agora é só executar outra vez e deverá ter o problema resolvido, e o NetBeans 6 a funcionar perfeitamente.

Monday, June 4, 2007

Object.clone();

Para entender como funciona a clonagem de objetos em Java fiz este exemplo, basta analizar o codigo e a execuçao, e tirar as proprias conclusões :P

[CODE]

public class RunVehiclesClone {

public static void main(String[] args) {
System.out.println();
System.out.println("===================================");
System.out.println();
run();
System.out.println("===================================");
System.out.println();
runClone();
System.out.println("===================================");
System.out.println();
runCloneDeep();
System.out.println("===================================");
System.out.println();
runCloneSerialization();
System.out.println("===================================");
System.out.println();
}

private static void run() {
System.out.println("-----------------------------------");
System.out.println("NORMAL");
System.out.println("-----------------------------------");
java.util.List<Vehicle> listVehicles = new java.util.ArrayList();

Vehicle vehicle = new Vehicle();
vehicle.setName("Vehicle");

VehicleDescription vehicleDescription = new VehicleDescription();
vehicleDescription.setName("Description");

vehicle.setVehicleDescription(vehicleDescription);

listVehicles.add(vehicle);

Vehicle superBike = vehicle;
superBike.setName("SuperBike");
superBike.getVehicleDescription().setName("Kawasaki Ninja ZXR6");

listVehicles.add(superBike);

Vehicle car = vehicle;
car.setName("Car");
car.getVehicleDescription().setName("Audi A3");

listVehicles.add(car);

System.out.println();
for (Vehicle _vehicle : listVehicles) {
System.out.println(_vehicle);
System.out.println();
}
}

private static void runClone() {
System.out.println("-----------------------------------");
System.out.println("CLONE");
System.out.println("-----------------------------------");
java.util.List<Vehicle> listVehicles = new java.util.ArrayList();

Vehicle vehicle = new Vehicle();
vehicle.setName("Vehicle");

VehicleDescription vehicleDescription = new VehicleDescription();
vehicleDescription.setName("Description");

vehicle.setVehicleDescription(vehicleDescription);

listVehicles.add(vehicle);

Vehicle superBike = (Vehicle)vehicle.clone();
superBike.setName("SuperBike");
superBike.getVehicleDescription().setName("Kawasaki Ninja ZXR6");

listVehicles.add(superBike);

Vehicle car = (Vehicle)vehicle.clone();
car.setName("Car");
car.getVehicleDescription().setName("Audi A3");

listVehicles.add(car);

System.out.println();
for (Vehicle _vehicle : listVehicles) {
System.out.println(_vehicle);
System.out.println();
}
}

private static void runCloneDeep() {
System.out.println("-----------------------------------");
System.out.println("CLONE > DEEP");
System.out.println("-----------------------------------");
java.util.List<Vehicle> listVehicles = new java.util.ArrayList();

Vehicle vehicle = new Vehicle();
vehicle.setName("Vehicle");

VehicleDescription vehicleDescription = new VehicleDescription();
vehicleDescription.setName("Description");

vehicle.setVehicleDescription(vehicleDescription);

listVehicles.add(vehicle);

Vehicle superBike = (Vehicle)vehicle.cloneDeep();
superBike.setName("SuperBike");
superBike.getVehicleDescription().setName("Kawasaki Ninja ZXR6");

listVehicles.add(superBike);

Vehicle car = (Vehicle)vehicle.cloneDeep();
car.setName("Car");
car.getVehicleDescription().setName("Audi A3");

listVehicles.add(car);

System.out.println();
for (Vehicle _vehicle : listVehicles) {
System.out.println(_vehicle);
System.out.println();
}
}

private static void runCloneSerialization() {
System.out.println("-----------------------------------");
System.out.println("CLONE > SERIALIZATION");
System.out.println("-----------------------------------");
java.util.List<Vehicle> listVehicles = new java.util.ArrayList();

Vehicle vehicle = new Vehicle();
vehicle.setName("Vehicle");

VehicleDescription vehicleDescription = new VehicleDescription();
vehicleDescription.setName("Description");

vehicle.setVehicleDescription(vehicleDescription);

listVehicles.add(vehicle);

Vehicle superBike = (Vehicle)vehicle.cloneSerialization();
superBike.setName("SuperBike");
superBike.getVehicleDescription().setName("Kawasaki Ninja ZXR6");

listVehicles.add(superBike);

Vehicle car = (Vehicle)vehicle.cloneSerialization();
car.setName("Car");
car.getVehicleDescription().setName("Audi A3");

listVehicles.add(car);

System.out.println();
for (Vehicle _vehicle : listVehicles) {
System.out.println(_vehicle);
System.out.println();
}
}
}

//////////////////////////////////////////////

class Vehicle implements java.io.Serializable, Cloneable {
private String name = "";
private VehicleDescription vehicleDescription = null;

public Vehicle() {

}

public void setName(String _name) {
name = _name;
}

public String getName() {
return name;
}

public void setVehicleDescription(VehicleDescription _vehicleDescription) {
vehicleDescription = _vehicleDescription;
}

public VehicleDescription getVehicleDescription() {
return vehicleDescription;
}

public Object clone() {
try {
return super.clone();
} catch(CloneNotSupportedException e) {
throw new Error ("Cannot clone this object.");
}
}

public Object cloneDeep() {
try {
Vehicle vehicle = (Vehicle)super.clone();
VehicleDescription _vehicleDescription = new VehicleDescription();
_vehicleDescription.setName(getVehicleDescription().getName());
vehicle.setVehicleDescription(_vehicleDescription);
return vehicle;
} catch(CloneNotSupportedException e) {
throw new Error ("Cannot clone this object.");
}
}

public Object cloneSerialization() {
java.io.ObjectOutputStream oos = null;
java.io.ObjectInputStream ois = null;
try {
java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
oos = new java.io.ObjectOutputStream(bos);
oos.writeObject(this);
oos.flush();
java.io.ByteArrayInputStream bin = new java.io.ByteArrayInputStream(bos.toByteArray());
ois = new java.io.ObjectInputStream(bin);
return ois.readObject();
} catch(Exception e) {
throw new Error ("Cannot clone this object.");
} finally {
try {
oos.close();
ois.close();
} catch(Exception e) {
}
}
}

public String toString() {
return name + " - " + vehicleDescription;
}
}

//////////////////////////////////////////////

class VehicleDescription implements java.io.Serializable {
String name = "";
java.sql.Connection con = null;
public VehicleDescription() {

}

public void setName(String _name) {
name = _name;
}

public String getName() {
return name;
}

public String toString() {
return name;
}
}

[/CODE]