after I received a very good answer in my post about Guice injection in general, I wanted to know, if you could also help me with injection of EntityManagers in Guice.
I already read the article https://github.com/google/guice/wiki/JPA about Guice JPA. My code looks like this (I need the providers for my work):
Provider:
public class DatabaseControllerProvider implements Provider<DatabaseControllerInterface> {
private final Provider<EntityManager> entityManagerProvider;
#Inject
public DatabaseControllerProvider(final Provider<EntityManager> manager) {
this.entityManagerProvider = manager;
}
#Override
public DatabaseControllerInterface get() {
return new DatabaseControllerImpl(entityManagerProvider.get());
}
}
Constructor of DatabaseControllerImplementation:
public class DatabaseControllerImpl implements DatabaseControllerInterface {
private final EntityManager em;
#Inject
public DatabaseControllerImpl(final EntityManager manager) {
this.em = manager;
}
}
Top level I call this:
public LogInFront() {
final Injector injector = Guice.createInjector(new ModuleBinder(), new JpaPersistModule("ATVPersistence"));
final PersistService persistService = persistenceInjector.getInstance(PersistService.class);
persistService.start();
logInService = injector.getInstance(LogInServiceInterface.class);
}
to instantiate the JPAPersistService with my database.
I receive an error, that no Implementation for EntityManager was bound, but if I call
...
public LogInFront() {
final Injector injector = Guice.createInjector(new JpaPersistModule("ATVPersistence"));
final PersistService persistService = persistenceInjector.getInstance(PersistService.class);
persistService.start();
logInService = injector.getInstance(LogInServiceInterface.class);
}
The instantiation works correctly, database works fine, and everything is nice and easy.
So my guess is, that there's something wrong with my GuiceModule. As seen above, when I'm not calling the new ModuleBinder(), everything works just fine.
public class ModuleBinder extends AbstractModule {
#Override
protected void configure() {
bind(DatabaseControllerInterface.class).asEagerSingleton();
bind(AnalyzerInterface.class).asEagerSingleton();
bind(SystemAdministrationInterface.class).asEagerSingleton();
bind(LogInServiceInterface.class).asEagerSingleton();
}
}
-----------------------------EDIT-------------------------------------
Rewrote above section.
Tl;dr edition:
ModuleBinder messes up Injection of EntityManager -why?
---------------------------Found error-------------------------------
I feel kind of dumb, I found the error. When taking a look into the ModuleBinder you can see, that it binds everything as EagerSingleton, but obviously, the EntityManager does not exist yet (the PersistService is started after creating the Injector). I created a new post on this here: https://stackoverflow.com/questions/47181835/jpapersistencemodule-guice-injector
May it help other people!
Best regards,
JosefRucksack
I feel kind of dumb, I found the error. When taking a look into the ModuleBinder you can see, that it binds everything as EagerSingleton, but obviously, the EntityManager does not exist yet (the PersistService is started after creating the Injector).
Calling
final Injector injector = persistenceInjector.createChildInjector(new ModuleBinder());
Fixes everything. It creates a childInjector that knows everything the parent knows, therefore the PersistenceService is already started and you can inject the EntityManager into everything.
Related
I'm working in a project with Java EE 7 and I need to inject a javax.ejb.#Stateless bean into another. Both beans have a similar structure:
#Stateless
public class OperationRepository extends GenericRepository<Operation> {
#PersistenceContext
private EntityManager entityManager;
public OperationRepository() {
}
/*Implementation of abstract methods, getters/setters, etc*/
}
#Stateless
public class MenuRepository extends GenericRepository<Menu> {
#PersistenceContext
private EntityManager entityManager;
#Inject
private OperationRepository operationRepository;
public MenuRepository() {
}
/*idem OperationRepository*/
public List<Menu> getMenuFromOperation(...) {
// Do something where I need operationRepository
}
}
The GenericRepository<E> is just an abstract class with some common methods and other abstract methods, doesn't matter here.
The problem is that in the getMenuFromOperation() method I get a NullPointerException. Debugging the code I realized that the injected operationRepository is null when requested in the method.
Why does fail the injection point? what am I missing here?
Just to make a little test, I injected manually by instantiating a default OperationRepository in the MenuRepository constructor, but in that case the OperationRepository.entityManager isn't injected (is null)
Thanks in advance for your answers.
Edit #1
As requested by John Ament, here it goes:
All my code is in a single jar file. It's a Maven module that will be deployed together with a web module (a war package) in a Glassfish Server 4.1.
The beans.xml still doesn't exists yet, because the project isn't ready to be deployed (I didn't perform any integration test yet)
The MenuRepository is leveraged from a #Test class because I'm still developing MenuRepository.
The code for the test class is as follows:
public class MenuOperationRepositoryUTest extends BaseTestRepository {
private MenuRepository menuRepository;
private OperationRepository operationRepository;
#Before
public void initTestCase() {
initTestDB();
menuRepository = new MenuRepository();
menuRepository.setEntityManager(em);
operationRepository = new OperationRepository();
operationRepository.setEntityManager(em);
}
#After
public void finalizeTestCase() {
closeEntityManager();
}
/*Some successful tests*/
#Test
public void showMenuFromOperation() {
// Insert some dummy data into the test DB (HSQL)
// This method needs the injected OperationRepository in MenuRepository
List<Menu> menu = menuRepository.getMenuFromOperation(...);
// Assertions
}
}
And the BaseTestRepository is as follows:
#Ignore
public class BaseTestRepository {
private EntityManagerFactory emf;
protected EntityManager em;
// This is a helper class that contains all the boilerplate to begin transaction
// and commit, it's used to insert data in the test DB
protected DBCommandExecutor dbCommandExecutor;
protected void initTestDB() {
// sigeaPU is the name declared in persistence.xml
emf = Persistence.createEntityManagerFactory("sigeaPU");
em = emf.createEntityManager();
dbCommandExecutor = new DBCommandExecutor(em);
}
protected void closeEntityManager() {
em.close();
emf.close();
}
}
I think that's all I got so far. Let me know any clue you can get (or guess)
Because you're testing out of the CDI container you should also set your dependencies manually in the #Before method of the test class.
menuRepository.setOperationRepository(operationRepository)
The application I have been working on has been getting more and more complicated, and it's gotten to the point where I have been running into the same problems over and over again with concurrency. It no longer made any sense to solve the same problems and not have any regression tests.
That's when I found ThreadWeaver. It was really nice for some simple concurrency cases I cooked up, but I started to get frustrated when trying to do some more complicated cases with my production code. Specifically, when injecting components using Guice.
I've had a bit of a hard time understanding the implications of the way ThreadWeaver runs tests, and looked for any mention of Guice or DI in the wiki documents, but with no luck.
Is Guice compatible with ThreadWeaver?
Here is my test
#Test
public void concurrency_test() {
AnnotatedTestRunner runner = new AnnotatedTestRunner();
runner.runTests(OPYLWeaverImpl.class, OPYLSurrogateTranscodingService.class);
}
Here is my test implementation
public class OPYLWeaverImpl extends WeaverFixtureBase {
#Inject private TaskExecutor taskExecutor;
#Inject private Serializer serializer;
#Inject private CountingObjectFileMarshaller liveFileMarshaller;
#Inject private GraphModel graphModel;
#Inject private CountingModelUpdaterService updaterService;
#Inject private BabelCompiler babelCompiler;
#Inject private EventBus eventBus;
OPYLSurrogateTranscodingService service;
private Path testPath;
#ThreadedBefore
public void before() {
service = new OPYLSurrogateTranscodingService(eventBus, taskExecutor, serializer, liveFileMarshaller,
() -> new OPYLSurrogateTranscodingService.Importer(graphModel, babelCompiler, updaterService, eventBus),
() -> new OPYLSurrogateTranscodingService.Validator(eventBus, babelCompiler),
() -> new OPYLSurrogateTranscodingService.Exporter(graphModel, updaterService));
}
#ThreadedMain
public void mainThread() {
testPath = FilePathOf.OASIS.resolve("Samples/fake-powershell-unit-test.opyl");
service.applyToExistingGraphModel(testPath);
}
#ThreadedSecondary
public void secondaryThread() {
}
#ThreadedAfter
public void after() {
}
And the WeaverFixtureBase
public class WeaverFixtureBase {
#Inject protected CountingEventBus eventBus;
#Before public final void setupComponents() {
Injector injector = Guice.createInjector(new WeaverTestingEnvironmentModule(CommonSerializationBootstrapper.class));
injector.getMembersInjector((Class) this.getClass()).injectMembers(this);
}
private class WeaverTestingEnvironmentModule extends AbstractModule {
private final Class<? extends SerializationBootstrapper> serializationBootstrapper;
public WeaverTestingEnvironmentModule(Class<? extends SerializationBootstrapper> serializationConfiguration) {
serializationBootstrapper = serializationConfiguration;
}
#Override protected void configure() {
bind(TaskExecutor.class).to(FakeSerialTaskExecutor.class);
bind(SerializationBootstrapper.class).to(serializationBootstrapper);
bind(ModelUpdaterService.class).toInstance(new CountingModelUpdaterService());
bindFactory(StaticSerializationConfiguration.Factory.class);
CountingEventBus localEventBus = new CountingEventBus();
bind(Key.get(EventBus.class, Bindings.GlobalEventBus.class)).toInstance(localEventBus);
bind(Key.get(EventBus.class, Bindings.LocalEventBus.class)).toInstance(localEventBus);
bind(CountingEventBus.class).toInstance(localEventBus);
bind(EventBus.class).toInstance(localEventBus);
}
#Provides
#Singleton
public GraphModel getGraphModel(EventBus eventBus, Serializer serializer) {
return MockitoUtilities.createMockAsInterceptorTo(new GraphModel(eventBus, serializer));
}
}
But when the classloader loads OPYLWeaverImpl, none of the Guice stuff goes off and I get a big pile of nulls.
I feel like this is one of those "missing-something-really-simple" kind of scenarios. Sorry if it is!
The above comment is right. Thread-weaver is fully agnostic of JUnit. Thread weaver is its own runner that executes a test case respecting its own annotations. You must not use any JUnit-specific annotation within a Thread Weaver test.
Other than that, Thread Weaver does not need any compatibility for a specific framework. It manipulates Java byte code and loads that manipulated code using aeperate class loaders.
Finally, a Thread Weaver test without any secondary test does not make any sense. Thread weaver works by interleaving seperate execution paths. Without a second thread, Thread Weaver only steps through a single thread without adding any value.
I am trying to #Inject a Guice service into a #ServerEndpoint. I am using Tomcat 8.0.15 as the JSR-356 implementation. However, the dependency injection isn't working. Is there any additional configuration that needs to be done in order to enable Guice injection? Note that I am using all standard javax annotations only.
I figured this out. The Websocket endpoint needs to have a custom configurator, which creates and returns instances using the Guice injector instance.
Example:
Custom Guice servlet context listener:
public class CustomServletContextListener extends GuiceServletContextListener {
public static Injector injector;
#Override
protected Injector getInjector() {
injector = Guice.createInjector(...);
return injector;
}
}
Websockets custom configurator:
public class CustomConfigurator extends Configurator {
#Override
public <T> T getEndpointInstance(Class<T> clazz)
throws InstantiationException {
return CustomServletContextListener.injector.getInstance(clazz);
}
}
And then in the Websocket endpoint:
#ServerEndpoint(value = "/ws/sample_endpoint", configurator = CustomConfigurator.class)
public class SampleEndpoint {
private final SomeService service;
#Inject
public SampleEndpoint(SomeService service) {
this.service = service;
}
...
}
Building upon Aritra's own answer:
To be honest, I don't know for sure if this works with Guice 3.0, but it does work for 4.0, which is the current stable release.
I think a somewhat cleaner approach is to change your CustomConfigurator into something like this:
public class CustomConfigurator extends Configurator {
#Inject
private static Injector injector;
public <T> T getEndpointInstance(Class<T> endpointClass) {
return injector.getInstance(endpointClass);
}
}
And then from your extended ServletModule class' configureServlets method, call requestStaticInjection(CustomConfigurator.class)
That way you won't expose the injector to everyone. I don't know about you, but it gives me a nice and fuzzy feeling inside to know that no one will be able to mess with my injector :-).
I understand how to inject a single dependency using Google Guice.
The following snippets are from the Guice site.
To code a configuration the code would be
public class BillingModule extends AbstractModule {
#Override
protected void configure() {
bind(TransactionLog.class).to(DatabaseTransactionLog.class);
bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class);
}
}
The component which use the dependencies to be injected shuold looks like the following:
class BillingService {
private final CreditCardProcessor processor;
private final TransactionLog transactionLog;
#Inject
BillingService(CreditCardProcessor processor,
TransactionLog transactionLog) {
this.processor = processor;
this.transactionLog = transactionLog;
}
public Receipt chargeOrder(PizzaOrder order, CreditCard creditCard) {
...
}
}
FInally, the client code would use Guice to inject the dependencies where needed:
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BillingModule());
BillingService billingService = injector.getInstance(BillingService.class);
...
}
My question is:
Is there a built-in feature in Guice to inject not only -for example- BillingService.class but another different implementation in runtime?
I think I can implement the variation of the different classes to be injected thru reflection or some manual mechanism like reading a configuration file to indicate which class to inject but I still want to know if this can be done from Guice itself.
You can make BillingService an interface and bind a different implementation of it decided in runtime in Module's configure method.
I'm trying to figure out the best practice for dealing with the following situation:
public class AppModule extends Module {
#Override
protected void configure() {
install(new JpaPersistModule("myJpaUnit").addFinder(Dao.class));
bind(MyJpaInitializer.class).asEagerSingleton();
}
#Provides
#IndicatesSomeConstantMap
#Singleton
Map<String, String> getMappings(Dao dao) {
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<String, String>();
// Build map from Dao
return builder.build();
}
}
I need to inject #IndicatesSomeConstantMap in other classes. It seem the only way that getMappings can get the Dao is if I bind MyJpaInitializer as an EagerSingleton - which feels wrong. What's the preferred way of dealing with these hierarchical dependencies?
EDIT:
Based on the answer from #jeffcrowe I came up with something like:
public class Module1 extends PrivateModule {
#BindingAnnotation #Target({ FIELD, PARAMETER, METHOD }) #Retention(RUNTIME)
public #interface Jpa1{}
#Singleton
public static class JpaInitializer1 {
#Inject
public JpaInitializer1(#Jpa1 PersistService service) {
service.start();
}
}
public interface Finder1 {
#Finder(query="FROM Foo", returnAs = ArrayList.class)
List<Foo> getAll();
}
#Override
protected void configure() {
install(new JpaPersistModule("firstJpaUnit").addFinder(Finder1.class));
bind(JpaInitializer1.class);
}
#Provides
#Exposed
#Jpa1
PersistService getPersistService(Provider<PersistService> provider) {
return provider.get();
}
#Provides
#Exposed
#Jpa1
Finder1 getFinder(Finder1 finder, JpaInitializer1 init) {
return finder;
}
}
This handles the the dependency by wrapping it behind the provider and feels cleaner to me than using the eagerSingleton approach. This also hides the JpaModule behind a private module making it useful in a situation where multiple persistence modules are bound. The new problem is that since the Finder is already bound by the JpaPersistModule we have to add the #Jpa1 annotation to every injection of Finder1. Is there a way around that?
This is an interesting case. Normally in a scenario like this you could bind the initializer in normal Singleton scope and inject it into the Dao implementation, and this would ensure that it was done before the Dao was used. Due to the way the Jpa persistence modules are set up, there doesn't seem to be an easy way to add this dependency.
As the OP pointed out to me, JpaPersistModule is final, so we can't work around this by subclassing it. We can, however wrap the binder used to install the JpaPersistModule.
First wrap the binder in a proxy with an overridden the bind() method to intercept the EntityManager.class binding. (BinderProxy implements Binder and passes every call to the Binder given in it's constructor. Source available here)
new BinderProxy(binder()) {
#Override
public <T> AnnotatedBindingBuilder<T> bind(Class<T> clazz) {
if (clazz == EntityManager.class) {
return (AnnotatedBindingBuilder<T>) super.bind(clazz).annotatedWith(DefaultEntityManager.class);
} else {
return super.bind(clazz);
}
}
}.install(new JpaPersistModule("myJpaUnit"));
Then add a provides method to your module which ensures Jpa init before an EntityManager is used
#Provides EntityManager provideEm(MyJpaInitializer init, #DefaultEntityManager EntityManager em){
return em;
}