Arquivo da tag: Spring

Injeção de Dependência: comparação de desempenho

No presente post procurar-se-á demonstrar uma comparação entre injeção de dependência de dois grandes Frameworks, o JSF e o Spring. Para efeito de comparação também foi testada uma versão do aplicativo web com JSF sem o uso de injeção de dependência.

No desenvolvimento Web, diferentemente do desenvolvimento de aplicativos para Desktop, os sistemas muitas vezes possuem dezenas de milhares de usuários simultaneamente, isso exige um grande desempenho das aplicações.

Sendo assim a verificação do desempenho de diferentes formas de implementações, utilizando JSF com e sem injeção de dependência, que é uma forma de IoC (Inversion of Control – Inversão de Controle), e Spring, é importante e aponta para possibilidades mais adequadas, considerando as diferenças de desempenho entre os frameworks citados.

Os sistemas serão submetidos a testes de stress e desempenho. Para realização desses testes foi utilizado a ferramenta JMeter, uma ferramenta que diante das crescentes necessidades por performance vem sendo muito utilizada. Apache JMeter pode ser usado para testar o desempenho tanto em recursos estáticos quanto dinâmicos (arquivos, Servlets, scripts Perl, Java Objects, Bases de Dados, Consultas SQL, servidores FTP e muito mais).

Para o presente trabalho foram realizados dois testes para cada sistema desenvolvido, primeiro com 1000 usuários e o segundo com 4000 usuários. Esses dois testes foram realizados da mesma maneira com os três sistemas desenvolvidos (Spring com IoC, JSF com e sem IoC). Foram realizados testes com o máximo de 4000 mil usuários pois, o sistema após esse número apresentava a exceção “java.lang.OutOfMemoryError: Java heap apace” tornando impossível a realização de testes com maior número de usuários.

Como pode ser visto logo abaixo, o JMeter permite entre outras características as seguintes:

Tempo da amostra – tempo de resposta da aplicação;

Desvio – dispersão dos valores em relação à média;

Porcentagem de erro – porcentagem de problemas nas respostas;

Vazão – o número de operações que o sistema é capaz de completar em um dado período de tempo;

Carga Máxima do servidor – uso do processador pelo servidor;

Memória Máxima do servidor – uso de memória pelo servidor.

Tabela 1: Comparativo de desempenho com 1000 threads

Item Spring JSF com IoC JSF sem IoC
Tempo da amostra 75ms 74ms 39ms
Desvio 49ms 40ms 19ms
% de erro 0 % 0% 0%
Vazão 19,8/seg 19,8/seg 19,8/seg
Carga Máx. servidor ~37% ~60% ~50%
Memória Máx. servidor ~75% ~100% ~98%

 

Tabela 2: Comparativo de desempenho com 4000 threads

Item Spring JSF com IoC JSF sem IoC
Tempo da amostra 41ms 39ms 39ms
Desvio 89ms 25ms 18ms
% de erro 0%  0% 0%
Vazão 18,1/seg 19,6/seg 19,8/seg
Carga Máx. servidor ~48% ~35% ~48%
Memória Máx. servidor 95% ~80% ~90%

Através dos dados obtidos com os testes é possível identificar onde cada abordagem de desenvolvimento obteve um melhor desempenho com respeito à performance. Na tabela 1 e 2, foram agrupados os principais quesitos com respeito ao desempenho da aplicação para que pudéssemos analisar de forma mais clara.
Tempo da Amostra – Com relação a tempo, que seria o tempo de resposta da aplicação, na tabela acima temos a média de cada um. Observamos que o JSF sem Injeção de Dependência obteve resultados um pouco melhores, sendo em média mais rápido.
A porcentagem de erro ou problemas ao acessar a aplicação foi de zero por cento em todas as abordagens apresentadas.
A Vazão não foi muito diferente entre um e outro ficando novamente o JSF sem IoC um pouco à frente dos demais, mas apenas no teste com 4000 usuários, sendo praticamente insignificante a diferença haja vista que a própria rede pode apresentar oscilações na transferência de dados.
Agora com relação ao servidor de aplicações Tomcat, a carga do sistema obteve resultados na faixa de 35% a 60%, entretanto, não somos capazes de inferir nada com relação, pois em todos os testes houve oscilações durante o intervalo observado, sendo, que o Spring conseguiu se manter mais estável. Com relação ao uso da memória também não houve muita diferença.
Os testes foram realizados com o grupo máximo de 4000 usuários devido a estouro de memória no sistema quando utilizado por um grupo maior de usuários, apresentando a seguinte exceção: “java.lang.OutOfMemoryError: Java heap apace”. Com o número de usuários máximo utilizado nos testes, embora tenha havido algumas diferenças nos resultados, os sistemas se comportaram bem, não gerando gargalos nem indisponibilidade. Podemos perceber diante disso que com a melhora cada vez maior das técnicas de desenvolvimento de Frameworks e linguagens de programação o nível de qualidade se mantém quase igual, claro havendo algumas metodologias e facilidades diferenciadas em cada um.

