Solucionado (ver solução)
Solucionado
(ver solução)
17
respostas

Dúvida em relação à dependências

Bom dia,

Eu tenho uma aplicação desktop pronta em Java Swing e Hibernate e gostaria de implementar alguns serviços REST sem mudar a estrutura do projeto para um WebApp, usando apenas Jersey e Grizzly. Eu simplesmente criei um pacote resources para os meus recursos JAX-RS. As entidades estão todas marcadas com @XmlRootElement.

No exemplo do curso eu deletei as pastas usadas em projeto web(webapp, web-inf, web.xml), importei as libs do projeto pelo Eclipse e deu certo...consegui testar os serviços sem web.xml, e etc...só que o projeto do curso não usa maven e já vem com todas as dependências "de mão beijada" e estou tendo dificuldades na escolha das dependências corretas...Quando eu acesso a url abaixo eu tenho erro 500...Eu queria gerar o xml usando jaxb...

http://localhost:8081/exemplo/categorias/1

Eu adicionei essas quatro dependências no meu pom.xml

    <dependency>
            <groupId>org.glassfish.grizzly</groupId>
            <artifactId>grizzly-http-server</artifactId>
            <version>2.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-grizzly2-http</artifactId>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
        </dependency>

Minha classe de servidor:

package com.exemplo;

import java.io.IOException;
import java.net.URI;

import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;

import com.floreantpos.model.dao.MenuCategoryDAO;
import com.floreantpos.util.DatabaseUtil;

public class GrizzlyServer {

    public static final String BASE_URI = "http://localhost:8081/exemplo/";

    public static HttpServer startServer() {

        final ResourceConfig rc = new ResourceConfig().packages("com.floreantpos");
        return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
    }

    public static void main(String[] args) throws IOException {

        final HttpServer server = startServer();
        System.out.println(String.format("Servidor Grizzly inicializado", BASE_URI));
        System.in.read();
        server.stop();
    }

}

Meu recurso:

package com.exemplo.resources;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.exemplo.model.MenuCategory;
import com.exemplo.model.dao.MenuCategoryDAO;

@Path("categorias")
public class MenuCategoryResource {

    @GET
    @Path("{id}")
    @Produces(MediaType.APPLICATION_XML)
    public MenuCategory busca(@PathParam("id") int id) {
        MenuCategoryDAO categoryDao = new MenuCategoryDAO().getInstance();
        return categoryDao.get(id);
    }

}

Entidade:

package com.exemplo.model;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

import org.apache.commons.lang.StringUtils;

@XmlRootElement(name = "menu-category")
@XmlAccessorType(XmlAccessType.FIELD)
public class MenuCategory extends BaseMenuCategory {
    private static final long serialVersionUID = 1L;


    public MenuCategory () {
    }
...
17 respostas

Olá, Fernando.

Qual é o stack trace do erro?

Olá Alexandre,

No console do eclipse não aparece nenhum erro, apenas no browser aparece :

Esta página não está funcionando localhost não consegue atender a esta solicitação no momento. HTTP ERROR 500

Seria legal você debugar, colocando alguns breakpoints pra descobrir qual é o ponto de falha!

Dá pra tentar habilitar o log do Grizzly também:

Logger l = Logger.getLogger("org.glassfish.grizzly.http.server.HttpHandler");
l.setLevel(Level.FINE);
l.setUseParentHandlers(false);
ConsoleHandler ch = new ConsoleHandler();
ch.setLevel(Level.ALL);
l.addHandler(ch);

Os imports são todos do pacote java.util.logging.*

Alexandre eu tive que mudar o nível do log para Level.ALL para ter alguma saída no console e obtive o seguinte log nesse link https://gist.github.com/fernandocorrea/5655e43e96a3cc7100eba04e76e29f23#file-saida-grizzly

Me parece que foi gerado pela linha abaixo mas eu não consigo identificar aonde eu errei

final ResourceConfig rc = new ResourceConfig().packages("com.exemplo");

Fernando,

pode ignorar esse erro de inicialização.

O que ocorre quando você faz um requisição?

Alexandre segue link do log gerado quando eu acesso http://localhost:8081/exemplo/categorias/1

https://pastebin.com/XbtqjsQ5

solução!

Veja que foi um erro no JAXB, na transformação de objetos para XML, por causa de um ciclo:

Caused by: javax.xml.bind.MarshalException
 - with linked exception:
[com.sun.istack.internal.SAXException2: Foi detectado um ciclo no gráfico do objeto. Isso causará XML profundo infinitamente: APPETIZERS -> FRENCH FRIES -> APPETIZERS]

APPETIZERS tem FRENCH FRIES que tem APPETIZERS

O lance é quebrar esse ciclo dos objetos!

Não entendi bem Alexandre...

No meu banco FRENCH FRIES é um APPETIZERS. FRENCH FRIES é uma linha na tabela menu_group, e essa tabela possui um campo category_id que é o id da categoria que no caso é o id do APPETIZER.

veja o link sobre como está o relacionamento das tabelas: https://imgur.com/a/R8bJb

Eu preciso mudar minha classe de entidade?

Como está o modelo dos objetos?

Vi um trecho classe MenuCategory, mas ela deve depender de MenuGroup.

Agora, a classe MenuGroup tem algum atributo do tipo MenuCategory?

package com.example.model;

import java.awt.Color;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

import org.apache.commons.lang.StringUtils;

import com.example.config.TerminalConfig;
import com.example.model.base.BaseMenuCategory;

@XmlRootElement(name = "menu-category")
@XmlAccessorType(XmlAccessType.FIELD)
public class MenuCategory extends BaseMenuCategory {
    private static final long serialVersionUID = 1L;

    public MenuCategory () {
        //super();
    }

    public MenuCategory (java.lang.Integer id) {
        super(id);
    }

    public MenuCategory (
        java.lang.Integer id,
        java.lang.String name) {
        super (id, name);
    }

    private Color buttonColor;
    private Color textColor;

    @Override
    public Integer getSortOrder() {
        return sortOrder == null ? 9999 : sortOrder;
    }

    @XmlTransient
    public Color getButtonColor() {
        if (buttonColor != null) {
            return buttonColor;
        }

        if (getButtonColorCode() == null || getButtonColorCode() == 0) {
            return null;
        }

        return buttonColor = new Color(getButtonColorCode());
    }

    public void setButtonColor(Color buttonColor) {
        this.buttonColor = buttonColor;
    }

    @XmlTransient
    public Color getTextColor() {
        if (textColor != null) {
            return textColor;
        }

        if (getTextColorCode() == null || getTextColorCode() == 0) {
            return null;
        }

        return textColor = new Color(getTextColorCode());
    }

    public void setTextColor(Color textColor) {
        this.textColor = textColor;
    }

    public String getDisplayName() {
        if (TerminalConfig.isUseTranslatedName() && StringUtils.isNotEmpty(getTranslatedName())) {
            return getTranslatedName();
        }

        return super.getName();
    }

    @Override
    public String toString() {
        return getDisplayName();
    }

    public String getUniqueId() {
        return ("menu_category_" + getName() + "_" + getId()).replaceAll("\\s+", "_"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
    }
}
package com.exemplo.model.base;

import java.io.Serializable;


public abstract class BaseMenuCategory  implements Comparable, Serializable {

    public static String REF = "MenuCategory";
    public static String PROP_NAME = "name";
    public static String PROP_TEXT_COLOR_CODE = "textColorCode";
    public static String PROP_BEVERAGE = "beverage";
    public static String PROP_VISIBLE = "visible";
    public static String PROP_SORT_ORDER = "sortOrder";
    public static String PROP_BUTTON_COLOR_CODE = "buttonColorCode";
    public static String PROP_ID = "id";
    public static String PROP_TRANSLATED_NAME = "translatedName";

    public BaseMenuCategory () {
        initialize();
    }

    public BaseMenuCategory (java.lang.Integer id) {
        this.setId(id);
        initialize();
    }

    public BaseMenuCategory (
        java.lang.Integer id,
        java.lang.String name) {

        this.setId(id);
        this.setName(name);
        initialize();
    }

    protected void initialize () {}

    private int hashCode = Integer.MIN_VALUE;

    private java.lang.Integer id;

    protected java.lang.String name;
    protected java.lang.String translatedName;
    protected java.lang.Boolean visible;
    protected java.lang.Boolean beverage;
    protected java.lang.Integer sortOrder;
    protected java.lang.Integer buttonColorCode;
    protected java.lang.Integer textColorCode;

    private java.util.List<com.exemplo.model.Discount> discounts;
    private java.util.List<com.exemplo.model.MenuGroup> menuGroups;

    public java.lang.Integer getId () {
        return id;
    }


    public void setId (java.lang.Integer id) {
        this.id = id;
        this.hashCode = Integer.MIN_VALUE;
    }

    public java.lang.String getName () {
        return name;
    }

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

