Demoiselle Framework's Blog

08/10/2010

Liberada a versão 1.0.0 do componente demoiselle-crud

Ontem, dia 07/10/2010, foi liberada a primeira versão do componente demoiselle-crud. Este componente contém uma série de abstrações de telas, da camada de visão, da camada de negócio e da camada de persistência, para quem pretende fazer crud. Juntamente com o componente, foi liberada a primeira versão estável da aplicação Simplify (aplicação do sample que tem o objetivo de demonstrar o uso do demoiselle-crud) e a versão 1.2.0 do archetype-webapp-sample. Esse arquetipo já se encontra disponível no catálogo de arquetipos do demoiselle e ele pode ser usado para se criar uma aplicação já com as configurações básicas necessárias para a utilização do demoiselle-crud. É importante lembrar que quem usar esse arquétipo, estará utilizando a versão 1.2.0 do framework demoiselle.

A documentação de referência do demoiselle-crud pode ser vista aqui.

Está disponível também um passo a passo, mostrando como criar uma aplicação utilizando o demoiselle-crud. Para visualizá-lo, clique aqui

17/09/2010

As novidades da JEE 6

Arquivado em: Demoiselle — Cleverson Sacramento @ 16:22
Tags: , , , , , , ,
As JEE (Java Enterprise Edition) nascem de JSR (Java Specification Request), bem como todas as outras funcionalidades oficiais do Java. As JSR são formadas por um grupo de experts (Expert Group), composto por pessoas e empresas, e organizadas pelo líderes da especificação (Specification Leads). Durante meses a equipe debate sobre as especificações, liberando rascunhos periodicamente para que a comunidade possa acompanhar e se manifestar à respeito das decisões.
A iniciativa que pode ser considerada a versão 1 chama-se, na realidade, JPE (Java Professional Edition), lançada pela Sun Microsystems em 1998. É preciso minerar bastante o Google para encontrar materiais consistentes sobre a JPE. Em 1999 foi lançada a versão 2, denominada J2EE 1.2. A versão 3 foi lançada em 2001. Conhecida como J2EE 1.3, esta especificação agregou, dentre outras, a especificação JAAS (Java Authentication and Authorization Service). Em 2003 surgiu a J2EE 1.4, a versão 4 da plataforma, englobando a especificação de Web Services em Java (e outras mais). Em 2006 foi lançada a versão 5, agora conhecida como JEE 5. Isso mesmo, não tem mais o “2″! A JEE 5 trouxe como principal novidade a especificação para tratamento de XML, o JAXB (Java Architecture for XML Binding), além do uso de Generics e Annotations introduzidos na JSE 5.
Cada nova versão da plataforma JEE incorporou diversas novas especificações. O modelo foi inchando… inchando… inchando. Na versão 6, a equipe deu um basta, fazendo uma limpeza em coisas antigas, tais como o JAX-RPC e o EJB 2. Para mais detalhes sobre este assunto, leia a seção EE.6.1.3 da especificação.
Das novidades da JEE 6, as seguintes são mais requisitadas em foruns pela internet. Para cada uma delas, está disponível um código de exemplo. O projeto está configurado com Maven 2:
Servlet 3.0
Implementação de Referência: GlassFish
Declaração via anotações: A novidade mais comentada desta especificação é o uso de anotações para declarar Servlets, Listeners e ServletContextListeners (dentro outros). Este novo recurso possibilita que fornecedores de frameworks, como kits JSF (PrimeFaces, RichFaces, ICEFaces, etc), já tragam as configurações anotadas nas classes compiladas no seu próprio arquivo JAR. O que você ganha com isso? Facilidade na configuração de ferramentas, e limpeza do seu web.xml.
Fragmentos web.xml: Agora é possível espalhar pedaços de web.xml pelo classpath de sua aplicação. Voltando ao exemplo dos fornecedores de kits JSF, agora o fornecedor poderá colocar fragmentos de web.xml dentro do seu JAR, deixando o web.xml da aplicação final muito mais limpo. Mas as vantagens são as mesmas da declaração via anotações? A resposta é: nem tudo que você pode fazer no web.xml é possível fazer via anotações.
Chamadas assíncronas: Agora sim, suporte nativo às chamadas assíncronas! Quem nunca enfrentou problemas com a falta deste recurso ao usar AJAX (Asynchronous Javascript And XML) em suas aplicações?
Servidor: JEE 6 AS (GlassFish 3, JBoss 6) ou simplesmente o Tomcat 7.
JSF 2.0
Implementação de Referência: Mojarra
Declaração via anotações: Esta é, sem dúvidas, a novidade mais esperada no JavaServer Faces (JSF) 2.0. Seguindo o exemplo do Servlet 3.0, agora é possível declarar os seus ManagedBeans através de anotações, proporcionando um faces-config.xml bem enxuto!
Facelets nativo: Quem nunca utilizou o Facelets? Muito gente já usou templates de tela sem nem saber que aquilo é Facelets, um recurso que não era nativo na versão anterior do JSF. O Facelets foi um projeto tão bem sucedido, e tão utilizado com aplicações JSF, que a nova especificação juntou tudo em uma coisa só. Agora sim, Facelets é um recurso nativo do JSF!
Outcome sem rodeios: Quem conhece a versão anterior sabe exatamente o que é isso: quando um botão invoca um método que retorna uma String, o valor de retorno (outcome) deve estar devidamente mapeado no faces-config.xml, identificando a página de destino. Agora, na versão 2, a coisa é bem mais direta: o retorno do método já é o endereço da página. Isso mesmo, não é mais preciso declarar os outcomes. Mas, se mesmo assim você quiser mapeá-los, pode também!
Tratamento de exceções: Agora é possível criar o seu próprio ExceptionHandler para tratar as falhas na aplicação (e convertê-las em mensagens, por exemplo) antes mesmo que a tela de erro apareça para o usuário.
EL Resolver melhorado: A especificação Expression Language (EL) 2.2 trouxe muitos benefícios para o JSF. Agora é possível passar parâmetros nas invocações de métodos. Antes cada kit usava um EL Resolver diferente, gerando conflito uns com os outros na maioria dos casos. Agora virou padrão.
Servidor: JEE 6 AS (GlassFish 3, JBoss 6) ou simplesmente o Tomcat 7.
JPA 2.0
Implementação de Referência: Eclipselink
Criteria Queries: Quem nunca sentiu falta do recurso Criteria do Hibernate? Quem nunca teve que abrir mão da especificação Java Persistence API (JPA) para amarrar o seu código ao Hibernate só por causa do Criteria? Agora não é mais preciso, o recurso Criteria Queries faz parte da JPA 2. É fácil de usar? Não, ainda pode melhorar.
Cache de segundo nível: Muita gente fala mal da JPA, argumentando sua baixa performance, servindo isso de justificativa para fazer as queries na mão. Muitos fornecedores oferecem o recurso de cache de segundo nível para resolver o problema. Agora isso faz parte da especificação também.
Servidor: Não se aplica, pois o exemplo está executando com JUnit.
Bean Validation 1.0
Implementação de Referência: Hibernate Validator
Validadores personalizados: Eu diria que aqui não há nenhuma novidade em relação ao conhecido Hibernate Validator. Na realidade a especificação foi baseada nele.
Agora é padrão: Como o recurso de validação agora é padrão, outras especificações (como JSF e JPA) estão nativamente integradas ao Bean Validation. O que você precisa fazer para configurar o JSF (ou JPA) para utilizar a Bean Validation? Nada! É tudo integrado mesmo, estilo plug-and-play.
Servidor: Não se aplica, pois o exemplo está executando com JUnit.
EJB 3.1
Implementação de Referência: GlassFish
EJB Lite: Muita gente usa EJB, mas saberiam me dizer o porquê? Pois é, muita gente não sabe responder isso. Outros dirão que usam por causa do controle de transação nativo. Outros dirão que é para distribuir componentes. A verdade é que pouquíssimos casos precisariam realmente dos recursos do EJB. Foi pensando nisso que a especificação Enteprise JavaBeans (EJB) 3.1 criou o EJB Lite: o EJB sem diversos penduricalhos. O EJB Lite oferece recursos como controle transacional nativo e outras coisas mais.
Interfaces opcionais: Como era trabalhoso criar interfaces remotas (e locais) para usar EJB. Agora isso é opcional, você só cria se realmente precisar delas.
Deploy em arquivos WAR: Na versão anterior, EJB só poderia existir em deployments no formato EAR. Agora você pode empacotar seus EJBs com sua aplicação WAR.
Servidor: JEE 6 AS (GlassFish 3, JBoss 6)
JAX-RS 1.1
Implementação de Referência: Jersey
Serviços Web de forma fácil: Quem já precisou criar um Web Service sabe que não é uma tarefa trivial. Quem precisou consumir Web Services sabe que não é tão simples. Existem diversas ferramentas que facilitam o trabalho, gerando o código-fonte de forma automática. Contudo, mesmo com a geração automática, é preciso manter dezenas de arquivos. A espeficicação Java API for RESTful Web Services (JAX-RS) 1.1 tem como objetivo padronizar a implementação de serviços REST, que já viraram moda!
Exemplo: Não fiz
Servidor: Não se aplica
CDI 1.0
Implementação de Referência: Weld
Injeção de dependência: A Context and Dependency Injection (CDI) é a antiga especificação Web Beans, mas com um novo nome. Os frameworks Spring e JBoss Seam motivaram a criação da especificação CDI. Agora é padrão, foi-se o tempo que cada um criava o seu. O Demoiselle está trabalhando na substituição do seu mecanismode injeção em prol da nova especificação, confira: http://sourceforge.net/apps/phpbb/demoiselle/viewtopic.php?f=35&t=63.
Contextos (ou escopos): Não se comenta sobre instância gerenciada sem falar do seu contexto. Imagine os famosos escopos da plataforma Web (aplicação, sessão, etc), agora imagine isso em aplicações Desktop. Como o CDI não foi concebido exclusivamente para Web, ele promove o conceito de escopos em aplicações em geral, de forma completamente independente de plataforma. Você pode também criar seu próprio escopo.
Fábricas: Fazer fábricas de objetos agora ficou muito fácil. Basta utilizar o recurso Producer para controlar a criação de sua instância associada ao contexto.
Interceptadores: Quem aqui já usou AspectJ? Tem gente que ama, tem gente que odeia. Então experimente o recurso Interceptor e me diga o que você achou. Ficou simples ou não?
Estereótipos: Com este recurso, você pode criar anotações para estereotipar suas classes. Os estereótipos podem conter informações de escopo, pontos de intercessão e muitos outros recursos que o CDI tem para oferecer.
Servidor: JEE 6 AS (GlassFish 3, JBoss 6)
Conclusão
A especificação JEE 6 trouxe uma série de novidades, muitas delas oriundas de soluções já consolidadas no mercado. O mais interessante é que as “sub-especificações” estão cada vez mais interligadas (porém desacopladas), reduzindo bastante o esforço para integração. Fica cada vez mais claro o foco na facilidade de uso, proporcionada pelas anotações, fragmentos de arquivos de configuração e simplificação da arquitetura. Talvez por todos estes pontos as especificação JEE estejam se tornando alvo dos curiosos, estudiosos e profissionais da área e, inclusive, do projeto Demoiselle.

