It would make more sense to me to organize the API around resources and use the verbs (GET, PUT, POST, DELETE) that come with the http protocol, in short: Make it more RESTful, that is surely considered good practice.
This is a good succinct talk on API design that also analyzes popular APIs such as facebook's or twitter's.
I am lost on the difference between your /getX and /getXForId so I can't really give you an example of how I would change your API.
Edit
I tried to model the API in Sinatra. It is pretty self explanatory and straight forward. (I saw you are using axis but it's been a while since I did serious Java). If you are serious about RESTful then you probably want to drop the approach with the four ids. However the approach works:
require "sinatra"
require "sinatra/reloader"
def all_ids_given?(ids_given, ids_needed)
ids_needed.reduce(true){|memo, id| memo &= ids_given.include? id}
end
#Your old /getXForId
get '/X/:combined_id' do |id|
"Getting X with combined id #{id}\r\n"
end
#Your old /createX
post '/X' do
post_params = request.body.read
"Creating a new X with #{post_params} \r\n"
end
#Your old /updateXForId
put '/X/:combined_id' do |id|
put_params = request.body.read
"Updating X with combined id #{id}: New values are #{put_params}\r\n"
end
#Your old /removeXForId
delete '/X/:combined_id' do |id|
"Deleting X with combined id #{id}\r\n"
end
#Your old /getX
get '/X' do
if all_ids_given?(params.keys, ["id1","id2","id3","id4"])
"Getting X with the ids #{params}\r\n"
else
"Error: Need arguments for id1, id2, id3 and id4\r\n"
end
end
#Your old /updateX
put '/X' do
if all_ids_given?(params.keys, ["id1","id2","id3","id4"])
put_params = request.body.read
"Updating X with the ids #{params}: New values are #{put_params}\r\n"
else
"Error: Need arguments for id1, id2, id3 and id4\r\n"
end
end
#Your old /removeX
delete '/X' do
if all_ids_given?(params.keys, ["id1","id2","id3","id4"])
"Deleting X with combined id #{params}\r\n"
else
"Error: Need arguments for id1, id2, id3 and id4\r\n"
end
end
#Extensibility
get '/X/:combined_id/Y' do |id|
"Getting all Ys for the X with combined id #{id}\r\n"
end
Testing the API with curl:
base_url="http://localhost:4567/"
echo "Getting a X with a combined id"
echo -n "-> "; curl ${base_url}X/id1234
echo "Creating a new X with a list of properties"
echo -n "-> "; curl --data "property_1=test" ${base_url}X
echo "Updating an existing X with a combined id"
echo -n "-> "; curl -X PUT --data "property_1=test&property_2=another_test" ${base_url}X/id1234
echo "Deleting an existing X with a combined id"
echo -n "-> "; curl -X DELETE ${base_url}X/id1234
echo "Getting a X with 4 ids"
echo -n "-> "; curl ${base_url}"X?id1=1&id2=2&id3=3&id4=4"
echo "Getting a X with 4 ids, but supplying only 3"
echo -n "-> "; curl ${base_url}"X?id1=1&id3=3&id4=4"
echo "Updating a X with 4 ids"
echo -n "-> "; curl -X PUT --data "property_1=test&property_2=another_test" ${base_url}"X?id1=1&id2=2&id3=3&id4=4"
echo "Updating a X with 4 ids"
echo -n "-> "; curl -X DELETE ${base_url}"X?id1=1&id2=2&id3=3&id4=4"
echo "\r\nTesting the extensibility"
echo "Getting all Ys for a single X (Unrelated example: /post/2/comments would give all comments to a single post with the id 2)"
echo -n "-> "; curl ${base_url}X/id1234/Y
echo "This won't work for the 4 ids"
echo -n "-> "; curl ${base_url}"X?id1=1&id2=2&id3=3&id4=4/Y"
The script returns the following:
Getting a X with a combined id
-> Getting X with combined id id1234
Creating a new X with a list of properties
-> Creating a new X with property_1=test
Updating an existing X with a combined id
-> Updating X with combined id id1234: New values are property_1=test&property_2=another_test
Deleting an existing X with a combined id
-> Deleting X with combined id id1234
Getting a X with 4 ids
-> Getting X with the ids {"id1"=>"1", "id2"=>"2", "id3"=>"3", "id4"=>"4"}
Getting a X with 4 ids, but supplying only 3
-> Error: Need arguments for id1, id2, id3 and id4
Updating a X with 4 ids
-> Updating X with the ids {"id1"=>"1", "id2"=>"2", "id3"=>"3", "id4"=>"4", "property_1"=>"test", "property_2"=>"another_test"}: New values are property_1=test&property_2=another_test
Updating a X with 4 ids
-> Deleting X with combined id {"id1"=>"1", "id2"=>"2", "id3"=>"3", "id4"=>"4"}
Testing the extensibility
Getting all Ys for a single X (Unrelated example: /post/2/comments would give all comments to a single post with the id 2)
-> Getting all Ys for the X with combined id id1234
This won't work for the 4 ids
-> Getting X with the ids {"id1"=>"1", "id2"=>"2", "id3"=>"3", "id4"=>"4/Y"}
What you can see is that nesting resources and the four parameter approach does not work well together. Maybe one could model it differently and do something like /X/:id1/:id2/:id3/:id4.