java - Changed & Improved passing data from WebServlet to a WebService -
i'm pretty new writing servlet , rest services, i'm @ problem i'm not sure if i'm doing correctly. service this:
@post @produces ("application/json") @path ("/register") public string register( @formparam("name") string name, @formparam("username") string username, @formparam("password") string password, @context httpservletresponse servletresponse) throws ioexception { if( this.user_taken(username) ) return "username_taken"; user user = new user(name,username,password); ..... return mapper.writevalueasstring(user); }
so can see service
takes care of doing end (database , creating user) servlet
on other hand in charge of taking request form, validating , passing service
. servlet code:
... validate user input form ... clientconfig config = new defaultclientconfig(); client client = client.create(config); webresource service = client.resource("http://localhost/jaba"); string map = mapper.writevalueasstring(request.getparametermap()); multivaluedmap<string, string> obj = mapper.readvalue(map, multivaluedmap.class); string result = service.path("api").path("register") .accept("application/json") .post(string.class, obj);
as can see client (servlet) has lot of nasty work, pass data service. how can changed/improved/optimized or better yet refactored ? i'm trying follow best practices , how in real life example.
here might do:
instead of doing
string result = service.path("api").path("register") .accept("application/json") .post(string.class, obj);
i more creating dto object, filling out , passing service. apply aspect along jsr validation , annotations (you can on have won't nice) on client call.
example:
@aspect public class dtovalidator { private validator validator; public dtovalidator() { } public dtovalidator(validator validator) { this.validator = validator; } public void dovalidation(joinpoint jp){ for( object arg : jp.getargs() ){ if (arg != null) { set<constraintviolation<object>> violations = validator.validate(arg); if( violations.size() > 0 ){ throw builderror(violations); } } } } private static badrequestexception builderror( set<constraintviolation<object>> violations ){ map<string, string> errormap = new hashmap<string, string>(); for( constraintviolation error : violations ){ errormap.put(error.getpropertypath().tostring(), error.getmessage()); } return new badrequestexception(errormap); } }
you can annotatively declare aspect or can in config (makes reusable). such:
<aop:config proxy-target-class="true"> <aop:aspect id="dtovalidator" ref="dtovalidator" order="10"> <aop:before method="dovalidation" pointcut="execution(public * com.mycompany.client.*.*(..))"/> </aop:aspect> </aop:config>
now can have dto this:
@xmlaccessortype(xmlaccesstype.field) @xmlrootelement public class loginrequest extends abstractdto{ @notnull private string username; @notnull private string password; private loginrequest() { } public loginrequest(string username, string password) { this.username = username; this.password = password; } public string getusername() { return username; } public string getpassword() { return password; } }
when fails @notnull
checks this:
{ "message":"{username=must not null", "httpstatuscode":400, "httpmessage":"bad request", "details":{ "username":"must not null" } }
then use restoperation client such
org.springframework.web.client.restoperations restclient ... restclient.postforobject(url,new dto(...),args);
place aspect around restclient
, you're golden (and, measure, on service calls too).
Comments
Post a Comment