Dependency of one class on three interfaces Guice - java

I have the following application class which uses a server to run its logic
Implementation of the application class is as follows:
package edu.umd.fcmd.guice.application;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class WebApplication {
private WebServer server;
public void run() {
System.out.println("starting web application...");
Injector injector = Guice.createInjector(new WebGuiceModule());
server = injector.getInstance(WebServer.class);
server.run();
System.out.println("web application finished.");
}
public static void main(String[] args) {
WebApplication app = new WebApplication();
app.run();
}
}
The server class is as follows which depends on three interfaces:
public class WebServer{
private final Frontend frontend;
private final Middleware middleware;
private final Persistance persistance;
#Inject
public WebServer(#Named("front")Frontend frontend, #Named("middle")Middleware middleware, #Named("pers")Persistance persistance) {
this.frontend = frontend;
this.middleware = middleware;
this.persistance = persistance;
}
public String getType() {
return "WebServer";
}
public boolean run() {
System.out.println("running " + this.getType());
Injector injector = Guice.createInjector();
Frontend frontend = injector.getInstance(Frontend.class);
frontend.run();
Middleware middleware = injector.getInstance(Middleware.class);
middleware.run();
Persistance persistance = injector.getInstance(Persistance.class);
persistance.run();
return true;
}
}
My webguicemodule is as follows:
public class WebGuiceModule extends AbstractModule{
#Override
protected void configure(){
bind(WebServer.class).annotatedWith(Names.named("front")).to(FrontEnd.class);
bind(WebServer.class).annotatedWith(Names.named("middle")).to(Middleware.class);
bind(WebServer.class).annotatedWith(Names.named("pers")).to(Persistance.class);
}
}
I am not sure why my module is not working properly. It is still in errors when I am writing the bind statements. Could not figure out why
I am receiving the following errors:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The method to(Class<? extends WebServer>) in the type LinkedBindingBuilder<WebServer> is not applicable for the arguments (Class<FrontEnd>)
FrontEnd cannot be resolved to a type
The method to(Class<? extends WebServer>) in the type LinkedBindingBuilder<WebServer> is not applicable for the arguments (Class<Middleware>)
Middleware cannot be resolved to a type
The method to(Class<? extends WebServer>) in the type LinkedBindingBuilder<WebServer> is not applicable for the arguments (Class<Persistance>)
Persistance cannot be resolved to a type

You are not using bind() correctly. You've configured WebGuiceModule such that FrontEnd, Middleware, and Persistance are subclasses of WebServer. However, the compiler errors indicate that is not the case.
You just need to say:
bind(FrontEnd.class);
bind(Middleware.class);
bind(Persistance.class);
Then when you ask the injector for an instance of WebServer, it will know how to create the objects that it needs to pass into the constructor.
WebServer server = injector.getInstance(WebServer.class);
In this case, you don't need #Named. That is for a case like this:
public class Foo {
#Inject
public Foo(#Named("bar") Jar bar, #Named("tar") Jar tar) {
}
}
public interface Jar {}
public class Bar extends Jar {}
public class Tar extends Jar {}
Then in a module...
bind(Jar.class).annotatedWith(Names.named("bar")).to(Bar.class);
bind(Jar.class).annotatedWith(Names.named("tar")).to(Tar.class);
The "name" disambiguates which implementation of Jar to create and inject. Otherwise it wouldn't know, and it would error.

Thank you #JeremyHeiler. This Frontend interface happens to be in a different package. Now, Frontend is dependent on an interface called authentication. When I tried implementing it with the similar code as that of the webserver, I am getting errors. The code I wrote was the following:
package edu.umd.fcmd.guice.interfaces;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import edu.umd.fcmd.guice.application.WebServer;
import edu.umd.fcmd.guice.interfaces.Authentication;
public interface Frontend{
private final Authentication authentication;
#Inject
public interface(Authentication authentication) {
System.out.println("5");
this.authentication = authentication;
}
public static String getType(){
return "Frontend";
}
public default boolean run(){
System.out.println("in frontend");
authentication.run();
return true;
}
}
Errors are the following:
Multiple markers at this line
- Duplicate field Frontend.authentication
- Illegal modifier for the interface field Frontend.authentication; only public, static & final are
permitted
Syntax error on token "interface", Identifier expected
The static field Frontend.authentication should be accessed in a static way
I have tried searching a lot on the internet but could not find figure out. I guess the problem is having files in different packages. If you could please let me know.

