[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [ecf-dev] Sending PUT Request using ECF

Hi Atanas,

On 3/12/2012 12:25 PM, Атанас Тодоров wrote:
Hi Scott,
I think i will not be able to make the service public available but i can give you more detailed information which i hope will help you help me .Also i have some questions.

At this row : 
return (T) restClientService.callSync(RestCallFactory.createRestCall(resource, request.getBody()));
the request.getBody() value is :

[<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PortSettings xsi:schemaLocation="/spm/configuration/common/schema/PortSettings.xsd" xmlns="http://namespaces.softwareag.com/Platform/Management/Common/PortSettings" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Port alias="com.softwareag.jmx.connector.pid-">
        <Enabled>true</Enabled>
        <Number>4446</Number>
        <Protocol>JMX</Protocol>
        <ExtendedProperties>
            <Property name="jaasRealm">SSXLoginOS</Property>
            <Property name="secure">false</Property>
        </ExtendedProperties>
    </Port>
</PortSettings>
]
which means the data i want to sent is not empty and is part of the request body.

The information i am trying to send via the wire is xml so i am trying to construct the put request like this:
AbstractRequestType requestType = new HttpPutRequestType(HttpPutRequestType.STRING_REQUEST_ENTITY,"application/xml");

Is this the right way?

The answer to this depends upon the characteristics/expectations of the service.  Here's the code (in RestClientService.preparePutMethod...which is called in callSync:

        if (putRequestType.useRequestEntity()) {
            if (defaultParameters != null && defaultParameters.length > 0 && parameters != null && parameters.length > 0) {
                RequestEntity requestEntity = putRequestType.generateRequestEntity(uri, call, callable, defaultParameters[0], parameters[0]);
                result.setRequestEntity(requestEntity);
            }
        } else {
            NameValuePair[] params = toNameValuePairs(uri, call, callable);
            if (params != null)
                result.setQueryString(params);
        }


In your case, useRequestEntity() should return true (STRING_REQUEST_ENTITY=1 ...which is > -1), and so this block gets called:

            if (defaultParameters != null && defaultParameters.length > 0 && parameters != null && parameters.length > 0) {
                RequestEntity requestEntity = putRequestType.generateRequestEntity(uri, call, callable, defaultParameters[0], parameters[0]);
                result.setRequestEntity(requestEntity);
            }


As you can see, this calls HttpPutRequestType.generateRequestEntity(uri,call,callable, defaultParameters[0], and parameters[0])

which for your case corresponds to:

uri=<whatever it is>
call = the IRestCall instance
callable = the associated IRemoteCallable
defaultParameters[0] = null
and
parameters[0] = your xml as given above (element [0] in the parameters array).

At least I think this is right.

Now, in HttpPutRequestType/AbstractEntityRequestType.generateRequestEntity is this code:

    public RequestEntity generateRequestEntity(String uri, IRemoteCall call, IRemoteCallable callable, IRemoteCallParameter paramDefault, Object paramToSerialize) throws NotSerializableException {
        if (paramToSerialize instanceof RequestEntity)
            return (RequestEntity) paramToSerialize;
        switch (requestEntityType) {
            case INPUT_STREAM_REQUEST_ENTITY :
...
//$NON-NLS-1$
            case STRING_REQUEST_ENTITY :
                if (paramToSerialize instanceof String) {
                    try {
                        return new StringRequestEntity((String) paramToSerialize, getContentType(call, callable, paramDefault), getCharset(call, callable, paramDefault));
                    } catch (UnsupportedEncodingException e) {
                        throw new NotSerializableException("Could not create request entity from call parameters: " + e.getMessage()); //$NON-NLS-1$
                    }
                }
                throw new NotSerializableException("Cannot generate request entity.  Expecting String and got class=" + paramToSerialize.getClass().getName()); //$NON-NLS-1$

So it's returning/creating a new StringRequestEntity with the body as the first param, content type getContentType result as second param, and getCharset result as third param.  StringRequestEntity is an httpclient class, that apparently writes the request out as a byte[] (with charset encoding).  Does this seem like what your service is expecting for the 'put'?

There is no javadoc nor any examples like POST request examples so it is hard to guess how to use the API in the right way.

I agree.  What we most need for examples is the server/service side impl...and no one has contributed that.  It would be great if you would consider contributing a simple put-based service (doesn't have to be one you are working on)...and then it should be straightforward to create an example for put.

For this specific case for example I do not know what's the difference between all the constructors of HttpPutRequestType  class and I do not know which one to use.

The answer to this is essentially determined by the implementation of generateRequestEntity, which is implemented in the AbstractEntityRequestType class.


Sending POST request via ECF do not require to specify content type but seems PUT request require that parameter.And if so why?

You can create an HttpPutRequestType with a default content type (which is null/unspecified), and you can also specify a defaultParameter by the name of "contentType" to specify the appropriate value (see AbstractEntityRequestType.getContentType()), or pass the desired content type in HttpPutRequestType, or you can/could even create an HttpPutRequestType subclass for your put request and override AbstractEntityRequestType.getContentType() to return the appropriate content type (application/xml).

It is possible, of course, that there is some problem/bug here...or even in the httpclient put code (e.g. StringRequestEntity), and obviously if we can isolate the problem and it's in our code we will fix it.

Please let me know if this helps...and please do consider providing some put-based service...just so that we can provide more examples/test code for the put use case.

Thanks,

Scott







2012/3/12 Scott Lewis <slewis@xxxxxxxxxxxxx>
Hi Atanas,

Yes, I believe we probably can help you.  One of the difficulties of testing/example/demoing this, however, is to have a PUT-based web service available.  Is there a put-based web service that you can make available (even temporarily) for us to use?

...or point to some public put-based service that resembles your service (in terms of parameters, serialization, etc).

Thanks,

Scott



On 3/8/2012 7:41 AM, Атанас Тодоров wrote:
Hi,
Can you help me send a PUT request using ECF framework.I have a web resource exposed via REST and i want to update it with some data.

NOTE: GET,POST,DELETE requests work for me.

The code i use is:

AbstractRequestType requestType = new HttpPutRequestType();
Request request = new Request(requestType, new Object[] { configuration }); // configuration is String and is not empty or null.
RemoteServiceProxy proxy =  new RemoteServiceProxy<Object>(deserializer, host) // deserializer is custom impl of BaseRemoteResponseDeserializer
proxy.makeRestSyncCall(url.toString(), request);

where 

 public T makeRestSyncCall(String resource, Request request) throws ECFException {
        IContainer originalContainer = ContainerFactory.getDefault().createContainer(REST_CONTAINER_TYPE, url);
        RestID restID = null;
        try {
         restID = new RestID(originalContainer.getConnectNamespace(), new URI(url));
        } catch (Exception ex) {
         //TODO log exception when we have logger
         return null;
        }
        IContainer container = new SPMRestClientContainer(restID);
        IRemoteServiceClientContainerAdapter adapter = (IRemoteServiceClientContainerAdapter) container
            .getAdapter(IRemoteServiceClientContainerAdapter.class);
        adapter.setConnectContextForAuthentication(ConnectContextFactory.createUsernamePasswordConnectContext(
            UriContainer.REMOTE_USERNAME, UriContainer.REMOTE_PASSWORD));
        adapter.setResponseDeserializer(deserializer);
        IRemoteCallParameter[] rcp = null;
        if (request.getRequestType() instanceof HttpPostRequestType) {
            rcp = RemoteCallParameterFactory.createParameters("", "");//$NON-NLS-1$ //$NON-NLS-2$
        }
        IRemoteCallable callable = RestCallableFactory.createCallable(resource, resource, rcp, request.getRequestType(),
            IRestCall.DEFAULT_TIMEOUT);
        IRemoteServiceRegistration registration = adapter.registerCallables(new IRemoteCallable[] { callable }, null);
        IRemoteService restClientService = adapter.getRemoteService(registration.getReference());

        return (T) restClientService.callSync(RestCallFactory.createRestCall(resource, request.getBody()));
    }




I think the problem is in the way i construct the HttpPutRequestType as it is the only difference comparing to POST,GET,DELETE.
On the server side the object i am sending is an empty string and that's the problem.

Hope can help me,
Best Regards,
Atanas Todorov


_______________________________________________
ecf-dev mailing list
ecf-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/ecf-dev


_______________________________________________
ecf-dev mailing list
ecf-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/ecf-dev




_______________________________________________
ecf-dev mailing list
ecf-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/ecf-dev