CONCLUSÃO

Com todas as metodologias e técnicas utilizadas atualmente no desenvolvimento de ferramentas para auxílio dos programadores de sistemas, e até mesmo a maior especialização e estudo por parte das pessoas envolvidas nesse processo de desenvolvimento, tornou-se possível, excluindo algumas especificidades, que os níveis dessas ferramentas, como já dito anteriormente, quanto a desempenho se tornem muito parecidas, não havendo uma diferença muito grande.

O presente trabalho mostrou exatamente que as funcionalidades básicas, como é o caso da injeção de dependência, já estão bem consolidadas na maior parte dos Frameworks, logo, salvo funcionalidade muito específica, que seja provida por apenas um Framework, qualquer um dos Frameworks demonstrados aqui seria muito importante para um sistema em desenvolvimento e não haveria grandes problemas por adotar um ou outro, notando apenas que a injeção de dependência é um padrão de projeto e como tal já foi provado por anos de experiência em desenvolvimento de software, que é a forma mais indicada para desenvolvimento de sistemas complexos por facilitar muito o trabalho, tendo sido utilizada uma versão sem injeção de dependência no trabalho apenas por questões comparativas (mesmo que fosse muito mais eficiente não seria indicada por muitos outros fatores).

 

Spring IDE no Eclipse

Nesse Post mostrarei duas formas de ter o plugin Spring IDE no Eclipse:

Primeira forma é baixando a IDE já com suporte nativo:

SpringSource Tool Suite (STS) é uma IDE baseada no Eclipse com plugins pré-instalados que fornece recursos valiosos para os desenvolvedores Spring. Além do suporte para o framework Spring core, STS também oferece editores visuais, validadores, Painel do Spring para outros projetos como Spring ROO, Grails, Groovy, Gradle, tcServer, e Insight Spring.

O plugin principal para STS é Spring IDE, que fornece as características fundamentais de ferramentas Spring.  STS  vem pré-configurado com muitos outros plugins, como M2Eclipse  para  Maven,  Web Tools Platform (WTP), Data Tools Platform (DTP), AspectJ  Development Tools (AJDT) e ferramentas JUnit. Já vem incluso também a edição de desenvolvedor do vFabric tc Server, o substituto para o Apache Tomcat, que vem otimizada para Spring.
STS está disponível a partir do site SpringSource:
http://www.springsource.com/developer/sts

Após o download é só proceder à instalação:

Mac OS:

É preciso montar a imagem de disco, clicando duas vezes sobre o arquivo dmg baixado. Abra o volume chamado ‘SpringSource’ e ​​dê um duplo clique no instalador para iniciar a instalação. Siga as instruções na tela para concluir a instalação.

Windows:

Dê um duplo clique no instalador para iniciar o processo de instalação. Siga as instruções na tela para concluir a instalação.
Se você baixou o arquivo ZIP, não use o utilitário de extração que vem com o Windows isso está causando problemas durante a extração. Em vez disso,use o utilitário livre 7-Zip, recomendado no próprio site.

Linux:

Uma vez baixado, iniciar a instalação, executando o seguinte comando em um terminal:

sh nomeDoArquivoBaixado.sh

Maiores informações referentes à instalação podem ser encontradas no próprio site.

