Persisting Classes implementing an interface with GORM MongoDB Plugin - mongodb

I am having a problem while persisting a class. I have a class called Scraper which uses an interface called Paginator. There are several implementations of the Paginator interface which will be instantiated at runtime. So the structure looks like this:
class Scraper {
//some code
Paginator paginator
//more code
def Scraper(Paginator paginator){
this.paginator = paginator
}
}
and then there are the concrete implementations of the paginator interface lets say paginatorA and paginatorB. So now I am trying to do the following:
PaginatorA p = new PaginatorA()
Scraper s = new Scaper(p)
s.save(flush:true)
...and what it get is:
Error Error executing script TestApp:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoDatastore': Cannot resolve reference to bean 'mongoMappingContext' while setting bean property 'mappingContext';
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoMappingContext': FactoryBean threw exception on object creation; nested exception is java.lang.NullPointerException (Use --stacktrace to see the full trace)
Can anybody tell me what to make of this? I guess it has something to do with the Mapper because it doesn't know which concrete Paginator to use or how to persist it? If that is the case then how can I tell the framework what to do? I tried to come up with a solution for hours now and am really frustrated so any help would be really really appreciated.
Oh btw I also tried implementing against the concrete implementation (PaginatorA) ... this works perfectly fine since my assumption that it has something to do with the paginator interface.
Thanks for any response...

The error is bad, you should probably raise a JIRA issue for that, but fundamentally there are 2 problems I can see with the code:
Your persistent classes must have a public no-args constructor as per any JavaBean, by adding a constructor that takes your interface, you are no longer providing one
Your Scraper class needs to mark the 'Paginator' as transient to tell the persistence engine not to attempt to persist the 'paginator' property. Since this a custom interface it will not know how to persist it.

Related

EclipseLink-Moxy Unable to load custom DomHandler class while instantiating JAXB context

