Spring Rest + AngularJS

56 views
Skip to first unread message

Evandro Cavichioli

unread,
Aug 13, 2014, 11:22:16 AM8/13/14
to redfo...@googlegroups.com
Olá pessoal,

Estou com um problema e não estou conseguindo achar solução... Talvez vocês possam me ajudar.

Estou criando uma aplicação usando Spring Rest + AngularJS. 
Estou tendo um problema que acredito ser de configuração do hibernate.

O caso é que tenho uma pagina que lista produtos cadastrados, ao realizar um novo cadastro de produto e a tela retornar para a minha lista de produtos, o produto que acabei de cadastrar ainda não consta na lista, ao fazer qualquer evento na tela esse produto aparece na lista. Tenho notado que as vezes se o rest demora um pouco pra responder o GET da lista então esse novo produto que acabou de ser cadastro já vem corretamente na lista.

OBS: quando eu cadastro ou excluo um produto ao retornar para lista o angular busca novamente a lista de produtos no banco de dados. Acredito então que não seja problema do angularJS.

Será que tem alguma coisa haver com configuração do hibernate? acredito que o tempo que leva para o hibernate persistir os dados no banco possa ser o problema.

Minhas configurações:
- hibernate 3.6.10.Final
- querydsl 2.9.0

@Configuration
@EnableJpaRepositories(basePackageClasses = {  ...  })
@EnableTransactionManagement(proxyTargetClass = true, mode = AdviceMode.ASPECTJ)
@ImportResource("classpath*:META-INF/spring/applicationContext-data.xml")
public class RepositoryConfig {

@Autowired
private EntityManagerFactory entityManagerFactory;

@Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory);
}

}


- applicationContext-data.xml
 contem apenas configuração: <aop:aspectj-autoproxy/>

Gabriel Such

unread,
Aug 13, 2014, 1:09:53 PM8/13/14
to redfo...@googlegroups.com
Fala Evandro, tudo bem?

Já tentou reproduzir esse cenário direto via API para ver se o problema também ocorre?
Tenta fazer um POST para seu cadastro seguido de um GET para validar sua listagem.
Sugiro fazer um teste automatizado para isso, assim fica claro se o problema está no backend ou no frontend.

Outra dica, apesar de não relacionada diretamente a seu problema:
você pode eliminar seu arquivo xml para a configuração aspectj-autoproxy, utilizando a anotação @EnableAspectJAutoProxy.

[]'s
Gabriel Such

--
Você recebeu essa mensagem porque está inscrito no grupo quot;Redfoot JUG" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para redfoot-jug...@googlegroups.com.
Para postar nesse grupo, envie um e-mail para redfo...@googlegroups.com.
Acesse esse grupo em http://groups.google.com/group/redfoot-jug.
Para ver essa discussão na Web, acesse https://groups.google.com/d/msgid/redfoot-jug/9d318991-ebd3-4223-94d6-c43b912fc3bf%40googlegroups.com.
Para mais opções, acesse https://groups.google.com/d/optout.

Evandro Cavichioli

unread,
Aug 13, 2014, 2:29:23 PM8/13/14
to redfo...@googlegroups.com
Olá Gabriel,

Obrigado pelas dicas, vou fazer esses testes. Quanto aos teste automatizados preciso dar uma estuda nisso rsrsrsrs.
Com relação a anotação valeu mesmo.

Abraço!

Mário Júnior

unread,
Aug 13, 2014, 2:50:49 PM8/13/14
to redfo...@googlegroups.com
Primeiro teste sua API:
- Manualmente com chrome, eu utilizo o Postman ... é um ótimo plugin

- Mas, não se esqueça de criar os testes unitários consumindo sua API (criar testes com mocks que instanciam os controller e invocam os métodos diretamente SEM invocar as URLs, imho, são inúteis. É importante que, além do comportamento do método, o mapeamento da URL do endpoint também seja acionado durante o teste):
Exemplo básico para te dar um starting up: http://spring.io/guides/tutorials/rest/4/


