Guice persistence with JDO - weird NPE - java

I am using Guice with JDO and Datanucleus in my desktop app. I am facing a NPE that I can't fix, so I hope someone can help me :)
I am using properly configured H2 db, with schema created and all my classes are nicely enhanced, so it's not that. Anyway, I am getting NPE here, at JDORepository class:
public abstract class JdoRepository<T> implements Repository<T>
{
private final Class<T> clazz;
private final Provider<PersistenceManager> pmProvider;
protected JdoRepository(Class<T> clazz, Provider<PersistenceManager> pmProvider)
{
this.clazz = clazz;
this.pmProvider = pmProvider;
}
public void persist(T entity)
{
pmProvider.get().makePersistent(entity); <---- NPE!
}
My PersistenceManagerFilter looks like that:
#Singleton
public class PersistenceManagerFilter implements Filter
{
private static final Logger logger = Logger.getLogger(PersistenceManagerFilter.class.getName());
private static final ThreadLocal<PersistenceManager> pm = new ThreadLocal<PersistenceManager>();
private PersistenceManagerFactory pmf;
public void init(FilterConfig filterConfig) throws ServletException
{
logger.info("Creating PersistenceManagerFactory");
pmf = JDOHelper.getPersistenceManagerFactory();
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
try
{
pm.set(pmf.getPersistenceManager());
chain.doFilter(request, response);
}
finally
{
pm.get().close();
}
}
public void destroy()
{
logger.info("Closing PersistenceManagerFactory");
pmf.close();
}
/**
* This module binds the JDO {#link javax.jdo.PersistenceManager} interface to the provider that allows the
* implementation to be injected as Provider<PersistenceManager>.
*/
public static class GuiceModule extends AbstractModule
{
#Override
protected void configure()
{
bind(PersistenceManager.class).toProvider(new Provider<PersistenceManager>()
{
public PersistenceManager get()
{
return PersistenceManagerFilter.pm.get();
}
});
}
}
}
And the responsible module:
public class GuiceModule extends AbstractModule
{
#Override
protected void configure()
{
// Enable per-request-thread PersistenceManager injection.
install(new PersistenceManagerFilter.GuiceModule());
bind(new TypeLiteral<Repository<Project>>() { }).to(JdoProjectRepository.class);
I am initiating it all that way:
Injector injector = Guice.createInjector(new GuiceModule());
Main main = injector.getInstance(Main.class);
main.run();
So repository bindings in main class work fine, as they are redirected to JDORepository. It's something at lower level, PMF not getting bound properly? Any ideas?

What does your main.run()-method do? Does it call PersistenceManagerFilter#doFilter? If it doesn't, the value in yourThreadLocal<PersistenceManager> will be null...
You could override the initialValue() and do something like this:
ThreadLocal<PersistenceManager> pm = new ThreadLocal<PersistenceManager>(){
#Override
protected PersistenceManager initialValue() {
return JDOHelper.getPersistenceManagerFactory().getPersistenceManager();
}
};
You should also remember to call the ThreadLocal#remove() method in your finally-block.
Instead of handling the ThreadLocal yourself, you could bind the PersistenceManager directly in the guice-module:
class GuiceModule extends AbstractModule {
#Provides #RequestScoped
PersistenceManager providePersistenceManager(){
return JDOHelper.getPersistenceManagerFactory().getPersistenceManager();
}
#Override
protected void configure() {}
}

Related

Other way to achive GWTP placeManager than Constructor's #Inject annotation

I use GWTP and restyGWT. I would like to use placeManager in restyGWT DispatcherCallback, when my rest server will answer with 401 unauthorised I would like to redirect application to login page, that User could apply credentials and retried his request.
To do this I have to somehow get instance of PlaceManager (from gwtp framework). I cannot use #Inject annotation, cause I have manuall call to constructor as follow:
public class ForbiddenDispatcherFilter implements DispatcherFilter {
#Override
public boolean filter(Method method, RequestBuilder builder) {
builder.setCallback(new ForbiddenDispatcherCallback(method));
return true;
}
}
public class ForbiddenDispatcherCallback implements RequestCallback {
protected RequestCallback requestCallback;
public ForbiddenDispatcherCallback(Method method) {
this.requestCallback = method.builder.getCallback();
}
#Override
public void onResponseReceived(Request request, Response response) {
if (response.getStatusCode() == Response.SC_FORBIDDEN || response.getStatusCode() == Response.SC_UNAUTHORIZED) {
// make a hard redirect to login page
// TODO change redirect to GWTP native
Window.Location.assign("#login");
// PlaceRequest placeRequest = new
// PlaceRequest.Builder(placeManager.getCurrentPlaceRequest()).nameToken(Routing.Url.login).build();
// placeManager.revealPlace(placeRequest);
} else {
requestCallback.onResponseReceived(request, response);
}
}
public class RestyDispatcher extends DefaultFilterawareDispatcher {
public RestyDispatcher() {
addFilter(new ForbiddenDispatcherFilter());
addFilter(new BasicAuthHeaderDispatcherFilter());
}
#Override
public Request send(Method method, RequestBuilder builder) throws RequestException {
return super.send(method, builder);
}
}
Please help.
Edit
public class ClientModule extends AbstractPresenterModule {
#Override
protected void configure() {
bind(RestyGwtConfig.class).asEagerSingleton();
install(new DefaultModule.Builder()//
.defaultPlace(Routing.HOME.url)//
.errorPlace(Routing.ERROR.url)//
.unauthorizedPlace(Routing.LOGIN.url)//
.tokenFormatter(RouteTokenFormatter.class).build());
install(new AppModule());
// install(new
// GinFactoryModuleBuilder().build(AssistedInjectionFactory.class));
bind(CurrentUser.class).in(Singleton.class);
bind(IsAdminGatekeeper.class).in(Singleton.class);
bind(UserLoginGatekeeper.class).in(Singleton.class);
// Google Analytics
// bindConstant().annotatedWith(GaAccount.class).to("UA-8319339-6");
// Load and inject CSS resources
bind(ResourceLoader.class).asEagerSingleton();
}
}
and:
public class RestyGwtConfig {
static {
// GWT.log("--> RestyGwtConfig -> setDispatcher");
Defaults.setDispatcher(new RestyDispatcher());
// GWT.log("--> RestyGwtConfig -> setServiceRoot");
Defaults.setServiceRoot(new Resource(GWT.getModuleBaseURL()).resolve(ServiceRouting.SERVICE_ROOT).getUri());
UserCredentials.INSTANCE.setUserName("ronan");
UserCredentials.INSTANCE.setPassword("password");
}
}
How and where do you create your ForbiddenDispatcherFilter ?
You could use guice's AssistedInjection to inject the PlaceManager into your ForbiddenDispatcherCallback.
public class ForbiddenDispatcherCallback implements RequestCallback {
protected RequestCallback requestCallback;
protected PlaceManager placeManager;
#Inject
public ForbiddenDispatcherCallback(PlaceManager placeManager, #Assisted Method method) {
this.placeManager = placeManager;
this.requestCallback = method.builder.getCallback();
}
}
You need to define an factory interface:
public interface AssistedInjectionFactory {
ForbiddenDispatcherCallback createForbiddenCallback(Method method);
}
In the configure method of your ClientModule you need to call:
install(new GinFactoryModuleBuilder().build(AssistedInjectionFactory.class));
Then you can instantiate your class this way:
public class ForbiddenDispatcherFilter implements DispatcherFilter {
AssistedInjectionFactory factory;
#Inject
public ForbiddenDispatcherFilter(AssistedInjectionFactory factory)
{
this.factory = factory;
}
#Override
public boolean filter(Method method, RequestBuilder builder) {
builder.setCallback(factory.AssistedInjectionFactory(method))
return true;
}
}
Of course this requires that you also inject the ForbiddenDispatcherFilter.
Edit:
You could try to pass the RestyDispatcher to the constructor of your RestyGWTConfig:
public class RestyGwtConfig {
#Inject
public RestyGwtConfig(RestyDispatcher dispatcher) {
Defaults.setDispatcher(dispatcher);
}
static {
// GWT.log("--> RestyGwtConfig -> setServiceRoot");
Defaults.setServiceRoot(new Resource(GWT.getModuleBaseURL()).resolve(ServiceRouting.SERVICE_ROOT).getUri());
UserCredentials.INSTANCE.setUserName("ronan");
UserCredentials.INSTANCE.setPassword("password");
}
}
The RestyDispatcher looks like this:
public class RestyDispatcher extends DefaultFilterawareDispatcher {
#Inject
public RestyDispatcher(ForbiddenDispatcherFilter filter) {
addFilter(filter);
addFilter(new BasicAuthHeaderDispatcherFilter());
}
#Override
public Request send(Method method, RequestBuilder builder) throws RequestException {
return super.send(method, builder);
}
}

Ways to mock Camel Endpoint POJO producer

I followed guide here, and I was successfully able to configure a producer on my bean endpoint like this:
#Produce( uri = "activemq:foo" )
private MyListener myListener;
MyListener is:
public interface MyListener {
#InOnly
public void send( String message );
}
and my bean:
public class MyBeanEndpoint {
#Produce( uri = "activemq:foo" )
private MyListener myListener;
#Handler
public void doSomething( final Object body ) {
...
}
public void setMyListener( final MyListener myListener ) {
this.myListener = myListener;
}
Now, how can I test this?
I mean: my test extends CamelTestSupport and I configured my routes with
#Override
public RouteBuilder createRouteBuilder() {
return new RouteBuilder() { ... }
That is: I've reproduced camel context, but I've NO spring context configured and I want (if possible) to avoid instantiating it.
How can I mock producer or make Camel instantiate and inject this bean into my bean endpoint?
What is the best way to test such situation using Apache Camel features like CamelTestSupport and similar utilities?
My reference test is:
public class Test extends CamelTestSupport {
private static BeanEndpoint beanEndpoint
#BeforeClass
public static void init() {
beanEndpoint.setActivemqMyListener( ??? );
}
#Override
public CamelContext createCamelContext() {
context = new DefaultCamelContext();
context.addComponent( "activemq", new SedaComponent() );
return context;
}
#Override
public RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from( "activemq:foo" )
.to( "mock:out" );
}
};
}
#Test
public void testFooQueue() throws Exception {}
Let Camel create your bean, then the various dependency injection and whatnot is configured for you.
private static BeanEndpoint beanEndpoint
...
beanEndpoint = camelContext.getInjector().newInstance(BeanEndpoint.class);

How to test multiple RouteBuilders in Apache Camel

I want to test multiple camel RouteBuilder in a single unit test
what I have:
Custom camel processor that changes state
public class MyProcessor implements Processor {
MyState state;
public MyProcessor(MyState state) {this.state = state;}
#Override
public void process(Exchange exchange) throws Exception {
state.setState(state.getState() + 5);
}}
Two simple RouteBuilders: first routes messages from "direct:start" to "direct:endroute1" second pick up messages from "direct:endroute1" and routes somewhere "mock:endroute2"
public class MyRouteBuilder1 extends RouteBuilder {
MyState state;
public MyRouteBuilder1(MyState state) {this.state = state;}
#Override
public void configure() throws Exception {
from("direct:start").process(new MyProcessor(state)).to("direct:endroute1");
}}
public class MyRouteBuilder2 extends RouteBuilder {
MyState state;
public MyRouteBuilder2(MyState state) {this.state = state;}
#Override
public void configure() throws Exception {
from("direct:endroute1").process(new MyProcessor(state)).to("mock:endroute2");
}}
Writing unit test for a single route builder is straightforward:
public class MyTest extends CamelTestSupport {
MyState state = new MyStateImpl();
#EndpointInject(uri = "mock:result")
protected MockEndpoint resultEndpoint;
#Test
public void testSingleRoute() throws Exception {
resultEndpoint.expectedMessageCount(1);
template.sendBody("direct:start", new Object());
assertTrue(state.getState() == 5);
resultEndpoint.assertIsSatisfied();
}
#Override
protected RouteBuilder createRouteBuilder() {
return new MyRouteBuilder1(state) {
public void configure() throws Exception{
super.configure();
from("direct:endroute1").to("mock:result");
}
};
}
}
What I really want to do is somehow to override CamelTestSupport.createRouteBuilder that will test whole chain of message processing from direct:start to mock:endroute2. As a result state.getState() should be 10
Try to override method:
protected RouteBuilder[] createRouteBuilders() {...}
from CamelTestSupport. It's available since version 2.17
you can just add multiple RouteBuilders to the context using the context.addRoutes(RouteBuilder) API
see this unit test for an example:
https://svn.apache.org/repos/asf/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/AddRoutesAtRuntimeTest.java
You could use one RouteBuilder including the routes of multiple other RouteBuilders.

"must implement the inherited abstract method"

I had in my class AbstractJpaDao method
#Override
public EntityManager getEntityManager() {
return em;
}
now it isn't in use and I wanted to delete it, but i get error:
The type JpaAclIdentityDao must implement the inherited abstract method IJpaDao.getEntityManager() in class JpaAclIdentityDao.
is that getter necessary? if not how to remove it
my code:
public abstract class AbstractJpaDao implements IJpaDao {
protected final IApplicationConfig config;
protected final EntityManager em;
private final SingletonEventBus eventBus;
public AbstractJpaDao(EntityManager entityManager, IApplicationConfig config, SingletonEventBus eventBus) {
checkArgument(entityManager != null);
checkArgument(config != null);
checkArgument(eventBus != null);
this.em = entityManager;
this.config = config;
this.eventBus = eventBus;
}
protected void saveEntity(IEntity entity) {
boolean isNew = entity.getId() == 0;
em.getTransaction().begin();
try {
em.persist(entity);
em.getTransaction().commit();
if (isNew) {
eventBus.post(new EntityCreatedEvent(entity));
}
} finally {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
}
}
#Repository
public class JpaAclIdentityDao extends AbstractJpaDao implements IAclIdentityDao {
public static final String GROUP_NAME_PATTERN = "GROUP_%d";
private static final String GROUP_TEMP_NAME = "TEMP_GROUP_NAME";
#Inject
public JpaAclIdentityDao(EntityManager entityManager, IApplicationConfig config, SingletonEventBus eventBus) {
super(entityManager, config, eventBus);
}
#Override
public AclIdentity findById(Object id) throws EntityNotFoundException {
return em.find(AclIdentity.class, id);
}
#Override
public List<AclIdentity> findAll() {
return findAllByType(AclIdentity.class);
}
#Override
public void delete(AclIdentity entity) {
// TODO Auto-generated method stub
}
#Override
public void save(AclIdentity entity) {
saveEntity(entity);
}
#Override
public AclIdentity createNew(String sid, boolean principal) {
AclIdentity identity = new AclIdentity(sid, principal);
save(identity);
return identity;
}
#Override
public AclIdentity createNew(User entity) {
return createNew(entity.getEmail(), true);
}
#Override
public AclIdentity createNew(Group entity) {
AclIdentity identity = createNew(GROUP_TEMP_NAME, false);
identity.setSid(String.format(GROUP_NAME_PATTERN, identity.getId()));
save(identity);
return identity;
}
}
Yes, you have to implement all methodes which are defined in the implemented interface. The only possible solutions i can think of, is to implement the method and leave it empty, or don't implement the interface.
Or, as ben75 said, just remove the method in the declaration of your interface "IJpaDao" if you don't need it (anywhere).
The method getEntityManager is defined in IJpaDao (or one super interface) that's why you need to provide an implementation of it in your class.
If it is not use at all (i.e. even by some reflection mechanism inside some frameworks you are using), then you can remove it from IJpaDao and you won't be forced to implement it.
If you don't want to use it, then throw an UnsupportedOperationException:
public class JpaAclIdentityDao extends AbstractJpaDao ... { // Or AbstractJpaDao...
// Some Code...
public EntityManager getEntityManager() {
throw new UnsupportedOperationException();
// return null; (This is not needed, due to the exception thrown above. Thanks dedek!)
}
// More Code...
}
Due to OO programing, if a concrete class inherits a class/interface with an abstract method, you must define that method, or make your class abstract and pass it down the line, like you did with AbstractJpaDao.
I am guessing that the Interface IJpaDao contains a getEntityManager abstract method.

How to call custom data loader on Spring application start

I'm trying to load some data to my DB on application start. I have a bean defined for this purpose
applicationContext.xml
<bean class="com.project.loader.DataLoader"
id="DataLoader"
depends-on="entityManagerFactory"
scope="singleton"/>
class:
#RooJavaBean
#RooConfigurable
public class DataLoader implements InitializingBean
It is being executed however on first persist() method being call, Spring throws me following error:
Caused by: java.lang.IllegalStateException: Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)
at com.project.lib.model.extensions.i18n.Locale_Roo_Jpa_ActiveRecord.entityManager_aroundBody0(Locale_Roo_Jpa_ActiveRecord.aj:19)
at com.project.lib.model.extensions.i18n.Locale_Roo_Jpa_ActiveRecord.ajc$interMethod$com_project_lib_model_extensions_i18n_Locale_Roo_Jpa_ActiveRecord$com_project_lib_model_extensions_i18n_Locale$entityManager(Locale_Roo_Jpa_ActiveRecord.aj:1)
at com.project.lib.model.extensions.i18n.Locale.entityManager(Locale.java:1)
Previousely it was working when I defined DataLoader in following way:
#Component
#Configurable
public class DataLoader implements ApplicationListener
but using raw types is not good practice so I would like to switch
How can I make it work?
Spring version: 3.1
I've solved this issue in the past by moving the component-scan definition to the end of the application context, as suggested here
I use the spring SmartLifecycle:
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/SmartLifecycle.html
I've created a class that does this nicely, just extend and override the run method:
public abstract class StartupService implements SmartLifecycle {
/** Logger for this class and subclasses */
protected static final Logger logger = LoggerFactory.getLogger(StartupService.class);
protected boolean running=false;
////////////////////// Lifecycle Methods \\\\\\\\\\\\\\\\\\
#Override
public void start() {
try {
logger.info("starting {}", this.getClass().getSimpleName());
run();
} catch (Exception e) {
logger.error("failed to run importer", e);
}
}
#Override
public void stop() {
running=false;
}
#Override
public boolean isRunning() {
return running;
}
////////////////////// SmartLifecycle Methods \\\\\\\\\\\\\\\\\\
#Override
public boolean isAutoStartup() {
return true;
}
#Override
public void stop(Runnable callback) {
stop();
callback.run();
}
#Override
public int getPhase() {
return 0;
}
public abstract void run() throws Exception;
}

Categories