Injecting an object that requires enum in Guice - java

I have an object to be injected that is defined as:
public class EnvironmentModule extends AbstractModule {
#Override
protected void configure() {
}
#Provides
#Singleton
private String getObject(final Client client) {
...
}
}
Client is an enum defined as :
#NoArgsConstructor(force = true)
public enum Client {
private String name;
Client(final String name) {
this.name = name;
}
public static Client identifyClient(final String clientName) {
}
}
This gives me an error-
Could not find a suitable constructor in Client. Classes must have either one (and only one) constructor annotated with #Inject or a zero-argument constructor that is not private
at Client.class(Client.java:5)
at EnvironmentModule.getObject(EnvironmentModule.java:35)
Please help. What has to be done.

The reason this is happening is because in your module you do not declare an instance of Client to be injected in the scope of the module, so it tries to create one with an empty constructor. This does not work because your enum has two constructors, and guice requires a single empty constructor. The solution to this to create a singleton of your client. I assume the code you omitted in Client looks like
public enum Client {
//I assume it works like this
NORMAL_CLIENT("whatever");
private String name;
Client(final String name) {
this.name = name;
}
public static Client identifyClient(final String clientName) {
return Arrays.stream(Client.values())
.filter(client -> clientName.equals(client.name))
.findAny()
//This is dangerous, throw an error if its not found
.get();
}
}
So we need to create a singleton in the environment module for the client. this would look like
public class EnvironmentModule extends AbstractModule {
#Override
protected void configure() {
super.configure();
}
#Provides
#Singleton
private Client getClient() {
return Client.identifyClient("whatever");
}
#Provides
#Singleton
private String doWhatever(final Client client) {
System.out.println("found client " + client);
return "cool it works";
}
}
invoking the module through
public class Main {
public static void main(String[] args) {
final var envInjector = Guice.createInjector(new EnvironmentModule());
final var client = envInjector.getInstance(Client.class);
final var doWhateverString = envInjector.getInstance(String.class);
System.out.println(doWhateverString);
System.out.println("found instance " + client);
}
}
we can see
found client NORMAL_CLIENT
cool it works
found instance NORMAL_CLIENT

Related

Using Guice Module class to setup entire JavaClient

Hello everyone I have this problem where I want to set up the entire Client setup inside a Guice module and then call it inside a clientSetup method in testing class.
What I am struggling with is how to abstract it even more.
Code I currently have:
JavaClient client;
public void clientSetup (param1, param2) {
final String var1;
Injector injector = createInjector(
new TestProviderModule()
};
var1 = injector.getInstance(Key.get(String.class, Names.named("var1Name")));
if (!value.equals("Dev")) {
System.setProperty(var1);
}
final String var2 = String.format("%s.%s", param1, param2);
this.client = injector.getInstance(ClientFactory.class).getTestingClient(var2);
}
I also have a TestProviderModule class which looks like this:
public class TestingModuleProvider extends AbastractModule {
#Override
protected void configure() {
};
#Provides
#Singleton
#Named("var1name")
String getVar1 () {
method that compares var1 based on blah blah
return var1;
}
#Provides
#Singleton
ClientFactory getFactory () {
return new ClientFactory();
}
}
This is my ClientFactory class.
public class ClientFactory {
public GetJavaClient javaClientSetup (final string var2) {
return new ClientBuilder()
.remoteOf(GetJavaClient.class)
.withConfiguration(var2)
.newClient();
}
public GetInventoryJavaClient javaClientSetup (final string var2) {
return new ClientBuilder()
.remoteOf(GetInventoryJavaClient.class)
.withConfiguration(var2)
.newClient();
}
}
What I am trying to get is this where I have everything set up inside the Guice Module class and just inject it into the client. The reason I want that is because I have 3 different test suits and I do not want to duplicate the code but am not sure how to best extract everything.
JavaClient client;
public void clientSetup (param1, param2) {
Injector injector = createInjector(
new TestProviderModule()
};
this.client = injector.getInstance(ClientFactory.class).getTestingClient(var2);
}

