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

Factory com CDI

Neste artigo, a partir de um exemplo simples de fábrica (Factory) na linguagem Java, vou  mostrar como implementar esta mesma fábrica, porém para criar objetos gerenciados pelo container, usando CDI.

Como exemplo vou usar uma fábrica de formas que, dado um tipo de forma, retorna uma instância deste tipo.

Para este exemplo teremos duas formas, o retângulo e o círculo, listadas na enumeração ShapeType.

public enum ShapeType {
   RECTANGLE, CIRCLE
}

A classe abstrata Shape representa uma forma genérica. Shape possui uma dependência do tipo ShapeDependency, que deve ser passada como parâmetro para o seu construtor.

public abstract class Shape {

   private ShapeDependency dependency;

   public Shape(ShapeDependency dependency) {
      this.dependency = dependency;
   }

   public ShapeDependency getDependency() {
      return dependency;
   }
}

A classe ShapeDependency por sua vez, possui a propriedade name, a qual deve ser  passada como parâmetro para o seu construtor.

public class ShapeDependency {

   private String name;

   public ShapeDependency(String name) {
      this.name = name;
   }

   public String getName() {
      return name;
   }
}

As classes Rectangle e Circle são formas específicas, subclasses de Shape. Elas instanciam ShapeDependency nos seus construtores e passam esta instância para o construtor da superclasse Shape, já recebendo o name correto.

public class Rectangle extends Shape {

   public Rectangle() {
      super(new ShapeDependency("Rectangle dependency"));
   }
}

public class Circle extends Shape {

   public Circle() {
      super(new ShapeDependency("Circle dependency"));
   }
}

Por fim, a fábrica ShapeFactory possui o método create que retorna uma instância da classe Shape, de acordo com o ShapeType recebido por parâmetro.

public class ShapeFactory {

   public Shape create(ShapeType type) {
      if(RECTANGLE.equals(type)){
         return new Rectangle();
      }
      if(CIRCLE.equals(type)){
         return new Circle();
      }
      return null;
   }
}

Até aqui tudo tranquilo, nada diferente de uma fábrica comum. Mas e se a instância retornada pela fábrica possui uma dependência gerenciada pelo container?

Para ilustrar este caso, Shape terá a sua dependência injetada por CDI.

public abstract class Shape {

   @Inject
   private ShapeDependency dependency;

   public ShapeDependency getDependency() {
      return dependency;
   }
}

Rectangle e Circle teriam de configurar a dependência num método anotado com @PostConstruct, pois este será executado pelo container após a injeção da dependência, ao contrário do construtor, que é executado antes, o que ocasionaria NullPointerException.

public class Rectangle extends Shape {

   @PostConstruct
   public void setUp() {
      dependency.setName("Rectangle dependency");
   }
}

public class Circle extends Shape {

   @PostConstruct
   public void setUp() {
      dependency.setName("Circle dependency");
   }
}

ShapeDependency teria o valor da propriedade name configurado num setter, pois o container usa apenas o construtor vazio (sem parâmetros) para instanciar as classes que ele gerencia.

public class ShapeDependency {

   private String name;

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

   public String getName() {
      return name;
   }
}

Neste novo contexto, o problema é que o método create de ShapeFactory não pode mais criar a instância de Shape com um comando new, pois esta nova instância não terá sua dependência injetada, já que com este comando é você que está gerenciando o ciclo de vida da instância, não o container.

Você também não pode simplesmente injetar Shape na ShapeFactory, pois Shape é uma classe abstrata e o container não saberia qual subclasse injetar, Rectangle ou Circle.

E mesmo que o container injetasse uma delas arbitrariamente, ele o faria ao instanciar ShapeFactory, e nós só sabemos de qual subclasse de Shape queremos uma instância durante a execução do método create, a partir do parâmetro ShapeType recebido.

A solução é usar um recurso que o CDI nos proporciona, que permite avisar ao container que ele não deve injetar a dependência (Shape) ao instanciar ShapeFactory, que é a interface Instance<T>. Esta interface ainda nos permite, no momento apropriado, selecionar a subclasse desejada através do método select, e obter a instância desta classe através do método get.

public class ShapeFactory {

   @Any
   @Inject
   private Instance<Shape> shape;

   public Shape create(ShapeType type) {
      if(RECTANGLE.equals(type)){
         return shape.select(Rectangle.class).get();
      }
      if(CIRCLE.equals(type)){
         return shape.select(Circle.class).get();
      }
      return null;
   }
}

Desta forma temos uma fábrica com o mesmo comportamento da primeira, mas que é capaz de entregar instâncias gerenciadas pelo container.

PS: Note que para funcionar a própria fábrica deve ser gerenciada pelo container.

Java programmer positions for foreign students / visiting professors

The ELSA-Brasil project (Longitudinal Study of Adult Health - Brazil) is a
multi-center cohort study now completing its baseline visit of 15 000
employees of public universities and research centers of southern,
southeastern and northeastern Brazil: FIOCRUZ, UFBA, UFES, UFMG, UFRGS and
USP). Its objective is to investigate the development of chronic diseases,
especially cardiovascular problems and diabetes. Part of the project´s
activities has been and will continue to be the development of a web-based
data management system and an accompanying PACS for image transmission.

The data system is based on Java technology and has been developed in Porto
Alegre - RS - Brazil
by a team using agile methods (Scrum+XP) in a
distributed architecture.

ELSA-Brasil is offering short term positions within the context of academic
interchange for Java software developers with experience in
building enterprise web applications. This will include coding, unit
testing, using design patterns, learning new technologies, and having
a lot of fun doing it.

We are looking for individuals in an academic setting
- with a bachelor´s degree in computer science or a related field or
- pursuing an undergraduate degree in computer science or a related course

Required Skills:
- OO design
- Java (J2EE)
- Unit Testing (JUnit)
- Fluency in English or Portuguese
- Teamwork and communication skills

Desired Skills:
- EJB
- JSF
- Selenium

We can offer financial support to cover plane flight and living expenses in
Porto Alegre.

If interested please submit a letter summarizing your circumstances and
explaining your interest, accompanied by your CV, in English or Portuguese,
to Emerson Hernandez in the address below.

Treinamento Java

Dos dias 12 a 27 de julho, dois membros da equipe tiveram a oportunidade de passar adiante um pedaço do conhecimento adquirido no desenvolvimento do sistema ELSA, ministrando um curso para a CR Sistemas e Web, de Taquara. O pessoal presente ao curso era composta de analistas, programadores e testadores, assim como pessoal de suporte. Os assuntos abordados incluiram tópicos desde as bases de Orientação a Objetos até JEE usando tecnologias como JBoss Seam.



Atividades de apresentações internas já foram usadas algumas vezes na equipe de desenvolvimento. Essa, porém, foi a primeira vez que a colocamos em um ambiente externo. A experiência foi extremamente gratificante e agora estamos na espera dos resultados práticos deste treinamento no dia-a-dia da equipe da CR.