    public java.lang.String getTranslatedName () {
        return translatedName;
    }

    public void setTranslatedName (java.lang.String translatedName) {
        this.translatedName = translatedName;
    }

    public java.lang.Boolean isVisible () {
        return visible == null ? Boolean.FALSE : visible;
    }

    public void setVisible (java.lang.Boolean visible) {
        this.visible = visible;
    }

    public java.lang.Boolean isBeverage () {
        return beverage == null ? Boolean.FALSE : beverage;
    }

    public void setBeverage (java.lang.Boolean beverage) {
        this.beverage = beverage;
    }

    public java.lang.Integer getSortOrder () {
        return sortOrder == null ? Integer.valueOf(0) : sortOrder;
    }

    public void setSortOrder (java.lang.Integer sortOrder) {
        this.sortOrder = sortOrder;
    }

    public java.lang.Integer getButtonColorCode () {
        return buttonColorCode == null ? Integer.valueOf(0) : buttonColorCode;
    }

    public void setButtonColorCode (java.lang.Integer buttonColorCode) {
        this.buttonColorCode = buttonColorCode;
    }


    public java.lang.Integer getTextColorCode () {
        return textColorCode == null ? Integer.valueOf(0) : textColorCode;
    }

    public void setTextColorCode (java.lang.Integer textColorCode) {
        this.textColorCode = textColorCode;
    }

    public java.util.List<com.exemplo.model.Discount> getDiscounts () {
        return discounts;
    }

    public void setDiscounts (java.util.List<com.exemplo.model.Discount> discounts) {
        this.discounts = discounts;
    }

    public void addTodiscounts (com.exemplo.model.Discount discount) {
        if (null == getDiscounts()) setDiscounts(new java.util.ArrayList<com.exemplo.model.Discount>());
        getDiscounts().add(discount);
    }

    public java.util.List<com.exemplo.model.MenuGroup> getMenuGroups () {
        return menuGroups;
    }

    public void setMenuGroups (java.util.List<com.exemplo.model.MenuGroup> menuGroups) {
        this.menuGroups = menuGroups;
    }

    public void addTomenuGroups (com.exemplo.model.MenuGroup menuGroup) {
        if (null == getMenuGroups()) setMenuGroups(new java.util.ArrayList<com.exemplo.model.MenuGroup>());
        getMenuGroups().add(menuGroup);
    }

    public boolean equals (Object obj) {
        if (null == obj) return false;
        if (!(obj instanceof com.exemplo.model.MenuCategory)) return false;
        else {
            com.exemplo.model.MenuCategory menuCategory = (com.exemplo.model.MenuCategory) obj;
            if (null == this.getId() || null == menuCategory.getId()) return false;
            else return (this.getId().equals(menuCategory.getId()));
        }
    }

    public int hashCode () {
        if (Integer.MIN_VALUE == this.hashCode) {
            if (null == this.getId()) return super.hashCode();
            else {
                String hashStr = this.getClass().getName() + ":" + this.getId().hashCode();
                this.hashCode = hashStr.hashCode();
            }
        }
        return this.hashCode;
    }

    public int compareTo (Object obj) {
        if (obj.hashCode() > hashCode()) return 1;
        else if (obj.hashCode() < hashCode()) return -1;
        else return 0;
    }

    public String toString () {
        return super.toString();
    }

}

Acredito que o problema esteja na lista de MenuGroups que a classe mãe da minha entidade possui:

private java.util.List<com.floreantpos.model.MenuGroup> menuGroups;

Você concorda Alexandre? Se eu retirar essa linha eu posso alterar algum outro fluxo do sistema....tem como configurar esse detalhe no jaxb?

Creio que é por aí mesmo!

Você pode omitir um objeto do XML com a anotação @XmlTransient.

Mas minha classe pai não é anotada com @XmlRootElement.... existe alguma peculiaridade no mapeamento de classes que herdam de outras no jaxb?

Boa pergunta, Fernando! Nunca enfrentei esse caso!

Ok Alexandre,

Eu testei em uma entidade simples sem relacionamentos e deu certo...como estou iniciando em JAX-RS e nunca havia trabalhado com JAXB acho que esse teste foi suficiente para saber o que "me aguarda".

Vou estudar melhor o mapeamento desses relacionamentos...Eu não queria alterar as entidades porque já estão prontas e funcionando... mas vou estudar e ver o que pode ser feito.

Obrigado pela ajuda

Bacana, Fernando!

Ninguém disse que ia ser fácil! hehe

Bons estudos e bom trabalho!