Related

Is it possible to have an ObjectProvider providing objects from other packages?

Initial situation
I'm currently building an API with Spring using the library PipelinR, which is inspired by the famous NuGet package MediatR. I've created multiple packages within this application to isolate the java classes. The entrypoint of the API is in the package com.example.project.WebApi. The configuration file for the pipeline is also located here.
#Configuration
public class PipelinrConfiguration {
#Bean
Pipeline pipeline(ObjectProvider<Command.Handler> commandHandlers, ObjectProvider<Notification.Handler> notificationHandlers, ObjectProvider<Command.Middleware> middlewares) {
return new Pipelinr()
.with(commandHandlers::stream)
.with(notificationHandlers::stream)
.with(middlewares::orderedStream);
}
}
Anyways all the commands and command handlers are in different packages, like com.example.project.ApplicationService.CreateSomethingCommand.
com.example.project.ApplicationService.CreateSomething/
CreateSomethingCommand.java
CreateSomethingCommandHandler.java
Does anybody knows how I could provide these classes in my PipelinrConfiguration.java file, so that the ObjectProvider is able to find those.
I highly appreciate any kind of help, cheers!
Edit: #001
Yes, the beans are annotated with #Component.
CreateSomethingCommand.java
public class CreateSomethingCommand implements Command<Voidy> {
public String host;
public CreateSomethingCommand() {
}
public CreateSomethingCommand(String host) {
this();
this.host = host;
}
}
CreateSomethingCommandHandler.java
#Component
public class CreateSomethingCommandHandler implements Command.Handler<CreateSomethingCommand, Voidy> {
#Override
public Voidy handle(CreateSomethingCommand command) {
System.out.println("Command recieved by " + command.host);
return null;
}
}
#Configuration
#ComponentScan(basePackages = {"package1”, "package2"})
public class PipelinrConfiguration {
// attention here you have to declare three different beans of type ObjectProvider otherwise it will inject by type
#Bean
Pipeline pipeline(#Qualifier(“bean1”) ObjectProvider<Command.Handler> commandHandlers, #Qualifier(“bean2”) ObjectProvider<Notification.Handler> notificationHandlers, #Qualifier(“bean3”) ObjectProvider<Command.Middleware> middlewares) {
return new Pipelinr()
.with(commandHandlers::stream)
.with(notificationHandlers::stream)
.with(middlewares::orderedStream);
}
}

Accessing main class from Jersey listener without the main class being a singleton object

I often use Jersey simple server as a webservice in my Java applications. Whenever I do this I only seem to be able to fetch properties from my application (main class) if it is setup as a singleton. So, I only seem to be able to fetch the information with MainClass.getInstance().
I know I can make the Jersey listener some sort of singleton in Jersey but this only means that the listener object will be instantiated once within Jersey in stead of for every single request: The listener is not a real singleton because it still needs a public constructor.
Is there a way to access my application class without it being a singleton object itself?
Here is the relevant code:
public class JerseyService {
private MainClass mainClass;
private int port = 8080;
private DefaultResourceConfig config;
private Closeable jerseyServer;
public JerseyService() {
config = new DefaultResourceConfig(JerseyListener.class); // Attach the listener (resource) to the Jersey server
jerseyServer = SimpleServerFactory.create("http://0.0.0.0:" + jerseyPort, config);
}
public String getData() {
return "somedata";
}
}
#Path("/")
public class JerseyListener {
#Path("getData")
#GET
#Produces("application/json")
public Response getData() {
// How can i call getData() from JerseyService
// without JerseyService being a singleton??
return Response.status(Response.Status.OK).entity("{<jsondata>}").build();
}
}

Why Guice prevents from binding to Provider?

