简体   繁体   中英

Rest JSON POST in a abstract class didn't marshall unmarshall generic argument error 400

Good morning all. I'm coding a project with rest. So when try pass my first controller to extract into a abstract class notice some diference. Well all post methods did not work. Since get methods work with path variable so nicely. I'm using spring for rest.

This is the call:

endpoint: http://localhost:8080
resource:/SpringRestCrud/client/merge
parameter:
Client Query Resource
Media type: application/json
post value:
{
         "@id": 1,
         "id": 1,
         "code": "code",
         "name": "nameb"
      }

This is the soapui raw for all post methods is the same and no exceptions in server log:

HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 968
Date: Fri, 02 Dec 2016 10:22:32 GMT
Connection: close

<html><head><title>Apache Tomcat/7.0.56 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 400 - </h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u></u></p><p><b>description</b> <u>The request sent by the client was syntactically incorrect.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/7.0.56</h3></body></html>

Well bellow is my controller, any guess or clue will be welcome, thanks for reading.

package com.beingjavaguys.controller;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.beingjavaguys.model.Model;
import com.beingjavaguys.model.Status;
import com.beingjavaguys.services.GenericServices;

@Controller
public abstract class AbstractRest<T extends Model,I extends GenericServices<T>> implements GenericRest<T>{
    @Autowired
    I services;
    static final Logger logger = Logger.getLogger(AbstractRest.class);
    public AbstractRest() {
        super();
        Type kind = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        this.setEntityClass((Class<T>) kind);
    }