Segunda forma, baixando o plugin Eclipse IDE:

O plugin prove facilidades para o uso de Spring. Possui auto complete para os xmls de configuração do Spring, módulo visual para o Spring Web Flow, navegação entre os beans do Spring, e visualização de recursos AOP.

Instalação:

No Eclipse, clique em “Help –> Install New Software…”para abrir a caixa de diálogo de instalação do plugin.

No segundo passo clique no botão Add. da imagem acima, na tela que abrirá digite “Spring IDE” sem as aspas no campo name, e “http://springide.org/updatesite” no campo Location e clique em OK.

 

Aguarde o Eclipse buscar os softwares, depois selecione apenas os campos acima e clique em Next, após isso basta aceitar os termos e aguardar pelo fim da instalação.

Para gerenciar os sites dos plugins clique em Help -> Install New Software …  Clicando no link “Available Software Sites” você vai ver os sites dos plugins configurados no momento.

Fonte: http://www.springsource.com/developer/sts

Disponibilizando ViewScope para Spring

spring e jsf

Quem trabalha com JSF sabe que existem escopos para seus Managed Beans, e que eles devem ser bem definidos conforme o papel de cada Managed Bean na aplicação. Esse tal de “escopo” define o tempo de vida desse objeto(o Managed Bean) dentro da aplicação.

A partir do JSF 2.0 foi implementado um novo tipo de escopo, chamado de ViewScope. Este novo escopo veio para suprir a necessidade de se ter um tempo de vida dos Managed Beans um pouco maior do que o Request e menor que o Session. O uso do ViewScope é muito recomendado pois evita que um ManagedBean fique instanciado durante a sessão inteira do usuário(caso do SessionScope) mesmo que não esteja mais sendo usado, e possibilita guardar dados enquanto o usuário não troca de página(UIViewRoot), mesmo utilizando requisições ajax(o que não é possível com o RequestScope).

Grande parte das aplicações possuem frameworks, como o Spring, para gerenciar seus Beans. Logicamente, devem ser utilizadas as configurações do framework para o gerenciamento dos mesmos. No caso do Spring, (ainda) não existe um escopo com a mesma lógica do ViewScope do JSF, mas como todo bom framework, pode-se customizar um tipo de escopo e fazer uso dele normalmente na aplicação. É claro que para isso é necessário implementá-lo.

Na empresa onde trabalho utilizamos Spring e tivemos a necessidade de modificar alguns escopos de Session para View. Encontramos um post(em inglês) que fala sobre isso e exemplifica como implementar e disponibilizar um “ViewScope” para o Spring.

Segue aí os passos para implementar seu ViewScope para o Spring.

1. Implementar a classe responsável pelo gerenciamento dos Beans:

import java.util.Map;

import javax.faces.context.FacesContext;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.web.context.request.FacesRequestAttributes;

public class ViewScope implements Scope {

	public static final String VIEW_SCOPE_CALLBACKS = "viewScope.callbacks";

	public synchronized Object get(String name, ObjectFactory<?> objectFactory) {
		Object instance = getViewMap().get(name);
		if (instance == null) {
			instance = objectFactory.getObject();
			getViewMap().put(name, instance);
		}
		return instance;
	}

	public Object remove(String name) {
		Object instance = getViewMap().remove(name);
		if (instance != null) {
			Map<String, Runnable> callbacks = (Map<String, Runnable>) getViewMap().get(VIEW_SCOPE_CALLBACKS);
			if (callbacks != null) {
				callbacks.remove(name);
			}
		}
		return instance;
	}

	public void registerDestructionCallback(String name, Runnable runnable) {
		Map<String, Runnable> callbacks = (Map<String, Runnable>) getViewMap().get(VIEW_SCOPE_CALLBACKS);
		if (callbacks != null) {
			callbacks.put(name, runnable);
		}
	}

	public Object resolveContextualObject(String name) {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		FacesRequestAttributes facesRequestAttributes = new FacesRequestAttributes(facesContext);
		return facesRequestAttributes.resolveReference(name);
	}