Faça o post para o endpoint que grava seu objeto e depois o GET, veja se o objeto está lá. Se estiver, daí o problema pode ser com seu front-end (cache de requisição?)


[]'s




Para mais opções, acesse https://groups.google.com/d/optout.



--
Mario Junior
@mariojunior

Evandro Cavichioli

unread,
Aug 14, 2014, 8:34:07 AM8/14/14
to redfo...@googlegroups.com, mrdesou...@gmail.com
Olá Mário, 

Cara obrigado mesmo, esta me ajudando muito essas dicas. Não consegui resolver o problema ainda mas estou no caminho.

Abraços!

Eduardo Rebola Danielli

unread,
Aug 14, 2014, 1:36:29 PM8/14/14
to redfo...@googlegroups.com
E não deixe de conferir o Spring Boot.

Abraço!

@eduardorebola


michel andrade

unread,
Aug 14, 2014, 2:59:54 PM8/14/14
to redfo...@googlegroups.com
Se vc realizar o teste que o Mario falou e apresentar o registro provavelmente o erro possa estar no seu front-end mesmo, posta o trecho de código do angular js

tu tens que fazer a rota para a lista ou executar o GET da listagem no success do request de gravação

$http
    .post() {
        
     })
     .success(function (data,status) {
   
// rota para a listagem ou GET da listagem

     });



Para mais opções, acesse https://groups.google.com/d/optout.



--
Atenciosamente,
Michel Andrade
(44) 9991-1568
(48) 9635 6943

Evandro Cavichioli

unread,
Aug 14, 2014, 3:08:38 PM8/14/14
to redfo...@googlegroups.com
Olá Michel...

segue a parte js que controla o cadastro e lista de produtos:

/* Controllers */
sdiControllers.controller('produtoCtrl', ['$rootScope', '$scope', '$routeParams', '$location', 'produtoService', 'alertService', 
function($rootScope, $scope, $routeParams, $location, produtoService, alertService) {
$scope.produtos = [];
$scope.listar = function(){
produtoService.listar()
.then(function( produtos ) {
$scope.produtos = produtos;
   });
};
$scope.deletar = function(produto) {
produtoService.deletar(produto)
.then($scope.listar(),alertService.add("success", "Excluído com sucesso"));
};
$scope.novo = function(){
$location.path('/produto/novo');
};
$scope.listar();
}
]);

/* Controllers */
sdiControllers.controller('novoProdutoCtrl', ['$rootScope', '$scope', '$routeParams', '$http', '$location', 'produtoService',
function($rootScope, $scope, $routeParams, $http, $location, produtoService) {
produtoService.novo()
.then(function( produto ) {
               $scope.produto = produto;
        });
$scope.salvar = function() {
produtoService.salvar($scope.produto)
.then(function( produtos ) {
console.log(JSON.stringify(produtos));
$scope.produtos = produtos;
$location.path('/produto').replace();
   });
};
$scope.cancelar = function() {
$location.path('/produto');
};
}
]);


/* Controllers */
sdiControllers.controller('editarProdutoCtrl', ['$rootScope', '$scope', '$routeParams', '$http', '$location', 'produtoService',
function($rootScope, $scope, $routeParams, $http, $location, produtoService) {
produtoService.buscar($routeParams.id)
.then(function( produto ) {
              $scope.produto = produto;
        });
$scope.salvar = function() {
produtoService.salvar($scope.produto).
then($location.path('/produto'));
};
$scope.cancelar = function() {
$location.path('/produto');
};
}
]);


