Mostrando postagens com marcador java. Mostrar todas as postagens
Mostrando postagens com marcador java. Mostrar todas as postagens

sexta-feira, 24 de julho de 2015

IntelliJ IDEA rodando com JVM mais nova no MAC OS X

Caso tenha atualizado seu MAC OS X e após isso passou a receber a mensagem que o IntelliJ IDEA precisa rodar em uma versão legada (legacy) da JVM, a solução para mim foi a seguinte.

No terminal:

cd /Applications/IntelliJ\ IDEA\ 14.app/Contents
vi Info.plist

OBS.: O número 14 no caminho acima é a versão do meu IntelliJ, mude esse número para a sua versão da aplicação.

Após isso, digite "/" para habilitar a busca e em seguida digite "JVMVersion" e "enter".

Note que logo abaixo da string encontrada vc verá a versão 1.6*. Mude o 6 por 8 e em seguida salve o documento "esc + wq + enter".

Tente abrir o Intellij novamente. ;-)

segunda-feira, 19 de novembro de 2012

Log de Auditoria - JPA + Spring

Vira e volta, aparecem sistemas onde é necessário fazer um esquema de log de auditoria para uma tabela ou várias.

Montei um esquema que pode ser facilmente extendido para outras tabelas do sistema, para fazê-lo, basta seguir os passos abaixo:

1- Criar um enum para representar as ações de banco:
public enum TransactionType {
    CREATE, UPDATE, DELETE;
}


2- Criar a entidade de log de auditoria:
@Entity
@Table(name = "log_trace")
@AttributeOverride(name = "id", column = @Column(name = "log_trace_id"))
public class LogTrace extends BaseEntity {

    @Column(name = "transaction_type", nullable = false)
    @Enumerated(EnumType.STRING)
    private TransactionType transactionType;

    @Column(name = "entity_name", nullable = false)
    private String entityName;

    @Column(name = "registry_id", nullable = false)
    private Long registryId;

    @Column(name = "operation_date", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date operationDate;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "executed_by", nullable = false)
    private User executedBy;

...getters e setters...
}


3- Criar o repositório (DAO) e o serviço como está sendo feito no restante do sistema;

4- Criar o listener que será disparado pelo hibernate:
public class LogTraceListener {

    @Autowired
    LogTraceService logTraceService;


    @Autowired
    UserService userService;

    @PostRemove
    void postDelete(BaseEntity e) {
        createLog(TransactionType.DELETE, e);
    }

    @PostPersist
    void postPersist(BaseEntity e) {
        createLog(TransactionType.CREATE, e);
    }

    @PostUpdate
    void postUpdate(BaseEntity e) {
        createLog(TransactionType.UPDATE, e);
    }

    private void createLog(TransactionType transactionType, BaseEntity e) {
        /*
         * OBSERVAÇÃO 1.
         */
        if (logTraceService == null) {
            ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext();

            logTraceService = (LogTraceService) ctx.getBean("logTraceService");
        }

        /*
         * OBSERVAÇÃO 2.
         */
        User user = userService.getAuthenticatedUser();

        LogTrace logTrace = new LogTrace();
        /*
         * OBSERVAÇÃO 3.
         */
        String entityName = e.getClass().getAnnotation(Table.class).name();
        if (entityName == null || entityName.isEmpty()) {
            entityName = e.getClass().getSimpleName();
        }

        logTrace.setTransactionType(transactionType);
        logTrace.setEntityName(entityName);
        logTrace.setRegistryId(e.getId());
        logTrace.setExecutedBy(user);
        logTrace.setOperationDate(new Date());

        logTraceService.save(logTrace);
    }
}