Recently, when I played around with Google Guice I was trying to do something like this:
#Override
protected void configure() {
...
bind(Provider.class).to(ViewFactory.class);
...
}
Where ViewFactory was:
public class ViewFactory implements Provider<SomeType> {...}
Of course, Guice didn't let me do that returing error:
1) Binding to Provider is not allowed.
{stacktrace}
What is the reason why it is not possible to bind to provider?
I guess it is because Provider interface is very special to Guice. In fact, all its internal machinery is implemented in term of providers.
Moreover, this could create ambiguities. If bindings to providers were possible:
bind(SomeClass.class).to(SomeClassImpl1.class);
bind(new TypeLiteral<Provider<SomeClass>>() {}).to(() -> new SomeClassImpl2());
then what should Guice inject here?
#Inject
OtherClass(Provider<SomeClass> someClassProvider) { ... }
Should it be a provider which returns SomeClassImpl1 (because of the first binding; remember, direct injections and provider injections are interchangeable in Guice) or should it be a provider which returns SomeClassImpl2 (because of the second binding)?
It really is redundant. Because you can inject SomeClass or Provider<SomeClass> regardless of the actual binding, you can bind the class itself to its provider:
bind(SomeClass.class).toProvider(() -> new SomeClassImpl());
// Either of the following will work
#Inject
OtherClass1(Provider<SomeClass> someClassProvider) { ... }
#Inject
OtherClass2(SomeClass someClass) { ... }
Provider is a special case. Guice does a lot of things behind the scenes with Provider, so they just ban binding to the Provider class entirely. One example is with scoping: your custom Provider might call new every single time, but if you create the provider in the Singleton scope, that should not happen. So Guice doesn't actually inject your provider, it injects a wrapped version. Things like that is why they ban binding to Provider.class directly. Here's a code example:
import com.google.inject.*;
import com.google.inject.name.*;
public class ProviderBindExample {
public static class ProvModule extends AbstractModule {
#Override
protected void configure() {
bind(Foo.class).toProvider(FooProvider.class);
bind(Foo.class).annotatedWith(Names.named("singleton"))
.toProvider(FooProvider.class)
.in(Singleton.class);
}
}
public static interface Foo { }
public static class FooProvider implements Provider<Foo> {
#Override
public Foo get() {
return new Foo() {};
}
}
public static class SomeClass {
#Inject public Provider<Foo> provider;
#Inject #Named("singleton") public Provider<Foo> singletonProvider;
}
public static void main(String... args) {
Injector inj = Guice.createInjector(new ProvModule());
SomeClass s = inj.getInstance(SomeClass.class);
System.out.println("Provider class = " + s.provider.getClass());
System.out.println("Singleton provider class = " + s.singletonProvider.getClass());
Foo first = s.provider.get();
Foo second = s.provider.get();
System.out.printf("regular scope: objects are %s%n", first == second ? "the same" : "different");
first = s.singletonProvider.get();
second = s.singletonProvider.get();
System.out.printf("singleton scope: objects are %s%n", first == second ? "the same" : "different");
}
}
Output:
Provider class = class com.google.inject.internal.InjectorImpl$4
Singleton provider class = class com.google.inject.internal.InjectorImpl$4
regular scope: objects are different
singleton scope: objects are the same

jax-rs and server name

I am still working on a jax-rs server, and I faced some new problems recently. I do not understand where I define the name of my webserver. I searched everything in my workspace, but couldn't find anything.
Let's roll out the problem a bit further:
I always reach my server's #GET method via http://XXXXXX.XXXXX.XXX-XXXXXXX.de/android/
This is the structure of my server class:
#Path("/users")
public class UserResource {
Connection dbconn = null;
public UserResource() {
userIds = new ArrayList<Integer>();
userIds.add(1);
userIds.add(2);
userIds.add(3);
}
#GET
#Path("/login/{id}")
#Consumes("application/xml")
public StreamingOutput getTests(#PathParam("id") int id, InputStream is) {
return new StreamingOutput() {
public void write(OutputStream outputStream) throws IOException,
WebApplicationException {
getTests(outputStream);
}
};
}
As you see, the path of my class is "/users", and the path of the #GET method is "/login/1" (for example id = 1). Now I tried to call the method via
http://XXXXXX.XXXXX.XXX-XXXXXXX.de/android/users/login/1
But this does not work. I get an error (unknown source). And my error.log says that it couldn't find the resource at
http://XXXXXX.XXXXX.XXX-XXXXXXX.de/users/users/login/1
My 1st question: Where does the double "/users" come from? I have no idea. When I leave away the "/users" in my request url, there will be only 1 "/users" in the error.log, but still the resource is not found.
And there is another thing I did not find out yet: How do I change the name of my service? Atm, it's "android", but how could I change this? I searched my whole workspace, found "android" in my pom.xml, but when i change it to, let's say "testandroid", upload everything, build and run the server, the name is still android. No idea why this is the case.
Thx for your help guys!
EDIT:
This is my "main" class:
package com.restfully.services;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;
public class ServerApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> empty = new HashSet<Class<?>>();
public ServerApplication() {
singletons.add(new UserResource());
}
#Override
public Set<Class<?>> getClasses() {
return empty;
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
I am using Eclipse and Maven. The application runs on a jetty-server. If you could use any further information, let me know.
You can look in the following places
Pom.xml file for context root the following entry;
<configuration>
<context>yourWarName</context>
</configuration>
Using Netbeans check Run Category context path under project properties.
Context Path: /yourWarName
Have a look in your web.xml as well.
When using jax-rs you normally define a config class;
#ApplicationPath("resources")
public class RestConfig extends Application{
}
From there you define your other paths;
#Stateless
#Path("/login")
public class LoginResource
public Response login(Credentials credentials) {
Credentials result = this.loginService.login(credentials);
return Response.status(Response.Status.OK).entity(result).build();
}
The path to the following is: http://domain.com/MyApp/resources/login
where MyApp is the context root.
It might be that there is a path specified in config or root with the name users that you are getting the double users.

how to mock a class used in the code

public void sendMail() {
/* I have simplified the method for here */
Transport t;
t.send();
}
When I am writing unit test for this, since I don't want to actually send the mail, I want to mock the Transport class. Is it possible and if so, how to do it ?
'cglib' may fits.
Use ‘Enhancer' to proxy the 'Transport' class. In order not to actually sending the mail, you need pass into the 'Enhancer' a 'MethodInterceptor' which will not invoke the 'send()' method in super class.
Unless you really want to use mockito, you can quite easily handcraft your own test double.
What you can do is create an interface that knows how to send mail:
public interface TransportInterface {
public void send(Message msg);
}
Let the mail sending class use this interface to send the mail:
public class MailSender {
private TransportInterface transport;
public MailSender(TransportInterface transport) {
this.transport = transport;
}
public void sendMail(Message msg) {
/* This is the method from your question */
this.transport.send(msg);
}
}
In production you use an implemenation of TransportInterface that actually send the mail:
public class TransportAdapter implements TransportInterface {
private Transport transport; // Created elsewhere...
public void sendMail(Message msg) {
transport.send(msg);
}
}
And in your test code you can use a fake:
public class TransportFake implements TransportInterface {
public void sendMail(Message msg) {
// I don't send the mail!
}
}
(It's been a while since I coded java. Hope there are not too many errors. Also, you can probably do a better job naming the classes than I have.)
You can try to use Mockito library:
here is example code:
import org.mockito.Mock;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
public class YourTestClass{
#Mock
Transport t;
#Test
public void someTest(){
t = Mockito.mock(Transport .class);
Mockito.when(t.send()).thenReturn(true);
}
}
Here is a solution which works regardless of how the Transport t object is obtained:
#Test
public sendMail(
// Mocks all current and future Transport instances,
// including those belonging to subclasses (if any).
#Capturing final Transport t)
{
new SUT().sendMail();
// Verifies that the t.send() method was called:
new Verifications() {{ t.send(); }};
}
The mocking API used above is JMockit (which I develop).

Categories