0
@Path("/test")
public class MyClass {

  @GET
  public Response response() {
    // Generating some expensive object here.
  }

Right now I load the data into arrays etc inside the "response" function, but I want to do it before the query is even made. This way, I want to avoid reloading the data every time a a query is made. How do I achieve this?

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
Strukks
  • 45
  • 1
  • 8
  • can you explain more, your question is not clear ! – Sikorski May 12 '14 at 12:37
  • @Sikorski I have data in files which I want to read into a dictionary and then when a query is made I want to respond with the data I have in those files. Right now I make the dictionary etc inside the "response" function, so with every query the data is reloaded into the dictionary etc, I want to do this before, so it doesn't have to load the data into the dictionary etc every time a request is made. – Strukks May 12 '14 at 13:17
  • Why not just make the dictionary a member of MyClass, so you don't have to reload it every time? Although you should think carefully of the trade off. Your way allows the underlying data to change without having to restart the application, which may be a desirable trait. – Mikkel Løkke May 12 '14 at 13:42
  • @MikkelLøkke How would I do this? With "public static void main(String[] args)"? I made a static dictionary under the MyClass and then did the stuff in the void main method, but the response function said it didn't exist. The result I want to get is that the data is buffered before, but if someone makes a request to an item that isn't in the dictionary it tries to rebuffer the data. – Strukks May 12 '14 at 14:41
  • You should probably not use a static variable. A more robust solution would be to make "MyClass" a singleton (either a classic Singleton, or through your IoC container), and the either lazy instantiate it from the filesystem the first time you need it, or eager instantiate it, in your setup code (which would probably be a ContextListener. Alternatively you can turn the problem on it's head and use something like EHCache as a write-through or write-behind cache. and Cache the result after you retrieve it the first time, this will require the least amount of reengineering of your existing code. – Mikkel Løkke May 13 '14 at 07:44

1 Answers1

0

This depends on your framework. Are you using the reference implementation Jersey? Jersey comes bundled with HK2 automatically. Then you could add

@Path("/test")
public class MyClass {

  @Inject
  private MyState stateful;

  // here comes your code...
}

to your resource. Of course, you would still need to configure what to inject into this field. With HK2, you use an AbstractBinder for this purpose:

class MyBinder extends AbstractBinder {

    private final MyState stateful;

    public MyBinder (MyState stateful) {
        this.stateful = stateful;
    }

    @Override
    protected void configure() {
        bind(stateful).to(MyState.class);
    }
}

Finally, you need to add this binder on the application's setup. For this purpose, JAX-RS Application object can be queried for singletons. Simply add the required instance to the application such that it is returned by Application#getSingletons as here:

class MyJaxRSApplication extends Application {

  @Override
  public Set<Class<?>> getClasses() {
    return Collections.singletonSet(MyClass.class);
  }

  @Override
  public Set<Object> getSingletons() {
    return Collections.singletonSet(new MyBinder(new MyStateImpl()));
  }
}

You can now run your application where MyStateImpl is always injected into MyClass.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • Can you ELI5? Or give me an example using my sample code? Yes I'm using jersey. – Strukks May 12 '14 at 13:18
  • 2
    If you are 5, you are too young to write web services. I extended my examples a little bit but I won't write your entire application. – Rafael Winterhalter May 12 '14 at 13:29
  • You are welcome. I recommend you to read the documentation of Jersey, it is actually really good for at least these basic features. If your question is resolved, consider marking my answer as accepted. – Rafael Winterhalter May 12 '14 at 13:40
  • "@Before" is a different thing? It's not something I could do this with? – Strukks May 12 '14 at 14:19
  • `@Before` could be a lot of things. The code I posted would initialize a component at application start up. – Rafael Winterhalter May 12 '14 at 14:23
  • yes, that's exactly what I'm trying to do, but your code still seems a bit difficult, I'm kinda lost at the last part, about the application objects. – Strukks May 12 '14 at 14:26
  • You might be confused by the `Application` class. It is equivalent to the Jersey specific `ResourceConfig`. Look at this answer on how to register an `AbstractBinder`: http://stackoverflow.com/questions/16216759/dependency-injection-with-jersey-2-0/17133081#17133081 – Rafael Winterhalter May 12 '14 at 14:54
  • Is there really no easier way to do this? – Strukks May 12 '14 at 15:13
  • You could annotate your resource `MyClass` with `@Singleton` and do the setup logic in a non-argument constructor but this does not scale very well in the long run. – Rafael Winterhalter May 12 '14 at 15:42