sdiApp.service('produtoService', [ '$http', '$q', 'cfpLoadingBar', function( $http, $q , cfpLoadingBar) {
var requestMapping = "produto/";
this.salvar = function(produto) {
var request = $http.post(requestMapping , JSON.stringify(produto) );
return request.then( handleSuccess, handleError );
};
this.listar = function() {
cfpLoadingBar.start();
var request = $http.get(requestMapping + 'lista', {cache:false});
var lista = request.then( handleSuccess, handleError ) ;
cfpLoadingBar.complete();
return lista;
};
    this.buscar = function(idProduto){
    var request = $http.get(requestMapping + idProduto);
return( request.then( handleSuccess, handleError ) );
    };
   
    this.novo = function(){
    var request = $http.get(requestMapping + 'novo');
return( request.then( handleSuccess, handleError ) );
    };
    
    this.deletar = function(produto) {
    var request = $http.delete(requestMapping + produto.id);
    return( request.then( handleSuccess, handleError ) );
    };

    function handleError(response, $q) {
if (!angular.isObject(response.data) || !response.data.message) {
return ($q.reject("Ocorreu um erro!"));
}
return ($q.reject(response.data.message));
    };

    function handleSuccess(response) {
return (response.data);
    };
}]);



Carlos Chiconato

unread,
Aug 14, 2014, 3:25:46 PM8/14/14
to redfo...@googlegroups.com
Você viu se dá algum erro no console do browser?

Aqui você trata o método listar como se ele retornasse uma promise, pelo que entendi do seu código ele retorna um object javascript.

$scope.listar = function(){
produtoService.listar()
.then(function( produtos ) {
$scope.produtos = produtos;
    });
};

Qual o código html usado para exibir os produtos?

Vlw,
Chiconato.


michel andrade

unread,
Aug 14, 2014, 3:40:31 PM8/14/14
to redfo...@googlegroups.com
Evandro,

O problema parece ser o scope do controllers, quando vc navega da listagem para o cadastro vc tem controllers diferentes e na sua function de salvar vc atualiza a lista de produtos 
$scope.salvar = function() {
produtoService.salvar($scope.produto)
.then(function( produtos ) {
console.log(JSON.stringify(produtos));
$scope.produtos = produtos;
$location.path('/produto').replace();
    });
};

mas essa lista produtos está no scope do controller da listagem, e quando vc seta essa lista vc esta setando o controller de novo produto (novoProdutoCtrl) e nao da listagem (produtoCtrl).
o scope do controller é "zerado" qdo vc troca de controllers no angular js ... é diferente do $rootScope que vc tem ele na "sessão" da app

por isso é comum se fazer 2 requisições POST e o GET na listagem

tente alterar esse trecho, tirando da function a listagem e executando na chamado do controller ,  pois ao chamar o controller de listagem ja vai fazer a requisição e atualizar os produtos.

DE
$scope.listar = function(){
produtoService.listar()
.then(function( produtos ) {
$scope.produtos = produtos;
    });
};

PARA
produtoService.listar()
.then(function( produtos ) {
$scope.produtos = produtos;
});


Para mais opções, acesse https://groups.google.com/d/optout.

Evandro Cavichioli

unread,
Aug 14, 2014, 4:43:41 PM8/14/14
to redfo...@googlegroups.com
E ai Michel,

desconsidera esse salvar que eu tinha feito... era apenas uns testes que eu tentei fazer... mas já não esta mais assim.

Vou adotar sua dica sobre o controller que lista.

quanto ao html que lista os produtos é esse:

<div class="row">
  <div class="col-xs-12 col-md-8">
  <h1 class="page-header">Produtos</h1>
  </div>
  <div class="col-xs-6 col-md-4">
  <button class="btn btn-success" ng-click="novo()">Novo</button>
  </div>
</div>

<div>
<table class="table">
<tr>
<th>ID</th>
<th>Identificação</th>
<th>Nome</th>
<th>Cadastro</th>
<th>Ação</th>
</tr>
<tr ng-repeat="produto in produtos">
<td><a href ng-href="#produto/{{produto.id}}">{{produto.numeroSequencial}}</a></td>
<td>{{produto.identificacao}}</td>
<td>{{produto.nome}}</td>
<td>{{produto.cadastro | date:'dd/MM/yy'}}</td>
<td><a href="javascript:return void(0);" ng-click="deletar(produto)">Excluir</a></td>
</tr>
</table>
</div>
Reply all
Reply to author
Forward
0 new messages