Observações:
1- O listener é disparado pelo mecanismo JPA. Uma vez que a classe não foi instanciada pelo Spring, as dependências não são injetadas e para resolver isso, podemos usar aspéctos (AOP) ou uma abordagem mais simples como a feita acima;
2- A lógica de recuperação do usuário logado (via consulta ou busca na sessão) está no serviço neste caso;
3- Alguns projetos adotam o uso da anotação @Table, neste listener, coloquei uma lógica que abrange esta abordagem (como principal) e se não for o caso, o campo receberá o nome da entidade, por exemplo, "PedidoInterno", ao invés de "pedido_interno" (que é a forma como os bancos normalmente são modelados. Veja que nossa "LogTrace" teria o campo salvo como "log_trace";

5- Anotar entidades que devem ser auditadas:
As entidades que devem ser auditadas recebem a anotação @EntityListeners(value = LogTraceListener.class). Para melhorar a leitura da classe, indico colocar esta anotação logo após a anotação @Entity ou @Table(name = "minha_entidade").

Com isso, sempre que uma das operações monitoradas pelo listener acontecer, são as anotações que estão sobre os métodos: @PostPersist, @PostUpdate e @PostRemove, um registro será gerado na tabela de log de auditoria.

Para que outra tabela/entidade seja autitada, basta repetir o passo 5 (incluir a anotação na entidade).

NOTA: Normalmente as entidades de um sistema extendem uma entidade base ou implementam uma interface para que um padrão "mínimo" seja seguido. Este exemplo foi construído considerando este caso, ou seja, as entidades extendem BaseEntity.

segunda-feira, 17 de setembro de 2012

App web Java + Maven não roda no ecplise

Imagine que você desenvolveu uma aplicação java com maven e versionou ela em algum repositório da vida, por exemplo, github, e ao instalá-la em outro computador ela apresenta a seguinte mensagem quando o servidor sobe:

Error configuring application listener of class org.springframework.web.context.ContextLoaderListener

Consultando este problema na internet achei a seguinte solução:
  1. Abre as propriedades do projeto (botão direito no projeto e propriedades); 
  2. Selecione "Deployment Assembly";
  3. Clique em "Add...";
  4. Selecione "Java Build Path Entries" e clique em "Next";
  5. Selecione "Maven Dependencies" e clique "Finish";
Reinicie seu servidor tomcat e veja que agora funciona.

Essas dicas foram retiradas do post 6210757 - java-lang-classnotfoundexception-org-springframework-web-context-contextloaderl no stackoverflow.com

quarta-feira, 18 de julho de 2012

JSF - Página de erro após sessão expirada?

Eu estava pegando sempre uma página de erro após muito tempo de inatividade em uma aplicação JSF ou quando reiniciava o servidor e clicava em algum link na página.

Para resolver esse problema chato, usei as seguintes linhas no web.xml da aplicação.

<error-page>
    <exception-type>
        javax.faces.application.ViewExpiredException
    </exception-type>
    <location>
        /index.html
    </location>
</error-page>


Com essas linhas no web.xml a aplicação ao invés de exibir a página de erro quando a view estiver expirada, vai redirecionar o usuário para a página indicada.

JSF - URL não muda após redirect?

Em situações que um método retorna a url de redirect da sua página, como por exemplo:

public String listar() {
    return "/pages/list.xhtml";
}


E o JSF não muda a URL na barra do browser, recomendo a inclusão da seguinte string após a url:  + "?faces-redirect=true"

ficando:

public String listar() {
    return "/pages/list.xhtml"  + "?faces-redirect=true";
}


Fazendo isso, a URL sempre vai mudar. ;-)

domingo, 15 de abril de 2012

JSF 2.0 + Spring - Injeção de Dependência (DI)

Estou desenvolvendo uma aplicação utilizando JSF 2.0, Hibernate, Spring 3, etc...

No caso, procurei utilizar anotações e acabei cometendo um equívoco na escolha das anotações que a principio, não gerou problema, porém, quando testei multiplos acessos à aplicação, os problemas começaram a aparecer, como por exemplo, um usuário invalidando a sessão do outro.

O ponto é que eu estava usando a anotação @Component("nomeBean") nos beans gerenciados e @Autowired para fazer o trabalho de DI (anotações do Spring).

Pesquisando para resolver o problema, cheguei ao seguinte resultado:

- Ao invés de:
@Component("nomeBean")

- Use:
@ManagedBean(name="nomeBean")

- e ao invés de:
@Autowired

- Use:
@ManagedProperty(value="#{nomeBeanInjetar}")


Utilizarei como exemplo uma classe usuário recebendo a injeção de um UsuarioDAO.

- Implentação do UsuarioDAO que deverá ser injetado no objeto usuarioController, que é meu managed bean:

@Component("usuarioDAO")
public class UsuarioDAO implements IUsuarioDAO {
...

- Classe que receberá a injeção:

@ManagedBean(name="usuarioController")
@SessionScoped
public class UsuarioController {

@ManagedProperty(value="#{usuarioDAO}")
private IUsuarioDAO usuarioDao;

public void setUsuarioDAO(IUsuarioDAO usuarioDAO) {
this.usuarioDAO = usuarioDAO;
}
...


Note que na abordagem acima estou usando anotações do JSF (@ManagedBean e @ManagedProperty) e anotações do Spring.

A ideia é a seguinte:
- Criamos os objetos que serão reutilizados mais adiante sendo injetados em nossos managed beans, esses objetos devem ser marcados como componentes e nesse momento, devemos dar um nome a ele, nesse processo, o Spring vai criar este objeto em memória e deixá-lo pronto para ser injetado quando for chamado;
- O segundo passo é no nosso managed bean que devemos identificar a propriedade com a anotação @ManagedProperty e informar qual será o objeto que deverá ser injetado usando o mesmo nome dado anteriormente;

Bom, seguindo o padrão de posts rápidos e dirétos, basicamente foi isso que me ajudou bastante.

OBS.:
1. Quando utilizada a anotação @ManagedProperty, o atributo deve possuir um setter associado a ele, como no exemplo acima;

2. Quando ainda não tinha notado que o erro era este, procurei coisas estáticas na aplicação e por ai vai, então, fica a dica;

Espero ter ajudado e até a próxima.

sexta-feira, 30 de março de 2012

Alguns comandos úteis para utilizar MAVEN

Abaixo vou listar algumas linhas de comando que podem ajudar no desenvolvimento de aplicações que usam MAVEN:

- Criar uma aplicação:
$ mvn archetype:generate -DgroupId=br.com.meusistema -DartifactId=AppExemplo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false 

Na primeira vez que este processo é executado, as coisas demoram um pouco por que o maven vai baixar meia internet no repositório local que ele cria na máquina.

Terminado o processo, você verá que o maven criou uma pasta com o nome que foi utilizado no artifactId, no nosso exemplo, "AppExemplo"

Depois disso, para que este projeto possa ser aberto no eclipse fácil, fácil, o comando é:
$ cd AppExemplo
E dentro do diretório da aplicação:
$ mvn eclipse:clean 
$ mvn eclipse:eclipse 
ou
$ mvn eclipse:m2eclipse 

Na primeira vez deve demorar um pouco também.

Depois, basta importar o projeto no eclipse e seguir a vida.

Estou disponibilizando abaixo uma lista de comandos que normalmente uso.

$ mvn clean
$ mvn compile
$ mvn install

Pretendo em uma hora com calma editar este post e incluir mais detalhes sobre cada operação descrita e incluir mais algumas que costumo usar.

terça-feira, 28 de fevereiro de 2012

Assinando um JAR (JAVA WEB START)

Toda vez que criamos uma aplicação Java Web Start e precisamos que esta aplicação tenha alguns acessos a máquina cliente, é necessário incluir no arquivo JNLP a seguinte instrução:
<security>
  <all-permissions/>
</security>
O problema é que feito isso, é necessário assinar os jars que estão na lista que deve ser entregue a máquina cliente, abaixo criei um tutorial bem simples de como fazer isso.
- Primeiro – no diretório onde estão os jars, digite a linha de comando que segue:
keytool -genkey -alias macielbombonato -keystore macielbombonato.cert
- Escolha a senha (minimo de 6 caracteres):
Enter keystore password:
Re-enter new password:
- Responda o questionário:
What is your first and last name?
[Unknown]: XXX
What is the name of your organizational unit?
[Unknown]: XXX
What is the name of your organization?
[Unknown]: XXX
What is the name of your City or Locality?
[Unknown]: XXX
What is the name of your State or Province?
[Unknown]: XX
What is the two-letter country code for this unit?
[Unknown]: XX
Is CN=XXX, OU=XXX, O=XXX, L=XXX, ST=XX, C=XX correct?
[no]: yes
Esses passos acima vão criar um certificado na pasta onde os jars estão, agora é necessário assinar cada um dos jars com esse certificado, para isso, basta utilizar a linha de comando abaixo:
jarsigner -verbose -keystore macielbombonato.cert -storepass 123456 -keypass 123456 
MeuJarAssinadoWebStart.jar macielbombonato
Caso não queira incluir as senhas nas linhas de comando para assinar os jars, basta não utilizar os parâmetros -storepass e -keypass, com isso, a senha será solicitada antes do jar ser assinado.

Dúvidas/Sugestões, por favor, comente este post.