users@jersey.java.net

Re: [Jersey] JSON GET followed by PUT

From: Keith R. Davis <keith.davis_at_zunisoft.com>
Date: Sat, 02 Aug 2008 11:22:19 -0600

Thanks for response,

The resource class was generated by the Netbeans wizard so all the
annotated methods are present. Something is very messed up, I tried
testing a very simple resource class in my project (all generated by the
wizards):

Class code:

public class CountryResource {
    private Integer id;
    private UriInfo context;
   
    /** Creates a new instance of CountryResource */
    public CountryResource() {
    }

    /**
     * Constructor used for instantiating an instance of dynamic resource.
     *
     * @param context HttpContext inherited from the parent resource
     */
    public CountryResource(Integer id, UriInfo context) {
        this.id = id;
        this.context = context;
    }

    /**
     * Get method for retrieving an instance of Countries identified by
id in XML format.
     *
     * @param id identifier for the entity
     * @return an instance of CountryConverter
     */
    @GET
    @ProduceMime({"application/xml", "application/json"})
    public CountryConverter get() {
        try {
            return new CountryConverter(getEntity(),
context.getAbsolutePath());
        } finally {
            PersistenceService.getInstance().close();
        }
    }

    /**
     * Put method for updating an instance of Countries identified by id
using XML as the input format.
     *
     * @param id identifier for the entity
     * @param data an CountryConverter entity that is deserialized from
a XML stream
     */
    @PUT
    @ConsumeMime({"application/xml", "application/json"})
    public void put(CountryConverter data) {
        PersistenceService service = PersistenceService.getInstance();
        try {
            service.beginTx();
            updateEntity(getEntity(), data.getEntity());
            service.commitTx();
        } finally {
            service.close();
        }
    }

    /**
     * Delete method for deleting an instance of Countries identified by id.
     *
     * @param id identifier for the entity
     */
    @DELETE
    public void delete() {
        PersistenceService service = PersistenceService.getInstance();
        try {
            service.beginTx();
            Countries entity = getEntity();
            service.removeEntity(entity);
            service.commitTx();
        } finally {
            service.close();
        }
    }

    /**
     * Returns a dynamic instance of StatesResource used for entity
navigation.
     *
     * @param id identifier for the parent entity
     * @return an instance of StatesResource
     */
    @Path("states/")
    public StatesResource getStatesResource() {
        final Countries parent = getEntity();
        return new StatesResource(context) {

            @Override
            protected Collection<States> getEntities(int start, int max) {
                Collection<States> result = new
java.util.ArrayList<States>();
                int index = 0;
                for (States e : parent.getStatesCollection()) {
                    if (index >= start && (index - start) < max) {
                        result.add(e);
                    }
                    index++;
                }
                return result;
            }

            @Override
            protected void createEntity(States entity) {
                super.createEntity(entity);
                entity.setCountryId(parent);
            }
        };
    }

    /**
     * Returns a dynamic instance of UserProfilesResource used for
entity navigation.
     *
     * @param id identifier for the parent entity
     * @return an instance of UserProfilesResource
     */
    @Path("userProfiles/")
    public UserProfilesResource getUserProfilesResource() {
        final Countries parent = getEntity();
        return new UserProfilesResource(context) {

            @Override
            protected Collection<UserProfiles> getEntities(int start,
int max) {
                Collection<UserProfiles> result = new
java.util.ArrayList<UserProfiles>();
                int index = 0;
                for (UserProfiles e : parent.getUserProfilesCollection()) {
                    if (index >= start && (index - start) < max) {
                        result.add(e);
                    }
                    index++;
                }
                return result;
            }

            @Override
            protected void createEntity(UserProfiles entity) {
                super.createEntity(entity);
                entity.setCountryId(parent);
            }
        };
    }