    private Class<T> entityClass;
    @Override
    @RequestMapping(value = "/create", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE,
            MediaType.APPLICATION_FORM_URLENCODED_VALUE })
    public @ResponseBody Status<T> addEntity(@RequestBody T t) throws Exception {
        try {
            if (services.addEntity(t)) {
                return new Status<T>(1, "Entity added Successfully !",t);
            } else {
                return new Status<T>(0, "Entity not added Successfully !",t);
            }
        } catch (Exception e) {
            logger.error("Entity not added Successfully !", e);
            return new Status<T>(0, e.toString(),t);
        }
    }

    @Override
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
    public @ResponseBody Status<Boolean> deleteEntity(@PathVariable("id") long id) throws Exception {
        try {
            if (services.deleteEntity(id)) {
                return new Status<Boolean>(1, "Entity deleted Successfully !",true);
            } else {
                return new Status<Boolean>(0, "Entity not deleted Successfully !",false);
            }
        } catch (Exception e) {
            logger.error("Entity not deleted Successfully !", e);
            return new Status<Boolean>(0, e.toString(),false);
        }
    }

    @Override
    @RequestMapping(value = "/merge", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody Status<T> mergeEntity(@RequestBody T t) throws Exception {
        try {
            if (services.mergeEntity(t)) {
                return new Status<T>(1, "Entity merged Successfully !",t);
            } else {
                return new Status<T>(0, "Entity not merged Successfully !",t);
            }
        } catch (Exception e) {
            logger.error("Entity not merged Successfully !", e);
            return new Status<T>(0, e.toString(),t);
        }
    }

    @Override
    @RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
    public @ResponseBody Status<T> getEntity(@PathVariable("id") long id) throws Exception {
        T entity = entityClass.newInstance();
        try {
            entity = services.getEntity(id);
            if(entity!=null)
                if(entity.getId()==0)
                    return new Status<T>(1, "Entity not found!",null);
                else
                    return new Status<T>(1, "Entity returned Successfully !",entity);
            else
                return new Status<T>(0, "Entity not returned Successfully !",entity);
        } catch (Exception e) {
            logger.error("Entity not returned Successfully !", e);
            return new Status<T>(0, e.toString(),entity);
        }

    }


    @Override
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public @ResponseBody Status<List<T>> getEntityList() throws Exception {
        List<T> entityList = new ArrayList<T>();
        try {
            entityList = services.getEntityList();
            if(entityList!=null)
                return new Status<List<T>>(1, "Entities returned Successfully !",entityList);
            else
                return new Status<List<T>>(0, "Entities not returned Successfully !",entityList);
        } catch (Exception e) {
            logger.error("Entities not lited Successfully !", e);
            return new Status<List<T>>(0, e.toString(),entityList);
        }

    }

    @Override
    @RequestMapping(value = "/search", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody Status<List<T>> getEntityList(@RequestBody T t) throws Exception {
        List<T> entityList = new ArrayList<T>();
        try {
            entityList = services.getEntityList(t);
            if(entityList!=null)
                return new Status<List<T>>(1, "Entities returned Successfully !",entityList);
            else
                return new Status<List<T>>(0, "Entities not returned Successfully !",entityList);
        } catch (Exception e) {
            logger.error("Entities not lited Successfully !", e);
            return new Status<List<T>>(0, e.toString(),entityList);
        }

    }

    public Class<T> getEntityClass() {
        return entityClass;
    }

    public void setEntityClass(Class<T> entityClass) {
        this.entityClass = entityClass;
    }
}

I found a way by Object args, not sure why but works:

package com.beingjavaguys.controller;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.beingjavaguys.model.Model;
import com.beingjavaguys.model.Status;
import com.beingjavaguys.services.GenericServices;

@Controller
public abstract class AbstractRest<T extends Model, I extends GenericServices<T>> {

    @Autowired
    I services;
    static final Logger logger = Logger.getLogger(AbstractRest.class);

    public AbstractRest() {
        super();
        Type kind = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        @SuppressWarnings("unchecked")
        Class<T> clazz = (Class<T>) kind;
        this.setEntityClass(clazz);
    }

    private Class<T> entityClass;

    @SuppressWarnings("unchecked")
    private T converter(Object t)
            throws InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException,IllegalArgumentException {
        if (entityClass.isInstance(t))
            return (T) t;
        LinkedHashMap<String, Object> c = ((LinkedHashMap<String, Object>) t);
        T entity = entityClass.newInstance();
        Class<?> clazz = entity.getClass();
        for (String key : c.keySet()) {
            try {
                Field field = clazz.getDeclaredField(key);

                field.setAccessible(true);

                Object value = c.get(key);
                if (Integer.class.isAssignableFrom(field.getType())) {
                    value = Integer.valueOf(((Number) value).intValue());
                } else if (Double.class.isAssignableFrom(field.getType())) {
                    value = Double.valueOf(((Number) value).doubleValue());
                } else if (Long.class.isAssignableFrom(field.getType())) {
                    value = Long.valueOf(((Number) value).longValue());
                } else if (Float.class.isAssignableFrom(field.getType())) {
                    value = Float.valueOf(((Number) value).floatValue());
                } 
                field.set(entity, value);
            } catch (Exception e) {
                logger.error("Entity does not have this atribute " + key + "! Returning entity without this.");
            }
        }
        return entity;
    }

    @RequestMapping(value = "/criar", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE,
            MediaType.APPLICATION_FORM_URLENCODED_VALUE })
    public @ResponseBody Status<T> addEntity(@RequestBody Object t) throws Exception {
        try {
            T entity = converter(t);

            if (services.addEntity(entity)) {
                return new Status<T>(1, "Entity added Successfully!", entity);
            } else {
                return new Status<T>(0, "Entity not added Successfully!", entity);
            }
        } catch (Exception e) {
            logger.error("Entity not added Successfully !", e);
            return new Status<T>(0, e.toString(), null);
        }
    }

    @RequestMapping(value = "/atualizar", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody Status<T> mergeEntity(@RequestBody Object t) throws Exception {
        try {
            T entity = converter(t);

            if (services.mergeEntity(entity)) {
                return new Status<T>(1, "Entity merged Successfully !", entity);
            } else {
                return new Status<T>(0, "Entity not merged Successfully !", entity);
            }
        } catch (Exception e) {
            logger.error("Entity not merged Successfully !", e);
            return new Status<T>(0, e.toString(), null);
        }
    }

    @RequestMapping(value = "/pesquisar", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody Status<List<T>> getEntityList(@RequestBody Object t) throws Exception {
        try {
            T entity = converter(t);
            List<T> entityList = services.getEntityList(entity);
            if (entityList != null)
                return new Status<List<T>>(1, "Entities returned Successfully !", entityList);
            else
                return new Status<List<T>>(0, "Entities not returned Successfully !", entityList);
        } catch (Exception e) {
            logger.error("Entities not lited Successfully !", e);
            return new Status<List<T>>(0, e.toString(), null);
        }

    }

    @RequestMapping(value = "/apagar/{id}", method = RequestMethod.GET)
    public @ResponseBody Status<Boolean> deleteEntity(@PathVariable("id") long id) throws Exception {
        try {
            if (services.deleteEntity(id)) {
                return new Status<Boolean>(1, "Entity deleted Successfully !", true);
            } else {
                return new Status<Boolean>(0, "Entity not deleted Successfully !", false);
            }
        } catch (Exception e) {
            logger.error("Entity not deleted Successfully !", e);
            return new Status<Boolean>(0, e.toString(), false);
        }
    }

    @RequestMapping(value = "/obter/{id}", method = RequestMethod.GET)
    public @ResponseBody Status<T> getEntity(@PathVariable("id") long id) throws Exception {
        T entity = entityClass.newInstance();
        try {
            entity = services.getEntity(id);
            if (entity != null)
                if (entity.getId() == 0)
                    return new Status<T>(1, "Entity not found!", null);
                else
                    return new Status<T>(1, "Entity returned Successfully !", entity);
            else
                return new Status<T>(0, "Entity not returned Successfully !", entity);
        } catch (Exception e) {
            logger.error("Entity not returned Successfully !", e);
            return new Status<T>(0, e.toString(), entity);
        }

    }

    @RequestMapping(value = "/listar", method = RequestMethod.GET)
    public @ResponseBody Status<List<T>> getEntityList() throws Exception {
        List<T> entityList = new ArrayList<T>();
        try {
            entityList = services.getEntityList();
            if (entityList != null)
                return new Status<List<T>>(1, "Entities returned Successfully !", entityList);
            else
                return new Status<List<T>>(0, "Entities not returned Successfully !", entityList);
        } catch (Exception e) {
            logger.error("Entities not lited Successfully !", e);
            return new Status<List<T>>(0, e.toString(), entityList);
        }

    }

    public Class<T> getEntityClass() {
        return entityClass;
    }

    public void setEntityClass(Class<T> entityClass) {
        this.entityClass = entityClass;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM