Quiet service interface with knitwear

Can I create a leisure service with an interface and an implementation class? and all JAX-RS imports go into the interface? I am using jersey2.4 and jetty8.1.

here is my interface:

MyService.java

package foo.bar; @Path("/abc") public interface MyService { @GET @JSONP @Path("/method/{id}") public MyResponse getStuff(@PathParam("id") Integer id); } 

MyServiceImpl.java

 package foo.bar.impl; public class MyServiceImpl implements MyService { public MyServiceImpl() {} @Override public MyResponse getStuff(Integer id) { // do stuff return MyResponse; } } 

here is my web.xml:

 <servlet> <servlet-name>Scivantage REST Service</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>foo.bar</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> 

I registered this service provider package (foo.bar), but it complains about this: javax.servlet.ServletException: MultiException has 1 exception. This is: | 1. java.lang.NoSuchMethodException: Could not find a suitable constructor in class foo.bar.MyService. |

When I tried with the implementation class package (foo.bar.impl), it complains about this: I get HTTP ERROR 404; doing nothing; no exceptions on the console

When I tried both, he complains the same as above:

javax.servlet.ServletException: MultiException has 1 exception. This is: | 1. java.lang.NoSuchMethodException: Could not find a suitable constructor in class foo.bar.MyService. |

You can help? What am I doing wrong?

+3
source share
5 answers

Although this is a question posted a year ago, here is a solution I came across after several tests (I work with berth 9 and jersey 2.13): instead of annotating the interface (with @Path("/abc") ), try adding a comment to the class instead implementation. I think this makes sense since the interface is "abstract" and should not be tied to physical paths. Thus, the interface can be reused in different ways.

+3
source

If you want to use interfaces with JAX-RS annotation, you can no longer scan the package using web.xml

 <param-name>jersey.config.server.provider.packages</param-name> <param-value>XXX</param-value> 

You need to manually bind your interface to the implementation of your resource

 bind(YourResource.class).to(YourResourceImpl.class); 

The reason for this:

For performance reasons, we decided that when scanning the interfaces would be ignored. We also found that Jersey will not try to create interfaces.

https://java.net/jira/browse/JERSEY-1004

+1
source

I struggled with the problem "Could not find a suitable constructor." I wanted to put all my annotations (including @Path) on my interfaces. I was able to get it working by managing the life cycle of resources on my own, rather than creating a jersey for them.

For example, if you have YourImplementation that implements YourRestInterface , you would do something similar to register an implementation instance with Jersey:

 public class RestConfig extends ResourceConfig { @Inject public RestConfig(ServiceLocator locator) { super(); DynamicConfiguration c = Injections.getConfiguration(locator); Object implInstance = new YourImplementation(); ServiceBindingBuilder<Object> bb = Injections.newFactoryBinder(new BeanFactory(locator, implInstance)); // tell Jersey to use the factory below to get an instance of YourRestInterface.class bb.to(YourRestInterface.class); Injections.addBinding(bb, c); c.commit(); } private static class BeanFactory implements Factory<Object> { private ServiceLocator locator; private Object bean; BeanFactory(ServiceLocator locator, Object bean) { this.locator = locator; this.bean = bean; } @Override public Object provide() { // have Jersey inject things annotated with @Context locator.inject(bean); return bean; } @Override public void dispose(Object instance) { } } } 
0
source

There is such a constructor in the ResourceConfig class

 ResourceConfig(Class<?>... classes) 

The constructor creates a new resource configuration initialized with the specified set of resource / provider classes.
This way you can extend ResourceConfig to register an implementation class.

 public class RestConfig extends ResourceConfig { public RestConfig() { // register the implementation class super(MyServiceImpl.class); } } 

Then configure web.xml .

 <servlet> <servlet-name>Scivantage REST Service</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <!-- the path of RestConfig --> <param-value>foo.bar.RestConfig</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> 

But the easiest way is to register the implementation class in web.xml .

 <servlet> <servlet-name>Scivantage REST Service</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.classnames</param-name> <!-- the path of implementation class --> <param-value>foo.bar.impl.MyServiceImpl</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> 
0
source

Yes, you can use the interface for annotation. In our application, we implemented this way. The following quote is from the Jersy spec.

JAX-RS annotations MAY be used for methods and method parameters in a super-class or implemented interface. Such annotations are inherited by the corresponding subclass or method of the implementation class if this method and its parameters do not have JAX-RS own annotations. Superclass annotations take precedence over implemented interfaces. If a subclass or implementation method has any JAX-RS annotations, then all annotations to the super class or interface method are ignored

I think in your case the error is that you might have missed the mapping, please check. <servlet-mapping> <servlet-name>api</servlet-name> <url-pattern>/api/*</url-pattern> </servlet-mapping>

-1
source

Source: https://habr.com/ru/post/1260556/


All Articles