    /**
     * Returns an instance of Countries identified by id.
     *
     * @param id identifier for the entity
     * @return an instance of Countries
     */
    protected Countries getEntity() {
        try {
            return (Countries)
PersistenceService.getInstance().createQuery("SELECT e FROM Countries e
where e.id = :id").setParameter("id", id).getSingleResult();
        } catch (NoResultException ex) {
            throw new WebApplicationException(new Throwable("Resource
for " + context.getAbsolutePath() + " does not exist."), 404);
        }
    }

    /**
     * Updates entity using data from newEntity.
     *
     * @param entity the entity to update
     * @param newEntity the entity containing the new data
     * @return the updated entity
     */
    protected Countries updateEntity(Countries entity, Countries
newEntity) {
        newEntity.setId(entity.getId());
        
entity.getStatesCollection().removeAll(newEntity.getStatesCollection());
        for (States value : entity.getStatesCollection()) {
            value.setCountryId(null);
        }
        
entity.getUserProfilesCollection().removeAll(newEntity.getUserProfilesCollection());
        for (UserProfiles value : entity.getUserProfilesCollection()) {
            value.setCountryId(null);
        }
        entity = PersistenceService.getInstance().mergeEntity(newEntity);
        for (States value : entity.getStatesCollection()) {
            value.setCountryId(entity);
        }
        for (UserProfiles value : entity.getUserProfilesCollection()) {
            value.setCountryId(entity);
        }
        return entity;
    }
}

GET works perfectly.

PUT doesn't

    Trailing slash removed: 404 error

    Trailing slash in-place: 500 error

Stack trace (short version):

StandardWrapperValve[ServletAdaptor]: PWC1406: Servlet.service() for
servlet ServletAdaptor threw exception
com.sun.jersey.api.container.ContainerException: Exception injecting
parameters to Web resource method

Caused by: java.lang.IllegalArgumentException: local part cannot be
"null" when creating a QName

Things get better with this class:

public class UserProfileResource {
    private Integer id;
    private UriInfo context;
   
    /** Creates a new instance of UserProfileResource */
    public UserProfileResource() {
    }

    /**
     * Constructor used for instantiating an instance of dynamic resource.
     *
     * @param context HttpContext inherited from the parent resource
     */
    public UserProfileResource(Integer id, UriInfo context) {
        this.id = id;
        this.context = context;
    }

    /**
     * Get method for retrieving an instance of UserProfiles identified
by id in XML format.
     *
     * @param id identifier for the entity
     * @return an instance of UserProfileConverter
     */
    @GET
    @ProduceMime({"application/xml", "application/json"})
    public UserProfileConverter get() {
        try {
            return new UserProfileConverter(getEntity(),
context.getAbsolutePath());
        } finally {
            PersistenceService.getInstance().close();
        }
    }

    /**
     * Put method for updating an instance of UserProfiles identified by
id using XML as the input format.
     *
     * @param id identifier for the entity
     * @param data an UserProfileConverter entity that is deserialized
from a XML stream
     */
    @PUT
    @ConsumeMime({"application/xml", "application/json"})
    public void put(UserProfileConverter data) {
        PersistenceService service = PersistenceService.getInstance();
        try {
            service.beginTx();
            updateEntity(getEntity(), data.getEntity());
            service.commitTx();
        } finally {
            service.close();
        }
    }

    /**
     * Delete method for deleting an instance of UserProfiles identified
by id.
     *
     * @param id identifier for the entity
     */
    @DELETE
    public void delete() {
        PersistenceService service = PersistenceService.getInstance();
        try {
            service.beginTx();
            UserProfiles entity = getEntity();
            service.removeEntity(entity);
            service.commitTx();
        } finally {
            service.close();
        }
    }

    /**
     * Returns a dynamic instance of CountryResource used for entity
navigation.
     *
     * @param id identifier for the parent entity
     * @return an instance of CountryResource
     */
    @Path("country/")
    public CountryResource getCountryResource() {
        final UserProfiles parent = getEntity();
        return new CountryResource(null, context) {

            @Override
            protected Countries getEntity() {
                Countries entity = parent.getCountryId();
                if (entity == null) {
                    throw new WebApplicationException(new
Throwable("Resource for " + context.getAbsolutePath() + " does not
exist."), 404);
                }
                return entity;
            }
        };
    }

    /**
     * Returns a dynamic instance of SpecialtyResource used for entity
navigation.
     *
     * @param id identifier for the parent entity
     * @return an instance of SpecialtyResource
     */
    @Path("specialty/")
    public SpecialtyResource getSpecialtyResource() {
        final UserProfiles parent = getEntity();
        return new SpecialtyResource(null, context) {

            @Override
            protected Specialties getEntity() {
                Specialties entity = parent.getSpecialtyId();
                if (entity == null) {
                    throw new WebApplicationException(new
Throwable("Resource for " + context.getAbsolutePath() + " does not
exist."), 404);
                }
                return entity;
            }
        };
    }

    /**
     * Returns a dynamic instance of StateResource used for entity
navigation.
     *
     * @param id identifier for the parent entity
     * @return an instance of StateResource
     */
    @Path("state/")
    public StateResource getStateResource() {
        final UserProfiles parent = getEntity();
        return new StateResource(null, context) {

            @Override
            protected States getEntity() {
                States entity = parent.getStateId();
                if (entity == null) {
                    throw new WebApplicationException(new
Throwable("Resource for " + context.getAbsolutePath() + " does not
exist."), 404);
                }
                return entity;
            }
        };
    }

    /**
     * Returns a dynamic instance of UserResource used for entity
navigation.
     *
     * @param id identifier for the parent entity
     * @return an instance of UserResource
     */
    @Path("user/")
    public UserResource getUserResource() {
        final UserProfiles parent = getEntity();
        return new UserResource(null, context) {

            @Override
            protected Users getEntity() {
                Users entity = parent.getUserId();
                if (entity == null) {
                    throw new WebApplicationException(new
Throwable("Resource for " + context.getAbsolutePath() + " does not
exist."), 404);
                }
                return entity;
            }
        };
    }

    /**
     * Returns an instance of UserProfiles identified by id.
     *
     * @param id identifier for the entity
     * @return an instance of UserProfiles
     */
    protected UserProfiles getEntity() {
        try {
            return (UserProfiles)
PersistenceService.getInstance().createQuery("SELECT e FROM UserProfiles
e where e.id = :id").setParameter("id", id).getSingleResult();
        } catch (NoResultException ex) {
            throw new WebApplicationException(new Throwable("Resource
for " + context.getAbsolutePath() + " does not exist."), 404);
        }
    }

    /**
     * Updates entity using data from newEntity.
     *
     * @param entity the entity to update
     * @param newEntity the entity containing the new data
     * @return the updated entity
     */
    protected UserProfiles updateEntity(UserProfiles entity,
UserProfiles newEntity) {
        newEntity.setId(entity.getId());
        entity = PersistenceService.getInstance().mergeEntity(newEntity);
        return entity;
    }
}

GET works perfectly.

PUT doesn't

    Trailing slash removed: 404 error

    Trailing slash in-place: 404 error

I also regenerated the classes and converters, testing yielded the same
results...

Craig McClanahan wrote:
> Keith R. Davis wrote:
>> This will be the dumbest question on this list for today:
>>
>> While using the web test functionality of 0.8ea within Netbeans 6.1
>> and GF v2UR2, if I test one of my resources with a GET
>> (application/json):
>>
>> http://localhost:8080/openeprs-svcs/resources/userProfiles/1/
>>
>> I get the JSON, no problem, looks as expected.
>>
>> Now if I copy the JSON returned and select PUT (application/json) and
>> paste the response into the content field and set the id field to '1':
>>
>> I get a 404 not found error with no obvious errors in the GF log.
>>
> I assume you have a suitable method annotated with @PUT in the same
> resource class, right? A 404 (if it came from JAX-RS would typically
> mean no method could be found to handle the incoming URL.
>
> The only other thought I have is an idle curiousity one ... does it
> work without the trailing slash? That's the way I've been formatting
> my URLs and it seems to work fine.
>
> Craig
>> The JSON being used:
>>
>> {"userProfile":{"@uri":"http://localhost:8080/openeprs-svcs/resources/userProfiles/1/","billName":"","cellPhone":"","city":"","countryRef":{"@uri":"http://localhost:8080/openeprs-svcs/resources/userProfiles/1/country/","id":"223"},"drugId":"","email":"admin@test.com","firstName":"System","homePhone":"","id":"1","lastName":"Administrator","middleName":"","npi":"","postalCode":"","prefix":"","specialtyRef":{"@uri":"http://localhost:8080/openeprs-svcs/resources/userProfiles/1/specialty/","id":"82"},"stateRef":{"@uri":"http://localhost:8080/openeprs-svcs/resources/userProfiles/1/state/","id":"1"},"street1":"","street2":"","suffix":"","taxId":"555-55-5555","upin":"","userRef":{"@uri":"http://localhost:8080/openeprs-svcs/resources/userProfiles/1/user/","id":"1"},"workFax":"","workPhone1":"","workPhone2":""}}
>>
>>
>> The only modification to the JSON returned by the GET and PUT is that
>> I update the taxid field. Still fails even with a straight cut and
>> paste.
>>
>> I must be missing something. When I PUT to
>> http://localhost:8080/openeprs-svcs/resources/userProfiles/1/ does
>> the JSON need to be formatted differently from what is returned by
>> the get?
>>
>> Thanks in advance...
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>