how to create abstract factory to instantiate objects in java

I would like to create an abstract factory. here is what I tried.
//abstract class Worker
public abstract class Worker {
String phoneNumber;
String firstName;
String lastName;
String workerType;
String ifu;
String imageParth;
//....
public String getWorkerType() {
return workerType;
}
}
// Electrician class which extends worker
package worker.domain.worker;
public class Electrician extends Worker{
public Electrician() {}
public Electrician(String phoneNumber, String firstName, String lastName, String ifu, String workerType,
String imageParth) {
super(phoneNumber, firstName, lastName, ifu,workerType, imageParth);
}
public String getWorkerType() {
return "Electrician";
}
}
//Mason class
package worker.domaine.worker;
public class Mason extends Worker{
public Mason() {};
public Mason(String phoneNumber, String firstName, String lastName, String ifu,String workerType,
String imageParth) {
super(phoneNumber, firstName, lastName, ifu, workerType, imageParth);
}
String getworkerType() {
return "Mason";
}
}
// interface WorkerAbstractFactory
package worker.domaine.worker;
public interface WorkerAbstractFactory {
Worker createWorker(String typeWorker);
}
//
public class WorkerFactory implements WorkerAbstractFactory{
#Override
public Worker createWorker(String typeWorker) {
Worker worker = null;
if(worker != null) {
switch (typeWorker) {
case "Electrician":
Electrician electrician =new Electrician();
electrician = new Electrician (electrician.getPhoneNumber(), electrician.getFirstName(), electrician.getLastName(), electrician.getIfu(), electrician.getWorkerType(),electrician.getImageParth());
case "Mason":
Mason mason =new Mason();
mason = new Mason (mason.getPhoneNumber(), mason.getFirstName(), mason.getLastName(), mason.getIfu(), mason.getworkerType(),mason.getImageParth());
}}
//app class
public class WorkerFactoryProvider {
public static WorkerAbstractFactory getWorkerFactory(String workerCategory) {
//WorkerFactory workerFactory = new WorkerFactory();
WorkerFactory workerFactory = new WorkerFactory();
if (workerCategory != null) {
switch (workerCategory) {
case "Electrician":
Worker worker1 = workerFactory.createWorker("Electrician");
worker1.getWorkerType();
String a=worker1.getWorkerType();
System.out.println(a);
case "Mason":
Worker worker2 = workerFactory.createWorker("Mason");
worker2.getWorkerType();
String b=worker2.getWorkerType();
System.out.println(b);
}
}
return null;
}
do you think it could work like that? now, if I really want a concrete object, how could it be done? because I would like to write for example a method to calculate the pay of each worker according to type for example how could I use my abstract Factory in the method to return me each type.
You have a single class hierarchy of Worker types. To instantiate those you can just use a standalone factory class, you don't need an abstract factory here. For example this would be sufficient:
public class WorkerFactory {
public Worker createWorker(String workerType) {
switch (workerType) {
case "Electrician": return new Electrician();
case "Mason": return new Mason();
}
}
}
The abstract factory pattern is more elaborate, and allows injecting different concrete factories for related hierarchies of objects, so that the client doesn't need to be aware of the difference. For example you could have an abstract TransportationFactory:
interface Transportation {
void travelTo(String destination);
}
interface TransportationFactory {
Transportation simple();
Transportation luxurious();
}
And two concrete implementations (matching two different but similar class hierarchies):
class WaterTransportationFactory {
Transportation simple() {
return new Kayak();
}
Transportation luxurious() {
return new Yacht();
}
}
And:
class LandTransportationFactory {
Transportation simple() {
return new Bike();
}
Transportation luxurious() {
return new RaceCar();
}
}
The benefit of this pattern is that the client can be configured to use water or land transportation (or a new air transportation that is added later) without the need to undergo any changes:
class Client {
private TransportationFactory transportationFactory;
public Client(TransportationFactory transportationFactory) {
this.transportationFactory = transportationFactory;
}
public void travel(String destination) {
transportationFactory.simple().travelTo(destination);
}
public void travelInStyle(String destination) {
transportationFactory.luxurious().travelTo(destination);
}
}
EDIT: You could change the simple/luxurious methods to match the style of your example with the getWorkerType method. I prefer to avoid the conditional logic if possible and let the created classes determine their availability themselves. This decouples even further, allowing hierarchy members to be added with minimal code changes:
enum TransportationType {
SIMPLE, LUXURIOUS
}
interface Transportation {
void travelTo(String destination);
// allow the class to specify its own type
TransportationType getType();
}
// intermediate interface to distinguish Water from Land
interface WaterTransportation extends Transportation {
}
class Kayak implements WaterTransportation {
void travelTo(String destination) {
// splash splash
}
TransportationType getType() {
return TransportationType.SIMPLE;
}
}
class WaterTransportationFactory {
private WaterTransportation[] waterTransportations;
// Inject all available beans implementing WaterTransportation
// e.g. using Spring or some other dependency injection mechanism
public WaterTransportationFactory(WaterTransportation[] waterTransportations) {
this.waterTransportations = waterTransportations;
}
public Transportation create(TransportationType type) {
for(WaterTransportation waterTransportation : waterTransportations) {
if (waterTransportation.getType() == type) {
// we are returning the same instance every time
// this could be ok for singleton beans
// but if you really need a fresh instance you could use builders (see below)
return waterTransportation;
}
}
throw new IllegalArgumentException("No implementation for WaterTransportation type=" + type);
}
}
An alternative with builders:
KayakBuilder implements WaterTransportationBuilder {
KayakBuilder name(String name) { ... };
KayakBuilder weight(String weightInKg) { ... };
KayakBuilder year(String yearBuilt) { ... };
KayakBuilder speed(String averageSpeed) { ... };
Kayak build() { return kayak; }
}
For more on Builders see this full exposition of the Builder pattern
class WaterTransportationFactory {
private WaterTransportationBuilder[] builders;
// Inject all available WaterTransportationBuilders
// e.g. using Spring or some other dependency injection mechanism
public WaterTransportationFactory(WaterTransportationBuilder[] builders) {
this.builders = builders;
}
// extra arguments can be passed to build the instance
public Transportation create(TransportationType type, String name, int weightInKg, int yearBuilt, int averageSpeed) {
for(WaterTransportationBuilder builder: builders) {
if (builder.getType() == type) {
return builder
.name(name)
.weight(weightInKg)
.year(yearBuilt)
.speed(averageSpeed)
.build();
}
}
throw new IllegalArgumentException("No implementation for WaterTransportation type=" + type);
}
}

Spring custom Scope with timed refresh of beans

I am working within an environment that changes credentials every several minutes. In order for beans that implement clients who depend on these credentials to work, the beans need to be refreshed. I decided that a good approach for that would be implementing a custom scope for it.
After looking around a bit on the documentation I found that the main method for a scope to be implemented is the get method:
public class CyberArkScope implements Scope {
private Map<String, Pair<LocalDateTime, Object>> scopedObjects = new ConcurrentHashMap<>();
private Map<String, Runnable> destructionCallbacks = new ConcurrentHashMap<>();
private Integer scopeRefresh;
public CyberArkScope(Integer scopeRefresh) {
this.scopeRefresh = scopeRefresh;
}
#Override
public Object get(String name, ObjectFactory<?> objectFactory) {
if (!scopedObjects.containsKey(name) || scopedObjects.get(name).getKey()
.isBefore(LocalDateTime.now().minusMinutes(scopeRefresh))) {
scopedObjects.put(name, Pair.of(LocalDateTime.now(), objectFactory.getObject()));
}
return scopedObjects.get(name).getValue();
}
#Override
public Object remove(String name) {
destructionCallbacks.remove(name);
return scopedObjects.remove(name);
}
#Override
public void registerDestructionCallback(String name, Runnable runnable) {
destructionCallbacks.put(name, runnable);
}
#Override
public Object resolveContextualObject(String name) {
return null;
}
#Override
public String getConversationId() {
return "CyberArk";
}
}
#Configuration
#Import(CyberArkScopeConfig.class)
public class TestConfig {
#Bean
#Scope(scopeName = "CyberArk")
public String dateString(){
return LocalDateTime.now().toString();
}
}
#RestController
public class HelloWorld {
#Autowired
private String dateString;
#RequestMapping("/")
public String index() {
return dateString;
}
}
When I debug this implemetation with a simple String scope autowired in a controller I see that the get method is only called once in the startup and never again. So this means that the bean is never again refreshed. Is there something wrong in this behaviour or is that how the get method is supposed to work?
It seems you need to also define the proxyMode which injects an AOP proxy instead of a static reference to a string. Note that the bean class cant be final. This solved it:
#Configuration
#Import(CyberArkScopeConfig.class)
public class TestConfig {
#Bean
#Scope(scopeName = "CyberArk", proxyMode=ScopedProxyMode.TARGET_CLASS)
public NonFinalString dateString(){
return new NonFinalString(LocalDateTime.now());
}
}

How to mock an object that is already being instantiated within the code of the class to be tested and write stubs for it?

The class I need to test will look somewhat similar to this. I am not writing the actual class here.
public class Client {
private String country;
private ConnectionImpl conn;
public Client (String country){
this.country = country;
}
private ConnectionImpl createConnection() {
SetConnectionImpl impl = new SetConnectionImpl() {
public String getFirstName() {
return "Some value";
}
public String getLastName() {
return "Some value";
}
public String getAddress() {
return "Some value";
}
public String getPhoneNumber() {
return "Some value";
}};
return new ConnectionImpl("", "", "", "", impl);
}
public String letsDoSomeWork(String requestObject) {
final ConnectionImpl impl = createConnection();
String letsHaveSomeResponse =
impl.methodTobeStubbed(requestObject);
return letsHaveSomeResponse;
}
}
Now the test class that I have written will look like this. I am using mockito to write stubs.
#Runwith(MockitoJunitRunner.class)
public class ClientTest {
#Mock
ConnectionImpl impl;
private Client client;
#Before()
public void initialize() {
client = new Client("India");
}
#Test
public void testLetsDoSomework_ShouldReturnString() {
String request = "request";
when(impl.methodTobeStubbed(request)).thenReturn("Response");
String letsHaveSomeResponse = client.letsDoSomeWork(request);
//Now I will make Assertions
}
}
Unfortunately this stubbing doesn't work and my assumption is that since the class to be tested is internally creating an "impl" object, the mock object that I am creating here is not being considered. So in the end the code is entering the "impl" class which it should not.
when(impl.methodTobeStubbed(request)).thenReturn("Response");
I made the test case to work. Here is what I did.
#RunWith(PowerMockRunner.class)
#PrepareForTest(Client.class)
public class ClientTest {
#Mock
ConnectionImpl impl;
private Client client;
#Before()
public void initialize() {
client = PowerMockito.spy(new Client("India"));
doReturn(impl).when(client, "createConnection");
}
#Test
public void testLetsDoSomework_ShouldReturnString() {
String request = "request";
when(impl.methodTobeStubbed(request)).thenReturn("Response");
String letsHaveSomeResponse = client.letsDoSomeWork(request);
//Now I will make Assertions
}
You can make createConnection method return your mocked connection.
First, change the method to protected:
protected ConnectionImpl createConnection() {
.... // same code
}
If the method is private, you can't mock it in your test.
Then, in your test, make a spy with the Client object, using Mockito.spy method:
#Before()
public void initialize() {
client = Mockito.spy(new Client("India"));
// letsDoSomeWork method will be called (instead of a mocked version)
when(client.letsDoSomeWork(anyString())).thenCallRealMethod();
// createConnection returns your mocked impl object (it doesn't compile if createConnection method is private)
when(client.createConnection()).thenReturn(impl);
}
Then, when you call letsDoSomeWork, it will call the real method in Client class. So, createConnection will be called - and as it's mocked, it will return the mocked impl object.
Note: make sure that ClientTest class is in the same package of Client class, in order to make createConnection visible by the test (even if they are in different source folders - like src/main and src/test, assuming you're using maven or similar - the package name must be the same)
Another way of doing it is to make a setter method for the connection:
public class Client {
private String country;
private ConnectionImpl conn;
public Client(String country) {
this.country = country;
}
// create setter method for connection
public void setConn(ConnectionImpl conn) {
this.conn = conn;
}
public String letsDoSomeWork(String requestObject) {
// no need to createConnection
String letsHaveSomeResponse =
this.conn.methodTobeStubbed(requestObject);
return letsHaveSomeResponse;
}
}
So your test will be like:
#RunWith(MockitoJUnitRunner.class)
public class ClientTest {
#Mock
MyConn impl;
private Client client;
#Before
public void initialize() {
client = new Client("India");
client.setConn(impl);
}
#Test
public void testLetsDoSomework_ShouldReturnString() {
String request = "request";
when(impl.methodTobeStubbed(request)).thenReturn("Response");
String letsHaveSomeResponse = client.letsDoSomeWork(request);
// do assertions
}
}
Or even better, make a constructor that receives the connection:
public Client(String country, ConnectionImpl conn) {
this.country = country;
this.conn = conn;
}
And in the test class:
#Before
public void initialize() {
client = new Client("India", impl);
}

How to provide your services via #Context in Neo4j unmanaged extension

I have Neo4j unmanaged extension. I want some services to be created as singletons and be available via #Context in my resources.
Something like this:
#Path("/example")
public class ExampleResource {
public ExampleResource(#Context CostlyService costlyService) { // <<---
// use it here
}
}
How this can be achieved?
Neo4j has PluginLifecycle interface that give us possibility to hook into Neo4j server lifecycle and provide our own services for injection blog post.
So, we have service. Let's take this one as example:
public interface CostlyService {
}
public class CostlyServiceImpl implements CostlyService {
public CostlyService() {
// a LOT of work done here
}
//...
}
Now we need to make our own PluginLifecycle implementation:
public class ExamplePluginLifecycle implements PluginLifecycle {
#Override
public Collection<Injectable<?>> start(GraphDatabaseService graphDatabaseService,
Configuration config) {
final List<Injectable<?>> injectables = new ArrayList<>();
return injectables;
}
#Override
public void stop() {
}
}
As you see, injectable list is empty for now. We will add our service there soon.
Important: you must register your PluginLifecycle implementation, so it will be available via SPI:
// file: META-INF/services/org.neo4j.server.plugins.PluginLifecycle
my.company.extension.ExamplePluginLifecycle
This will make your PluginLifecycle discoverable by Neo4j server.
Now we need to create actual injectable. Let's write implementation for Injectable interface:
public final class TypedInjectable<T> implements Injectable<T> {
private final T value;
private final Class<T> type;
private TypedInjectable(final T value, final Class<T> type) {
this.value = value;
this.type = type;
}
public static <T> TypedInjectable<T> injectable(final T value, final Class<T> type) {
return new TypedInjectable<>(value, type);
}
#Override
public T getValue() {
return value;
}
#Override
public Class<T> getType() {
return type;
}
}
This will serve as simple container for our service. Usage:
import static my.company.extension.TypedInjectable.injectable;
injectable(new CostlyServiceImpl(), CostlyService.class);
Now we can add our injectable into PluginLifecycle.
#Override
public Collection<Injectable<?>> start(GraphDatabaseService graphDatabaseService,
Configuration config) {
final List<Injectable<?>> injectables = new ArrayList<>();
injectables.add(injectable(new CostlyServiceImpl, CostlyService.class)); // <<---
return injectables;
}
After this change our CostlyService will be available for our resources via #Context:
#Path("/example")
public class ExampleResource {
public ExampleResource(#Context CostlyService costlyService) {
// use it here
}
// ...
}
Tip: keep your PluginLifecycle's in same package or in subpackage with your resources.

Categories