I am using Eclipselink Moxy Implementation of JAXB in my project to map complex XML to String Object using XmlAnyElement.
For this I have implemented DomHandler named as LayoutHandler.
I am using JAXB for resteasy web services deployed in JBoss 6.
I am facing Below issue intermittently -
Exception [EclipseLink-50033] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b):
org.eclipse.persistence.exceptions.JAXBException
Exception Description: The DomHandlerConverter for DomHandler
[com.**.LayoutHandler] set on property [layoutXml] could not be
initialized.
Internal Exception: java.lang.ClassNotFoundException:
com.**.LayoutHandler from
BaseClassLoader#5c0b3ad0{vfs:///*/*/jboss-server/server/all/deployers/resteasy.deployer}
While EclipseLink Moxy is instantiating JAXBContext using JAXBContext.newInstance(classes, properties)
After spending some time in debugging and analyzing the issue I could figure out that ClassLoader of resteasy is getting used to load LayoutHandler class instead of my application class loader(vfs://///jboss-server/server/all/deploy/app_name.ear/app_name.war/) which is causing the issue as its unable to find the LayoutHandler class.
When I bounce the server, issue is getting resolved so I am unable to find out the exact root cause. Any help will be appreciated.
Further debugging into org.eclipse.persistence.jaxb.JAXBContextFactory revealed that below two classes are getting passed to createContext() method of JAXBContextFactory -
org.jboss.resteasy.plugins.providers.jaxb.JaxbCollection
com.**.Model_class
public static javax.xml.bind.JAXBContext createContext(Class[] classesToBeBound, Map properties) throws JAXBException {
ClassLoader loader = null;
if (classesToBeBound.length > 0) {
loader = classesToBeBound[0].getClassLoader();
}
return createContext(classesToBeBound, properties, loader);
}
In above method classloader of first class is getting used to load the custom DomHandler later on.
When first element in array is model class at that time code is working fine as application context class loader is getting used but when the first element in array is JaxbCollection rest easy context class loader is getting used and its throwing mentioned exception.
This issue is occurring intermittently as order of elements in array is varying which might be due to the use of HashSet to hold the elements of type Class by caller of this method which is passing the classesToBeBound array
Note: I have replaced actual package names with *.
I'm surprised it works on a bounce... all of your JAXB bits need to line up, you should be using the moxy jaxb provider at all times. If it's failing after initial deploy, then working after a bounce, I suspect that you want to specify the moxy jaxb provider in your system properties ( -Djavax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory ) and ensure that they're available to jboss when your app is not deployed.

Does Crud Repository has saveAll method that works?

I am trying to use CRUDRepository for my development project. I have seen in many posts that CRUD Repository do support saveAll method which allows to save a list of object in the database. But when I am using it, It is giving me an error that saveAll property is not found
Here is the detailed error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'BinaryPartCRUDRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query method public abstract java.util.List xxx.xxx.xx.xxxx.repository.BinaryPartCRUDRepository.saveAll(java.util.List)! No property saveAll found for type BinaryPart!
Here is my code.
public interface BinaryPartCRUDRepository extends CrudRepository<BinaryPart, Long> {
BinaryPart save(BinaryPart binaryPart);
List<BinaryPart> saveAll(List<BinaryPart> binaryParts);
}
The save Function is working. But saveAll is not.
I have also tried to use the Persistence manager to do the batch save. But having null object while doing JUnit Testing. So I am preferring to stay with CRUD Repository. Appreciate any kind of suggestion.
saveAll already there in CrudRepository, so no need to specify your own method for save all in repository interface.
remove this part:
List<BinaryPart> saveAll(List<BinaryPart> binaryParts);
and in your service class , directly call `saveAll method. Remember this method using iterable as param and return value.
The saveAll method has the following signature:
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
You define an additional method with the same name, but a different signature. Spring Data does not know how to create an implementation for that and throws the exception.
Just change your interface to:
public interface BinaryPartCRUDRepository extends CrudRepository<BinaryPart, Long> {}
And you are good to go.

JPA2, JAX-RS: #PersistentContext, How to get EntityManager in a Facade constructor?

I have a JAX-RS web service that was generated by Netbeans. There are non-abstract facade classes for the service's endpoints. The persistence context is being injected into the non-abstract facade. Everything is working well and I see my data being returned to Fiddler.
We are using DTOs and I am implementing an assembler pattern. So, in the non-abstract facade's constructor, I am creating an instance of the assembler, and am passing the facade's entity manager instance into it. Unfortunately, it seems that the injection of the persistence context has not happened before the facade's constructor has been called, so I cannot pass the entity manager instance into the assembler for its to use in mapping operations. Kind of a chicken-before-the-end situation... I cannot figure out how to make this work... Is there some kind of post-constructor method that I can override and perform the initialization of the assembler and pass in the entity manager to it? I'd really appreciate your help and suggestions.
Thank you for your time and ideas,
Mike
Use method marked with #PostConstruct annotation. Like this:
#PostConstruct
private void init() {
// I'm called after all injections have been resolved
// initialize some object variables here
...
}
In that method you can use both, object fields initialized in the constructor and passed by injection.

Sharprepository Autofac InstancePerApiRequest in Webapi environment not working

Does anyone have a working example of sharprepository intergration with autofac using InstancePerApiRequest for DbContext?
I am registering my dbcontext thusly:
builder.RegisterType<AuditTestEntities>().As<DbContext>().InstancePerApiRequest();
If I remove the InstancePerApiRequest, sharprepository is able to get a dbcontext. But with the InstancePerApiRequest, I get the error message pasted below. Basically the crux of the error is, I suspect, the way sharprepository makes the call:
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
The full error stack:
iisexpress.exe Error: 0 : Operation=DefaultHttpControllerActivator.Create, Exception=System.InvalidOperationException: An error occurred when trying to create a controller of type 'AccountController'. Make sure that the controller has a parameterless public constructor. ---> Autofac.Core.DependencyResolutionException: An exception was thrown while invoking the constructor 'Void .ctor()' on type 'AccountRepository'. ---> Could not resolve type 'System.Data.Entity.DbContext' using the 'AutofacDependencyResolver'. Make sure you have configured your Ioc container for this type. View the InnerException for more details. (See inner exception for details.) ---> SharpRepository.Repository.Ioc.RepositoryDependencyResolverException: Could not resolve type 'System.Data.Entity.DbContext' using the 'AutofacDependencyResolver'. Make sure you have configured your Ioc container for this type. View the InnerException for more details. ---> Autofac.Core.DependencyResolutionException: No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
Okay found the issue. There is a problem with using the SharpRepository AutofacDependencyResolver when using the MVC or Web API integration and trying to use the scope InstancePerApiRequest or InstancePerHttpRequest. Autofac expects those items to be resolved from the System.Web.DependencyResolver.Current instead of from the Autofac IContainer directly as the AutofacDependencyResolver is currently doing.
Here is how you can fix the issue right now until we make an overload for AutofacDependencyResolver that fixes the issue.
You will need to create your own dependency resolver within your project like this one:
public class CustomAutofacDependencyResolver : BaseRepositoryDependencyResolver
{
private readonly IDependencyResolver _resolver;
public CustomAutofacDependencyResolver(IDependencyResolver resolver)
{
_resolver = resolver;
}
protected override T ResolveInstance<T>()
{
return _resolver.GetService<T>();
}
protected override object ResolveInstance(Type type)
{
return _resolver.GetService(type);
}
}
And then register it with SharpRepository so it will use it to resolve the DbContext and then it will work as expected.
RepositoryDependencyResolver.SetDependencyResolver(new CustomAutofacDependencyResolver(DependencyResolver.Current));
** Update**
I was testing with MVC and able to replicate the error and fix it but that doesn't work with Web API. I am used to using StructureMap where it works fine using the GlobalConfiguration.Configuration.DependencyResolver.
It seems the issue is that Autofac needs a IDependencyScope that you can access from the HttpRequestMessage but I'm not seeing a way to get to that outside of the ApiController. This describes the issue and the reason: https://groups.google.com/forum/#!msg/autofac/b3HCmNE_S2M/oMmwFE5uD80J
Unfortunately right now I'm at a bit of a loss on the best way to handle this. But I'll keep thinking about it.
So, I was able to get mine working by changing the lifetime scope to InstancePerLifetimeScope. I don't know whether this has any unforeseen consequences or not. Everything appears to be working fine for me so far.

Creating new entities while enabling injection

I have a method on a stateless session bean which creates a new instance of an entity and persists it. You might normally use new MyEntity() to create the object but I would like injection to populate some of the properties of the entity for me.
I got partial success using
#Inject
#New
private MyEntity myNewEntity;
in the session bean and then using that instance in my method.
The problem I have now is that the second time the method is called, myNewEntity isn't a new object, its the same object as the one created the first time. As a result I'm getting
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '9' for key 'PRIMARY'
Or at least that's why I think I'm getting this exception. Certainly if I use new MyEntity() I don't get the exception but my injection doesn't happen.
Am I on the wrong track? How can I create a new local entity object while enabling injection?
Any help would be great!
First of all - I have serious doubts that it's a good idea to use CDI to control the lifecycle of a Entity. See this quote from the documentation (here):
According to this definition, JPA
entities are technically managed
beans. However, entities have their
own special lifecycle, state and
identity model and are usually
instantiated by JPA or using new.
Therefore we don't recommend directly
injecting an entity class. We
especially recommend against assigning
a scope other than #Dependent to an
entity class, since JPA is not able to
persist injected CDI proxies.
What you should do to create new instances of entities is adding a layer of indirection, either with #Produces or #Unwraps (Seam Solder, if you need it to be truly stateless), and thereby making sure that you code explicitly calls new.
I think I have a working solution now which seems okay, though I'm not quite sure why it works so I welcome your feedback on a better solution. I am now injecting a DAO-style bean into my stateless session bean:
#Stateless
public class PhoneService {
#Inject
protected ProblemReports problemReports;
An injecting my entity into the ProblemReports bean:
public class ProblemReports {
#Inject
#New
private ProblemReport newProblemReport;
I assume that ProblemReports defaults to #Dependant scope which as I understand it should be the same as the stateless session bean which containts it. I could understand this if the scope of ProblemReports was shorter, causing a new instance of ProblemReport to be created when the new ProblemReports is created; but it isn't.
Is this just an example of EJB and CDI not playing well together?