Em novembro de 2009 foi lançada a versão final da JSR-316, mais conhecida como JEE 6 (http://jcp.org/en/jsr/detail?id=316).

As JEE (Java Enterprise Edition) nascem de JSR (Java Specification Request), bem como todas as outras funcionalidades oficiais do Java. As JSR são formadas por um grupo de experts (Expert Group), composto por pessoas e empresas, e organizadas pelo líderes da especificação (Specification Leads). Durante meses a equipe debate sobre as especificações, liberando rascunhos periodicamente para que a comunidade possa acompanhar e se manifestar à respeito das decisões.

A iniciativa que pode ser considerada a versão 1 chama-se, na realidade, JPE (Java Professional Edition), lançada pela Sun Microsystems em 1998. É preciso minerar bastante o Google para encontrar materiais consistentes sobre a JPE. Em 1999 foi lançada a versão 2, denominada J2EE 1.2. A versão 3 foi lançada em 2001. Conhecida como J2EE 1.3, esta especificação agregou, dentre outras, a especificação JAAS (Java Authentication and Authorization Service). Em 2003 surgiu a J2EE 1.4, a versão 4 da plataforma, englobando a especificação de Web Services em Java (e outras mais). Em 2006 foi lançada a versão 5, agora conhecida como JEE 5. Isso mesmo, não tem mais o “2″! A JEE 5 trouxe como principal novidade a especificação para tratamento de XML, o JAXB (Java Architecture for XML Binding), além do uso de Generics e Annotations introduzidos na JSE 5.

Cada nova versão da plataforma JEE incorporou diversas novas especificações. O modelo foi inchando… inchando… inchando. Na versão 6, a equipe deu um basta, fazendo uma limpeza em coisas antigas, tais como o JAX-RPC e o EJB 2. Para mais detalhes sobre este assunto, leia a seção EE.6.1.3 da especificação.

Das novidades da JEE 6, as seguintes são mais requisitadas em foruns pela internet. Para cada uma delas, está disponível um código de exemplo. O projeto está configurado com Maven 2:

Servlet 3.0

[JSR-315: http://jcp.org/en/jsr/detail?id=315%5D

Implementação de Referência: GlassFish

Declaração via anotações: A novidade mais comentada desta especificação é o uso de anotações para declarar Servlets, Listeners e ServletContextListeners (dentro outros). Este novo recurso possibilita que fornecedores de frameworks, como kits JSF (PrimeFaces, RichFaces, ICEFaces, etc), já tragam as configurações anotadas nas classes compiladas no seu próprio arquivo JAR. O que você ganha com isso? Facilidade na configuração de ferramentas, e limpeza do seu web.xml.

Fragmentos web.xml: Agora é possível espalhar pedaços de web.xml pelo classpath de sua aplicação. Voltando ao exemplo dos fornecedores de kits JSF, agora o fornecedor poderá colocar fragmentos de web.xml dentro do seu JAR, deixando o web.xml da aplicação final muito mais limpo. Mas as vantagens são as mesmas da declaração via anotações? A resposta é: nem tudo que você pode fazer no web.xml é possível fazer via anotações.

Chamadas assíncronas: Agora sim, suporte nativo às chamadas assíncronas! Quem nunca enfrentou problemas com a falta deste recurso ao usar AJAX (Asynchronous Javascript And XML) em suas aplicações?

Exemplo: http://zyc.googlecode.com/svn/lab/jee6/examples/servlet/math/

Servidor: JEE 6 AS (GlassFish 3, JBoss 6) ou simplesmente o Tomcat 7.

JSF 2.0

[JSR-314: http://jcp.org/en/jsr/detail?id=314%5D

Implementação de Referência: Mojarra

Declaração via anotações: Esta é, sem dúvidas, a novidade mais esperada no JavaServer Faces (JSF) 2.0. Seguindo o exemplo do Servlet 3.0, agora é possível declarar os seus ManagedBeans através de anotações, proporcionando um faces-config.xml bem enxuto!

Facelets nativo: Quem nunca utilizou o Facelets? Muito gente já usou templates de tela sem nem saber que aquilo é Facelets, um recurso que não era nativo na versão anterior do JSF. O Facelets foi um projeto tão bem sucedido, e tão utilizado com aplicações JSF, que a nova especificação juntou tudo em uma coisa só. Agora sim, Facelets é um recurso nativo do JSF!

Outcome sem rodeios: Quem conhece a versão anterior sabe exatamente o que é isso: quando um botão invoca um método que retorna uma String, o valor de retorno (outcome) deve estar devidamente mapeado no faces-config.xml, identificando a página de destino. Agora, na versão 2, a coisa é bem mais direta: o retorno do método já é o endereço da página. Isso mesmo, não é mais preciso declarar os outcomes. Mas, se mesmo assim você quiser mapeá-los, pode também!

Tratamento de exceções: Agora é possível criar o seu próprio ExceptionHandler para tratar as falhas na aplicação (e convertê-las em mensagens, por exemplo) antes mesmo que a tela de erro apareça para o usuário.

EL Resolver melhorado: A especificação Expression Language (EL) 2.2 trouxe muitos benefícios para o JSF. Agora é possível passar parâmetros nas invocações de métodos. Antes cada kit usava um EL Resolver diferente, gerando conflito uns com os outros na maioria dos casos. Agora virou padrão.

Exemplo: http://zyc.googlecode.com/svn/lab/jee6/examples/jsf/registering/

Servidor: JEE 6 AS (GlassFish 3, JBoss 6) ou simplesmente o Tomcat 7.

JPA 2.0

[JSR-317: http://jcp.org/en/jsr/detail?id=317%5D

Implementação de Referência: Eclipselink

Criteria Queries: Quem nunca sentiu falta do recurso Criteria do Hibernate? Quem nunca teve que abrir mão da especificação Java Persistence API (JPA) para amarrar o seu código ao Hibernate só por causa do Criteria? Agora não é mais preciso, o recurso Criteria Queries faz parte da JPA 2. É fácil de usar? Não, ainda pode melhorar.

Cache de segundo nível: Muita gente fala mal da JPA, argumentando sua baixa performance, servindo isso de justificativa para fazer as queries na mão. Muitos fornecedores oferecem o recurso de cache de segundo nível para resolver o problema. Agora isso faz parte da especificação também.

Exemplo: http://zyc.googlecode.com/svn/lab/jee6/examples/jpa/crud/

Servidor: Não se aplica, pois o exemplo está executando com JUnit.

Bean Validation 1.0

[JSR-303: http://jcp.org/en/jsr/detail?id=303%5D

Implementação de Referência: Hibernate Validator

Validadores personalizados: Eu diria que aqui não há nenhuma novidade em relação ao conhecido Hibernate Validator. Na realidade a especificação foi baseada nele.

Agora é padrão: Como o recurso de validação agora é padrão, outras especificações (como JSF e JPA) estão nativamente integradas ao Bean Validation. O que você precisa fazer para configurar o JSF (ou JPA) para utilizar a Bean Validation? Nada! É tudo integrado mesmo, estilo plug-and-play.

Exemplo: http://zyc.googlecode.com/svn/lab/jee6/examples/validation/credential/

Servidor: Não se aplica, pois o exemplo está executando com JUnit.

EJB 3.1

[JSR-318: http://jcp.org/en/jsr/detail?id=318%5D

Implementação de Referência: GlassFish

EJB Lite: Muita gente usa EJB, mas saberiam me dizer o porquê? Pois é, muita gente não sabe responder isso. Outros dirão que usam por causa do controle de transação nativo. Outros dirão que é para distribuir componentes. A verdade é que pouquíssimos casos precisariam realmente dos recursos do EJB. Foi pensando nisso que a especificação Enteprise JavaBeans (EJB) 3.1 criou o EJB Lite: o EJB sem diversos penduricalhos. O EJB Lite oferece recursos como controle transacional nativo e outras coisas mais.

Interfaces opcionais: Como era trabalhoso criar interfaces remotas (e locais) para usar EJB. Agora isso é opcional, você só cria se realmente precisar delas.

Deploy em arquivos WAR: Na versão anterior, EJB só poderia existir em deployments no formato EAR. Agora você pode empacotar seus EJBs com sua aplicação WAR.

Exemplo: http://zyc.googlecode.com/svn/lab/jee6/examples/ejb/concat/

Servidor: JEE 6 AS (GlassFish 3, JBoss 6)

JAX-RS 1.1

[JSR-311: http://jcp.org/en/jsr/detail?id=311%5D

Implementação de Referência: Jersey

Serviços Web de forma fácil: Quem já precisou criar um Web Service sabe que não é uma tarefa trivial. Quem precisou consumir Web Services sabe que não é tão simples. Existem diversas ferramentas que facilitam o trabalho, gerando o código-fonte de forma automática. Contudo, mesmo com a geração automática, é preciso manter dezenas de arquivos. A espeficicação Java API for RESTful Web Services (JAX-RS) 1.1 tem como objetivo padronizar a implementação de serviços REST, que já viraram moda!

Exemplo: Não fiz

Servidor: Não se aplica

CDI 1.0

[JSR-299: http://jcp.org/en/jsr/detail?id=299%5D

Implementação de Referência: Weld

Injeção de dependência: A Context and Dependency Injection (CDI) é a antiga especificação Web Beans, mas com um novo nome. Os frameworks Spring e JBoss Seam motivaram a criação da especificação CDI. Agora é padrão, foi-se o tempo que cada um criava o seu. O Demoiselle está trabalhando na substituição do seu mecanismode injeção em prol da nova especificação, confira: http://sourceforge.net/apps/phpbb/demoiselle/viewtopic.php?f=35&t=63.

Contextos (ou escopos): Não se comenta sobre instância gerenciada sem falar do seu contexto. Imagine os famosos escopos da plataforma Web (aplicação, sessão, etc), agora imagine isso em aplicações Desktop. Como o CDI não foi concebido exclusivamente para Web, ele promove o conceito de escopos em aplicações em geral, de forma completamente independente de plataforma. Você pode também criar seu próprio escopo.

Fábricas: Fazer fábricas de objetos agora ficou muito fácil. Basta utilizar o recurso Producer para controlar a criação de sua instância associada ao contexto.

Interceptadores: Quem aqui já usou AspectJ? Tem gente que ama, tem gente que odeia. Então experimente o recurso Interceptor e me diga o que você achou. Ficou simples ou não?

Estereótipos: Com este recurso, você pode criar anotações para estereotipar suas classes. Os estereótipos podem conter informações de escopo, pontos de intercessão e muitos outros recursos que o CDI tem para oferecer.

Exemplo: http://zyc.googlecode.com/svn/lab/jee6/examples/cdi/auditing/

Servidor: JEE 6 AS (GlassFish 3, JBoss 6)

CONCLUSÃO

A especificação JEE 6 trouxe uma série de novidades, muitas delas oriundas de soluções já consolidadas no mercado. O mais interessante é que as “sub-especificações” estão cada vez mais interligadas (porém desacopladas), reduzindo bastante o esforço para integração. Fica cada vez mais claro o foco na facilidade de uso, proporcionada pelas anotações, fragmentos de arquivos de configuração e simplificação da arquitetura. Talvez por todos estes pontos as especificação JEE estejam se tornando alvo dos curiosos, estudiosos e profissionais da área e, inclusive, do projeto Demoiselle.

25/09/2009

Injeção de dependência no framework demoiselle

Arquivado em: Demoiselle,IoC — Demoiselle @ 16:48
Tags: , , ,

O objetivo deste post é mostrar como utilizar o mecanismo de injeção de dependência no framework demoiselle.

Para manter o baixo acoplamento entre as camadas da aplicação é necessário implementar uma técnica que permita que uma camada apenas saiba sobre as funcionalidades disponibilizadas por outra camada, sem se preocupar em como a mesma foi implementada, garantido que seja possível modificar o comportamento(implementação) de uma camada sem que a camada cliente sofra alterações.

Esta técnica é chamada de Injeção de dependência e tem como responsabilidade instanciar as classes concretas para prover a comunicação entre as camadas.

No framework demoiselle está técnica é implementada a partir da anotação @Injection que deve ser colocada sobre as propriedades a serem injetadas.

public class AuctionMB extends AbstractManagedBean {

@Injection
private
IAuctionBC auctionBC;

Esta anotação indica ao framework que esta propriedade deverá ser instanciada automaticamente antes que a mesma seja utilizada. Uma vez que a classe( onde se encontra a propriedade) for instanciada o framework irá procurar todas as propriedades que estejam anotadas com @Injection e delegará a fábrica padrão que localize a classe concreta correspondente.

O modulo Web do framework implementa as fabricas padrão para cada camada injetando a classe concreta a partir do padrão seguinte:

A partir de:
org.demoiselle.sample.auction5.business.IAuctionBC

Para:
org.demoiselle.sample.auction5.business.implementation.AuctionBC

Carregamento tardio

A implementação padrão do módulo web garante que a classe concreta só será instanciada caso realmente vá ser utilizada. Para garantir isto ao invés de injetar diretamente a classe contreta, um proxy é injetado garantindo que apenas na primeira vez que a propriedade for utilizada a mesma será instanciada.

Flexibilidade

Algumas aplicações precisam de um comportamento customizado para a instanciação de seus objetos, então neste caso, é preciso que se utilize fabricas customizadas.

É possível indicar qual será a fábrica utilizada na classe ou até mesmo em todo o pacote. Para isso basta utilizar a anotação @Factory sobre a classe ou dentro da classe package-info.java.

@Factory(factory=EscolaDAOFactory.class)
public class FuncionarioBC implements IFuncionarioBC {

@Injection
IFuncionarioDAO
funcionarioDao;

Para criar uma fábrica customizada basta criar uma classe que implemente IFactory e implementar o método create com as características necessárias à aplicação.

Autor: Robson Ximenes

Tema: Rubric. Blog no WordPress.com.

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.

Junte-se a 462 outros seguidores

%d bloggers like this: