{"id":18076594,"url":"https://github.com/ggeorgovassilis/spring-rest-invoker","last_synced_at":"2025-04-12T08:25:56.544Z","repository":{"id":15596005,"uuid":"18332040","full_name":"ggeorgovassilis/spring-rest-invoker","owner":"ggeorgovassilis","description":"Spring invoker which maps remote REST services to local interfaces.","archived":false,"fork":false,"pushed_at":"2022-02-22T03:01:21.000Z","size":2110,"stargazers_count":37,"open_issues_count":5,"forks_count":19,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-06T09:02:34.111Z","etag":null,"topics":["rest","rpc","spring"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ggeorgovassilis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-04-01T14:22:14.000Z","updated_at":"2023-06-08T07:43:50.000Z","dependencies_parsed_at":"2022-09-02T21:21:31.229Z","dependency_job_id":null,"html_url":"https://github.com/ggeorgovassilis/spring-rest-invoker","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ggeorgovassilis%2Fspring-rest-invoker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ggeorgovassilis%2Fspring-rest-invoker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ggeorgovassilis%2Fspring-rest-invoker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ggeorgovassilis%2Fspring-rest-invoker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ggeorgovassilis","download_url":"https://codeload.github.com/ggeorgovassilis/spring-rest-invoker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248538625,"owners_count":21121019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rest","rpc","spring"],"created_at":"2024-10-31T11:10:32.272Z","updated_at":"2025-04-12T08:25:56.522Z","avatar_url":"https://github.com/ggeorgovassilis.png","language":"Java","funding_links":[],"categories":["HTTP客户端"],"sub_categories":["微服务框架"],"readme":"\u003cimg src=\"https://travis-ci.org/ggeorgovassilis/spring-rest-invoker.svg\"/\u003e\n\n\nspring-rest-invoker\n===================\n\nSpring invoker that binds remote JSON REST services to java interfaces similarily to how [HttpInvokerProxyFactoryBean](http://docs.spring.io/spring/docs/3.2.8.RELEASE/javadoc-api//org/springframework/remoting/httpinvoker/HttpInvokerProxyFactoryBean.html \"HttpInvokerProxyFactoryBean\") works. Invoking methods on those interfaces will make an HTTP request to the remote service and (de)serialize any objects to/from JSON. The concrete mapping between an interface and a remote service can be done programmatically or by annotating interfaces with Spring or JAX-RS annotations.\n\n![Schematic of the spring-invoker proxy's function](https://raw.githubusercontent.com/ggeorgovassilis/spring-rest-invoker/master/images/spring-invoker.png \"Mapping of a java interface to a REST http service\")\n\nFeatures:\n\n- Consume REST JSON services\n- Declare a service interface and bind it to remote URLs with annotations (spring or jax-rs)\n- Convert JSON to Java POJOs and vice versa\n- Convert method arguments to GET parameters\n- POST one or more objects\n\n\n## News\n\n2021-06-10: Released 1.8 to maven central. Corrections in documentation, example for annotation-based configuration, supporting more Spring annotations (thanks [Arturo Volpe](https://github.com/aVolpe)), added MT test for opaque proxy factory (thanks [Arturo Volpe](https://github.com/aVolpe)), upgraded jackson dependencies, supporting Spring mapping path computation (thanks [Serhii Teroshyn](https://github.com/minasgull))\n\n2018-06-22: Released 1.7 to maven central\n\n2017-09-27: Released 1.6. #26 CglibProxyFactory now really creating opaque proxies; refactored ProxyFactory API.\n\n2017-09-20: Released 1.5. #20 Backported to Java 6, #21 Separate integration tests, #22 HTTP method headers for JaxRs\n\n2017-08-04: Released 1.4. Handling parametrised return types (credits to [Valentin Ozanne](https://github.com/ValentinOzanne))\n\n2017-06-04: Released 1.3. Updated dependencies\n\n2016-01-07: Released 1.2. Fixed order of parameters and attributes in JSON, updated Spring, Jackson\n\n2014-08-17: edited 1.0.RC-SNAPSHOT to fix broken unit tests and rename proxy factories\n\n2014-08-12: version 1.0.RC-SNAPSHOT adds support for opaque (cglib) proxies\n\n2014-08-11: version 0.0.9-SNAPSHOT adds support for bean expressions in RequestMapping and Path annotations\n\n2014-07-25: version 0.0.7-SNAPSHOT adds support for logging HTTP traffic\n\n2014-07-12: version 0.0.6-SNAPSHOT is out with support for jax-rs annotations, arguments as HTTP headers, arguments as cookies\n\n2014-05-25: version 0.0.5-SNAPSHOT is out with support for multipart form encoding\n\n2014-04-04: version 0.0.3-SNAPSHOT is out with support for more HTTP methods such as PUT, DELETE etc.\n\n\n## Using\n\n### 0. Getting\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.ggeorgovassilis\u003c/groupId\u003e\n  \u003cartifactId\u003espring-rest-invoker\u003c/artifactId\u003e\n  \u003cversion\u003e1.8.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Building\n\n```git clone https://github.com/ggeorgovassilis/spring-rest-invoker```\n\n```mvn clean install jxr:jxr pmd:pmd pmd:cpd surefire-report:report site```\n\njax-rs support requires a further dependency with the annotations, ie.:\n\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003eorg.jboss.resteasy\u003c/groupId\u003e\n\t\u003cartifactId\u003ejaxrs-api\u003c/artifactId\u003e\n\t\u003cversion\u003e3.0.8.Final\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### 1. Declare an interface, eg:\n\n```java\n@RequestMapping(\"volumes\")\npublic interface BookService {\n\n\t@GetMapping\n\tQueryResult findBooksByTitle(@RequestParam(\"q\") String q);\n\n\t@GetMapping(\"{id}\")\n\tItem findBookById(@PathVariable(\"id\") String id);\n\n\t@PostMapping\n\tLong createBook(@RequestBody NewItem newItem);\n}\n```\n\nNote that the annotations are from spring's web package.\n\nOr, with jax-rs annotations:\n\n```java\npublic interface BookServiceJaxRs extends BookService{\n\n    @Override\n    @GET\n    @Path(\"/volumes\")\n    QueryResult findBooksByTitle(@QueryParam(\"q\") String q);\n    \n    @Override\n    @GET\n    @Path(\"/volumes/{id}\")\n    Item findBookById(@PathParam(\"id\") String id);\n}\n```\n\n### 2. Then map it to the remote REST URL you want to consume:\n\n```xml\n\u003cbean id=\"BookService\"\n\tclass=\"com.github.ggeorgovassilis.springjsonmapper.spring.SpringRestInvokerProxyFactoryBean\"\u003e\n\t\u003cproperty name=\"baseUrl\" value=\"https://www.googleapis.com/books/v1\" /\u003e\n\t\u003cproperty name=\"remoteServiceInterfaceClass\" value=\"com.github.ggeorgovassilis.springjsonmapper.services.spring.BookServiceSpring\"/\u003e\n\u003c/bean\u003e\n```\n\nwith jax-rs\n\n```xml\n\u003cbean id=\"BookService\"\n\tclass=\"com.github.ggeorgovassilis.springjsonmapper.jaxrs.JaxRsInvokerProxyFactoryBean\"\u003e\n\t\u003cproperty name=\"baseUrl\" value=\"https://www.googleapis.com/books/v1\" /\u003e\n\t\u003cproperty name=\"remoteServiceInterfaceClass\" value=\"com.github.ggeorgovassilis.springjsonmapper.services.jaxrs.BookServiceJaxRs\"/\u003e\n\u003c/bean\u003e\n```\n\n### 3. Use it\n\n```java\n...\n@Autowired\nRemoteBookService bookService;\n\n...\nQueryResult results = bookService.findBooksByTitle(\"Alice in Wonderland\");\n\n```\n\n### 4. Examples\n\nPOSTing an object:\n\n```java\npublic interface BankService {\n\n\t@PostMapping(value = \"verify\")\n\tBoolean checkAccount(@RequestBody Account account);\n\n}\n```\n\nor the jax-rs way:\n\n```java\npublic interface BankService {\n\n\t@POST\n\t@Path(\"/verify\")\n\tBoolean checkAccount(@BeanParam Account account);\n\n}\n```\n\n\nPOSTing multiple objects (object names are passed through parameters `@RequestParam`):\n\n```java\npublic interface BankService {\n    @PostMapping(value=\"transfer\")\n    Account transfer(\n\t    @RequestBody @RequestParam(\"fromAccount\") Account fromAccount, \n\t    @RequestBody @RequestParam(\"actor\") Customer actor,\n\t    @RequestBody @RequestParam(\"toAccount\") Account toAccount,\n\t    @RequestBody @RequestParam(\"amount\") int amount,\n\t    @RequestParam(\"sendConfirmationSms\") boolean sendConfirmationSms);\n\n}\n```\n\nOr the respective jax-rs declaration:\n\n```java\npublic interface BankService {\n\t@POST\n\t@Path(\"/transfer\")\n\tAccount transfer(@BeanParam @QueryParam(\"fromAccount\") Account fromAccount, @BeanParam @QueryParam(\"actor\") Customer actor,\n\t\t\t@BeanParam @QueryParam(\"toAccount\") Account toAccount, @BeanParam @QueryParam(\"amount\") int amount,\n\t\t\t@QueryParam(\"sendConfirmationSms\") boolean sendConfirmationSms);\n}\n```\n\nwhich will POST a JSON object similar to:\n\n```javascript\n{\n\t\"fromAccount\":\t{\n\t\t\t\"accountNumber\": 1234,\n\t\t\t\"balance\": 99,\n\t\t\t\"customer\":{\n\t\t\t\t\t\"name\":\"joe doe\"\n\t\t\t\t}\n\t\t\t},\n\t\"actor\":{\n\t\t\"name\":\"joe doe\"\n\t\t},\n\t\"toAccount\":\t{\n\t\t\t\"accountNumber\": 7890,\n\t\t\t\"balance\": 0,\n\t\t\t\"customer\": {\n\t\t\t\t\t\"name\":\"jane doe\"\n\t\t\t\t}\n\t\t\t},\n\t\"amount\": 123\n}\n```\n\nAlternatively, if you prefer annotation-based configuration over XML:\n\n```java\n@Configuration\npublic class MyConfiguration{\n\n\t@Bean\n\tSpringRestInvokerProxyFactoryBean BankService() {\n\t\tSpringRestInvokerProxyFactoryBean proxyFactory = new SpringRestInvokerProxyFactoryBean();\n\t\tproxyFactory.setBaseUrl(\"http://localhost/bankservice\");\n\t\tproxyFactory.setRemoteServiceInterfaceClass(BankServiceSpring.class);\n\t\treturn proxyFactory;\n\t}\n```\n## Supported Annotations\n\n### Spring\n\n```java\n@RequestMapping\t// Specify the URL to bind to. Variable parts are written as {varname} and are replaced with the values of @PathParam. Property placeholders like ${property_name} can also be used which will be looked up in the application context.\n@GetMapping   // same as @RequestMapping(method = GET)\n@PutMapping   // same as @RequestMapping(method = PUT)\n@PostMapping  // same as @RequestMapping(method = POST)\n@DeleteMapping // same as @RequestMapping(method = DELETE)\n@PatchMapping // same as @RequestMapping(method = PATCH)@PathVariable\t// Replace parts of the @Path with the (string) value of this argument\n@PathVariable\t// Replace parts of the @Path with the (string) value of this argument\n@RequestParam\t// Pass argument value as URL parameter (or JSON field, see below)\n@Header\t\t// Pass argument (string) value as HTTP header \n@RequestBody\t// Pass argument as JSON in the request body. If a @QueryParam has been specified, then encode it with that JSON field name\n@RequestPart\t// Pass argument as multipart form request\n@CookieValue\t// Pass argument as cookie\n```\n\n\n### JAX-RS\n\n```java\n@Path\t\t// Specify the URL to bind to. Variable parts are written as {varname} and are replaced with the values of @PathParam. Property placeholders like ${property_name} can also be used which will be looked up in the application context.\n@GET, @POST etc\t// Specify the HTTP request method to use\n@Produces\t// Value of the Accept HTTP header\n@Consumes\t// Value of the Content-Type HTTP header\n@PathParam\t// Replace parts of the @Path with the (string) value of this argument\n@QueryParam\t// Pass argument value as URL parameter (or JSON field, see below)\n@HeaderParam\t// Pass argument (string) value as HTTP header \n@BeanParam\t// Pass argument as JSON in the request body. If a @QueryParam has been specified, then encode it with that JSON field name\n@FormParam\t// Pass argument as multipart form request. Mandatory argument can be blank\n@Headers\t// Non-standard annotation which adds HTTP headers to request\n```\n\n## F.A.Q.\n\n#### What does @RequestParam do?\n\nMethod arguments annotated with `@RequestParam` are, unless otherwise specified, taken as strings and passed as HTTP parameters, e.g.\n\n```java\npublic interface BookService {\n\n    @GetMapping(value=\"books\")\n    Book findBook(@RequestParam(\"isbn\") String isbn);\n\n}\n\n...\n\nbookService.findBook(\"123\");\n```\n\nan invocation of ```findBook``` will result in an HTTP GET request to this url: ```/books?isbn=123```\n\nWhen there is also a ```@RequestBody```, then the handling is different - look further down the F.A.Q.\n\n#### What does @RequestBody do?\n\nUsed when sending JSON to a REST service via an HTTP POST request. Method arguments annotated with ```@RequestBody``` are serialized into JSON and sent to the remote service. If there is only a single method argument annotated with `@RequestBody`, then that argument is serialized and sent over. If multiple arguments are annotated, then each @RequestBody needs to be accompanied by a `@RequestParam` which specifies the field name of the object.\n\nIn an ideal world we wouldn't need `@RequestParam` because the invoker would, supposedly, be able to read method argument names and pick URL parameter names accordingly; in Java that's suprisingly hard to do since the reflection API does not expose method argument names.\n\nFor example:\n\n```java\npublic interface BookService {\n\n\t@PostMapping(value = \"books\")\n\tvoid saveBook(@RequestBody Book book);\n\n}\n...\n\nbookService.saveBook(book);\n```\n\nwill result in this JSON being posted to ```/books```:\n\n```javascript\n{\n\t\"name\":\"Some Book Title\",\n\t\"author\":\"John Doe\",\n\t\"genres\":[\"technology\",\"educational\"],\n\t\"availability\":{\n\t\t\t\"available\":true,\n\t\t\t\"itemsInStock\":4\n\t\t\t}\n}\t\t\t\n```\n\nUsing multiple arguments:\n\n```java\npublic interface BookService {\n\n    @PostMapping(value=\"books\")\n    void saveBook(@RequestBody @RequestParam(\"book\") Book book, @RequestBody @RequestParam(\"availability\") availability);\n\n}\n\n...\n\nbookService.saveBook(book, availability);\n```\n\nwill result in this JSON being posted to ```/books```:\n\n```javascript\n{\n\t\"book\":{\n\t\t\"name\":\"Some Book Title\",\n\t\t\"author\":\"John Doe\",\n\t\t\"genres\":[\"technology\",\"educational\"]\n\t},\n\t\"availability\":{\n\t\t\t\"available\":true,\n\t\t\t\"itemsInStock\":4\n\t\t\t}\n}\t\t\t\n```\n\n\n#### What does @PathVariable do?\n\nSome REST services incorporate parameters in the URL path rather than URL parameters, i.e.: ```example.com/service/findBooks/isbn/1234``` as opposed to ```example.com/service/findBooks?isbn=1234````\n\n`@PathVariable` is specified together with a `@RequestParam` and indicates the the method argument is not to be sent as a URL parameter. Note that you need to specify a matching placeholder with `@RequestMapping`:\n\n```java\n\npublic interface BookService {\n\n\t@GetMapping(\"volumes/{id}\")\n\tItem findBookById(@PathVariable(\"id\") String id);\n}\n```\n\nor jax-rs:\n\n```java\npublic interface BookService {\n\n    @Path(\"/volumes/{id}\")\n    Item findBookById(@PathParam(\"id\") String id);\n}\n```\n\nThe ```{id}``` notation in `@RequestMapping` must match the one specified in `@PathVariable`\n\n\n#### How do I post a JSON object to a remote service?\n\nSee the section earlier in this document about posting. In short: if you want to post just a single object, then a JSON object is posted to the remote service where fields have the name of member variables (this applies recursively for objects within objects).\n\n```java\npublic interface BankService {\n\n\t@PostMapping(value = \"verify\")\n\tBoolean checkAccount(@RequestBody Account account);\n\n}\n```\n\nor jax-rs:\n\n```java\npublic interface BookService {\n\n\t@POST\n\t@Path(\"/verify\")\n\tBoolean checkAccount(@BeanParam Account account);\n\n}\n```\n\nMultiple objects can be posted through multiple method arguments, also including a ```@RequestParam``` mapping so that the invoker knows under which field names to place the generated JSON objects:\n\n```java\npublic interface BankService {\n\n\t@PostMapping(value = \"transfer\")\n\tAccount transfer(@RequestBody @RequestParam(\"fromAccount\") Account fromAccount, @RequestBody @RequestParam(\"actor\") Customer actor,\n\t\t\t@RequestBody @RequestParam(\"toAccount\") Account toAccount, @RequestBody @RequestParam(\"amount\") int amount,\n\t\t\t@RequestParam(\"sendConfirmationSms\") boolean sendConfirmationSms);\n\n}\n```\n\nor jax-rs:\n\n```java\npublic interface BankService {\n\n\t@POST\n\t@Path(\"/transfer\")\n\tAccount transfer(@BeanParam @QueryParam(\"fromAccount\") Account fromAccount, @BeanParam @QueryParam(\"actor\") Customer actor,\n\t\t\t@BeanParam @QueryParam(\"toAccount\") Account toAccount, @BeanParam @QueryParam(\"amount\") int amount,\n\t\t\t@QueryParam(\"sendConfirmationSms\") boolean sendConfirmationSms);\n\n}\n```\n\n#### The remote service requires messages to be submitted as multipart form posts...\n\n... for example Twitter https://dev.twitter.com/docs/api/1.1/post/statuses/update_with_media\n\nUse ```@RequestPart``` instead of ```@RequestBody``` :\n\n```java\n\t@PostMapping(value = \"join-accounts\")\n\tAccount joinAccounts(@RequestPart @RequestParam(\"account1\") Account account1, @RequestPart @RequestParam(\"account2\") Account account2);\n```\n\nor the jax-rs way:\n\n```java\n\t@POST\n\t@Path(\"/join-accounts\")\n\tAccount joinAccounts(@FormParam(\"\") @QueryParam(\"account1\") Account account1, @FormParam(\"\") @QueryParam(\"account2\") Account account2);\n```\n\n#### Dependencies?\n\nThe maven pom will pull in dependencies required for the spring mapper's basic features to work. `pom.xml` declares more dependencies for advanced features as `optional` which can be pulled into the project by re-declaring them in the project's `pom.xml`.\n\nJAX-RS support:\n\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003ejavax.ws.rs\u003c/groupId\u003e\n\t\u003cartifactId\u003ejavax.ws.rs-api\u003c/artifactId\u003e\n\t\u003cversion\u003e2.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nIf you use the logging interceptor then you'll also need some logging implementation for commons logging, ie. log4j:\n\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003elog4j\u003c/groupId\u003e\n\t\u003cartifactId\u003elog4j\u003c/artifactId\u003e\n\t\u003cversion\u003e1.2.17\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nOpaque proxies require cglib:\n\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003ecglib\u003c/groupId\u003e\n\t\u003cartifactId\u003ecglib\u003c/artifactId\u003e\n\t\u003cversion\u003e3.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n#### Is the spring-rest-invoker a JAX-RS implementation?\n\nYes, since `0.0.6-SNAPSHOT`. See the introduction.\n\n#### How do I log the entire HTTP communication with the remote service?\n\nYou need to provide your own RestTemplate, have a look at this http://stackoverflow.com/a/22620168/3194801 which enables logging. If you want to use the logging interceptor that comes with this library, then have a look at the configuration example in the unit tests: https://github.com/ggeorgovassilis/spring-rest-invoker/blob/master/spring-rest-invoker/src/test/resources/test-context-googlebooks-spring.xml\n\nAlso enable logging in your log4j configuration:\n\n```properties\nlog4j.logger.com.github.ggeorgovassilis.springjsonmapper.Request=DEBUG\nlog4j.logger.com.github.ggeorgovassilis.springjsonmapper.Response=DEBUG\n```\n\n#### I need to modify the outgoing HTTP request / I need to supply a client certificate / I need to validate a server certificate\n\nAgain the solution is to provide your own RestTemplate, see the previous section.\n\n#### I need to parametrise the mapping URL depending on the execution environment\n\nJust use property place holders in the URL, i.e.:\n\n```java\n@PostMapping(value = \"${serverIp}/join-accounts\")\nAccount joinAccounts(@RequestPart @RequestParam(\"account1\") Account account1, @RequestPart @RequestParam(\"account2\") Account account2);\n```\n\nWhenever the ```joinAccounts``` method is invoked, the ```serverIp``` property will be looked up in the application context and replaced by its current value. Note that this mechanism works only for values of the ```@RequestMapping``` and ```@Path``` annotations.\n\n#### Where can I find more examples?\n\nHave a look at mapping declarations for the unit test: [https://github.com/ggeorgovassilis/spring-rest-invoker/tree/master/src/test/java/com/github/ggeorgovassilis/springjsonmapper/services](https://github.com/ggeorgovassilis/spring-rest-invoker/tree/master/src/test/java/com/github/ggeorgovassilis/springjsonmapper/services)\n\n#### I need proxies to extend a specific class\n\nSince 1.0.RC it's possible to generate opaque proxies with cglib instead of the default dynamic proxies. Opaque proxies extend a concrete class and implement the REST mapping interface. In order to do so, specify a ```ProxyFactory``` instance, e.g.:\n\n```xml\n\u003cbean id=\"BookService_OpaqueProxy\" class=\"com.github.ggeorgovassilis.springjsonmapper.spring.SpringRestInvokerProxyFactoryBean\"\u003e\n\t\t\u003cproperty name=\"baseUrl\" value=\"https://www.googleapis.com/books/v1\" /\u003e\n\t\t\u003cproperty name=\"remoteServiceInterfaceClass\"\n\t\t\tvalue=\"com.github.ggeorgovassilis.springjsonmapper.services.spring.BookServiceSpring\" /\u003e\n\t\t\u003cproperty name=\"proxyFactory\"\u003e\n\t\t\t\u003cbean\n\t\t\t\tclass=\"com.github.ggeorgovassilis.springjsonmapper.utils.CglibProxyFactory\"\u003e\n\t\t\t\t\u003cproperty name=\"proxyTargetClass\"\n\t\t\t\t\tvalue=\"com.github.ggeorgovassilis.springjsonmapper.support.BaseProxyClass\" /\u003e\n\t\t\t\u003c/bean\u003e\n\t\t\u003c/property\u003e\n\u003c/bean\u003e\n```\n\n\n#### I specified some (other) annotations on the mapping interface but they are missing on the service proxy\n\nSymptoms: you specified more annotations on the mapping interface like ```@Transactional``` or ```@Valid``` but they don't seem to work on the remote service proxies. The code that is looking for annotations doesn't know how to deal with dynamic proxies properly. Either fix that or use opaque proxies; see \"I need proxies to extend a specific class\".\n\n#### Are there any alternatives?\n\nHave a look at RESTEasy http://resteasy.jboss.org/\n\n### How do I build from source code?\n\n```git clone https://github.com/ggeorgovassilis/spring-rest-invoker```\n\n```mvn clean install jxr:jxr pmd:pmd pmd:cpd surefire-report:report site```\n\nor without the fancies:\n\n```mvn clean install -DskipTests=true```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fggeorgovassilis%2Fspring-rest-invoker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fggeorgovassilis%2Fspring-rest-invoker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fggeorgovassilis%2Fspring-rest-invoker/lists"}