1

My rest application contains a service and I need to make this service to act like a singleton to save a state of the service.

a service:

@Path("/script")
public class ScriptEngineProvider {

private AtomicInteger idCounter;

public ScriptEngineProvider() {
    System.out.println("before AtomicInteger");
    idCounter = new AtomicInteger();
}

@POST
public Response executeScript( String x ) {
    idCounter.incrementAndGet();
    System.out.println("counter " + idCounter);
    ...

a client besides all other code has:

WebTarget webTarget = client.target("http://localhost:8080/NashornEngine/rest").path("script");

web.xml

<url-pattern>/rest/*</url-pattern>

With the above configuration the application works but with every request the variable idCounter creates so idCounter is allways 1.

Now I use next class to make the ScriptEngineProvider to be a singleton:

@ApplicationPath("/services")
public class NashornApplication extends Application {
    private Set<Object> singletons = new HashSet<Object>();
    public NashornApplication() {
        singletons.add(new ScriptEngineProvider());
    }
    @Override
    public Set<Object> getSingletons() {
        return singletons;
    }
}

The problem is that I get The requested resource is not available with request:

//path services was added
WebTarget webTarget = client.target("http://localhost:8080/NashornEngine/rest").path("services").path("script");

What is the problem with this config?

rozero
  • 149
  • 3
  • 15
  • the whole service doesn't have to be a singleton. Only idCounter needs to be static... – jHilscher Jan 03 '16 at 15:19
  • @jHilscher, let is `idCounter ` will be a static and how could that help if `ScriptEngineProvider ` is new with every request? – rozero Jan 03 '16 at 16:00

2 Answers2

2

try this:

@Singleton // this is the important line
@Path("/script")
public class ScriptEngineProvider {

private AtomicInteger idCounter;

public ScriptEngineProvider() {
    System.out.println("before AtomicInteger");
    idCounter = new AtomicInteger();
}

@POST
public Response executeScript( String x ) {
    idCounter.incrementAndGet();
    System.out.println("counter " + idCounter);
    ...
Panda TG Attwood
  • 1,468
  • 2
  • 16
  • 31
pL4Gu33
  • 2,045
  • 16
  • 38
1

@ApplicationPath effectively serves the same purpose as the url-mapping. But only one can be used. You use @ApplicationPath with an Application subclass when you don't want to use web.xml configuration. To go web.xml-less, you need to make sure of two things

  1. You are deploying to a 3.x servlet container.
  2. You have the dependency that supports the servlet pluggability. See more here

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>${jersey2.version}</version>
    </dependency>
    

It's also possible to use an Application subclass without the @ApplicationPath, which will then use the url-mapping to map the Jersey servlet. For example

<servlet>
    <servlet-name>MyApplication</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.pkg.YourApplication</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>MyApplication</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

Which ever way you choose, either the url-mapping path will be used, or the @ApplicationPath value will be used, but not both. So in your case, if you do with no web.xml configuration, the path would not include the /rest in the url-mapping. And if you go with the above web.xml configuration, then you should get rid of the @ApplicationPath on your Application subclass, that url you would use would with /rest, with no /services.

The reason you keep getting one is because

  1. The default behavior is to create a new resource class for every request
  2. Your Application subclass is not being used, and your web.xml configuration is being used, where you are package scanning.

Review the information from this post, and make the changes accordingly.

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • It works the only problem which is Eclipse makes Application class with erorr while annotation is missing `The Application Path should be configured with an @ApplicationPath annotation or in the web deployment descriptor.` even if web.xml configured. – rozero Jan 03 '16 at 16:13
  • Shouldn't be an error, but a warning. Same thing happens in Netbeans. If you really don't like the warning then go web.xml-less. See above for the requirements – Paul Samsotha Jan 03 '16 at 16:16
  • The other point is that app works even if annotation `@ApplicationPath("")` is present with all that web.xml stuff. – rozero Jan 03 '16 at 16:17
  • It'll work even you you add `@ApplicationPath('boomshakalaka")`. The annotation isn't being used. Your url-mapping is being used – Paul Samsotha Jan 03 '16 at 16:17