	public String getConversationId() {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		FacesRequestAttributes facesRequestAttributes = new FacesRequestAttributes(facesContext);
		return facesRequestAttributes.getSessionId() + "-" + facesContext.getViewRoot().getViewId();
	}

	private Map<String, Object> getViewMap() {
		return FacesContext.getCurrentInstance().getViewRoot().getViewMap();
	}
}

2. Para poder “destruir” o Bean é necessário colocá-lo em algum local em que seja possível recuperá-lo posteriormente. A classe acima implementa o método registerDestructionCallback, responsável por registrar uma chamada de destruição ao Bean. Essa chamada será armazenada no viewMap da ViewRoot(nossa página que será mostrada), dentro de um Map para que possamos acessá-lo através de uma chave que será o nome do Bean. Graças ao mecanismo de Listeners, conseguimos inserir um novo objeto(no nosso caso um novo Map) dentro do viewMap da página.

Com a implementação da classe abaixo estaremos tratando de dois eventos simultaneamente: assim que o viewMap é construído(na inicialização da página ou PostConstructViewMapEvent) inserimos nosso “repositório” de Beans com ViewScope e seus respectivos destrutores, que será utilizado pelo método registerDestructionCallback, e pouco antes dele ser destruído(PreDestroyViewMapEvent) resgatamos os Beans com ViewScope inseridos no nosso “repositório” criado anteriormente e chamamos seus destrutores.

import java.util.HashMap;
import java.util.Map;

import javax.faces.component.UIViewRoot;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.PostConstructViewMapEvent;
import javax.faces.event.PreDestroyViewMapEvent;
import javax.faces.event.SystemEvent;
import javax.faces.event.ViewMapListener;

public class ViewScopeCallbackRegistrer implements ViewMapListener {

	public void processEvent(SystemEvent event) throws AbortProcessingException {
		if (event instanceof PostConstructViewMapEvent) {
			PostConstructViewMapEvent viewMapEvent = (PostConstructViewMapEvent) event;
			UIViewRoot viewRoot = (UIViewRoot) viewMapEvent.getComponent();
			viewRoot.getViewMap().put(ViewScope.VIEW_SCOPE_CALLBACKS, new HashMap<String, Runnable>());
		} else if (event instanceof PreDestroyViewMapEvent) {
			PreDestroyViewMapEvent viewMapEvent = (PreDestroyViewMapEvent) event;
			UIViewRoot viewRoot = (UIViewRoot) viewMapEvent.getComponent();
			Map<String, Runnable> callbacks = (Map<String, Runnable>) viewRoot.getViewMap().get(ViewScope.VIEW_SCOPE_CALLBACKS);
			if (callbacks != null) {
				for (Runnable c : callbacks.values()) {
					c.run();
				}
				callbacks.clear();
			}
		}
	}

	public boolean isListenerForSource(Object source) {
		return source instanceof UIViewRoot;
	}
}

3. Disponibilizar a nossa classe ViewScope para o Spring, inserindo o código abaixo no seu applicationContext.xml:

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
    <property name="scopes">
        <map>
            <entry key="view">
                <bean class="seupackage.ViewScope"/>
            </entry>
        </map>
    </property>
</bean>

4. Registrar nossa classe ViewScopeCallbackRegistrer nos listeners do Faces, inserindo o código abaixo no faces-config.xml:

<system-event-listener>
    <system-event-listener-class>seuPackage.ViewScopeCallbackRegistrer</system-event-listener-class>
    <system-event-class>javax.faces.event.PostConstructViewMapEvent</system-event-class>
    <source-class>javax.faces.component.UIViewRoot</source-class>
</system-event-listener>

<system-event-listener>
    <system-event-listener-class>seuPackage.ViewScopeCallbackRegistrer</system-event-listener-class>
    <system-event-class>javax.faces.event.PreDestroyViewMapEvent</system-event-class>
    <source-class>javax.faces.component.UIViewRoot</source-class>
</system-event-listener>

Basta agora utilizar a anotação @Scope(“view”) sobre seus Managed Beans e eles passarão a ter o comportamento do @ViewScope, mas agora gerenciados pelo Spring.

Bons códigos!!!

Fonte: http://www.harezmi.com.tr/spring-view-scope-for-jsf-2-users/