Repository uses N1QL - couchbase

I'm getting the following exception:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'answerRepository': Invocation of init method failed; nested exception is org.springframework.data.couchbase.core.UnsupportedCouchbaseFeatureException: Repository uses N1QL
I'm using Spring 4.2.0.RELEASE with spring-data-couchbase 2.0.0.M1 against Couchbase 2.5.1 enterprise edition (build-1083)
I can't see any explanation in the doc for this error.
Here is the repository:
public interface AnswerRepository extends BaseRepository<Answer, String> {
final static String DESIGN_DOCUMENT = "answers";
#View(viewName = "answers_by_quizId_startTime", designDocument = DESIGN_DOCUMENT)
public List<Answer> findByQuizIdAndStartTime(String quizId, long startTime);
Answer findByUuid(String uuid);
}
#NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {
}
Maybe my Couchbase server does not support this feature, whereas my repository expects it.
I might need to code my repository differently.
It's too bad it doesn't say which method is the invalid one here.
Or it is my using of the CrudRepository in the base class ?
I wonder how to find out which views it expects to find in my Couchbase server.

Repositories in Spring Data Couchbase 2.0 rely almost exclusively on Views and N1QL. A good chunk of the new features in this version are made possible by N1QL, which is now the default mechanism Spring Data uses for things like "query derivation" (implementing a repository method by producing some sort of query that is derived from the method name).
Couchbase Server 2.5.1 doesn't have access to N1QL (which came with Couchbase Server 4.0 and of course also in the brand new 4.1 version).
If you want Spring Data to implement findByUuid for you, you'll have to annotate that method with #View and create the appropriate view that emits uuids from your Answer documents.
View query derivations are heavily restricted and give you more work since you have to write the correct map function:
a repository method based on a view can only query with one criteria.
you have to create your view correctly, emitting the correct keys corresponding to the criteria you'll query with.
you have to create one view per entity class, restricting the view to only emit if the "_class" field in the JSON matches said entity (note: this field can be renamed in the configuration so make sure to use the relevant one).
So that means that your findByQuizIdAndStartTime cannot work either. You may have to implement this (and maybe findByUuid) in the BaseRepository, relying on the CouchbaseTemplate and using its findByView method (or even queryView as a last resort).
The UnsupportedCouchbaseFeatureException is mentioned in the M1 doc chapter 7 (on N1QL based querying).
See also the section on view query derivation further down the documentation.

Related

Grails JSON marhsaling using introspection causes severe bottleneck on Classloader.loadClass()

I am using Grails 2.2.4 and have a controller endpoint which converts a domain object list to JSON. Under load (as little as 5 concurrent requests) the marshaling performance is very poor. Taking thread dumps the threads are blocked on:
java.lang.ClassLoader.loadClass(ClassLoader.java:291)
There is a single marhsaler registered to marshal all domain objects using reflection and introspection. Realizing that reflection and introspection is slower than direct method calls, I am still seeing unexpected behavior in that the class loader is caller every time and in turn blocking occurs. An example stacktrace is as follows:
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.ClassLoader.loadClass(ClassLoader.java:291)
- waiting to lock <785e31830> (a org.grails.plugins.tomcat.ParentDelegatingClassLoader)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.beans.Introspector.instantiate(Introspector.java:1470)
at java.beans.Introspector.findExplicitBeanInfo(Introspector.java:431)
at java.beans.Introspector.<init>(Introspector.java:380)
at java.beans.Introspector.getBeanInfo(Introspector.java:167)
at java.beans.Introspector.getBeanInfo(Introspector.java:230)
at java.beans.Introspector.<init>(Introspector.java:389)
at java.beans.Introspector.getBeanInfo(Introspector.java:167)
at java.beans.Introspector.getBeanInfo(Introspector.java:230)
at java.beans.Introspector.<init>(Introspector.java:389)
at java.beans.Introspector.getBeanInfo(Introspector.java:167)
at java.beans.Introspector.getBeanInfo(Introspector.java:230)
at java.beans.Introspector.<init>(Introspector.java:389)
at java.beans.Introspector.getBeanInfo(Introspector.java:167)
at org.springframework.beans.CachedIntrospectionResults.<init>(CachedIntrospectionResults.java:217)
at org.springframework.beans.CachedIntrospectionResults.forClass(CachedIntrospectionResults.java:149)
at org.springframework.beans.BeanWrapperImpl.getCachedIntrospectionResults(BeanWrapperImpl.java:324)
at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:727)
at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:721)
at org.springframework.beans.PropertyAccessor$getPropertyValue.call(Unknown Source)
at com.ngs.id.RestDomainClassMarshaller.extractValue(RestDomainClassMarshaller.groovy:203)
...
...
A simple benchmark loading the same endpoint with the same parameters results in the loadClass call.
I was under the impression the classes would be at least cached by the class loader and not loaded on every method call to get the property to be marshaled.
The code to retrieve the property value is as follows:
BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(domainObject);
return beanWrapper.getPropertyValue(property.getName());
Is there a configuration setting that is needed to ensure the classes are only loaded once? or perhaps a different way to get the property that doesn't result in class loading every time? Or perhaps a more performant way to achieve this?
Writing a custom marshaler per domain class would avoid the reflection and introspection but is going to be a lot of repeat code.
Appreciate any input.
So after much digging this is what I found out.
Using the BeanUtils.getPropertyDescriptors and getValue will always try and find a BeanInfo class describing the bean using the class loader. In this case we don't provide BeanInfo classes for our grails domain classes so this call is redundant. I found some information where you can provide a custom BeanInfoFactory to bypass this and exclude your packages but I couldn't find how to configure it with Grails.
Also searching the springframework documentation there is a configuration option you can pass Introspector.IGNORE_ALL_BEANINFO that will tell CachedIntorspectionResults to never look up the bean classes. However this was not available in version 3.1.4 of springframework which was current for grails 2.2.4. The newer versions do appear to have this option.
So, if using BeanUtils you can't by pass this initial lookup on the class loader. However subsequent loaders should be cached by CachedIntrospectionResults. Unfortunately this doesn't happen in our scenario. There looks to be a bug in the test to see if the lookup is cacheable. See more info on this below.
The fix was ultimately to fall back to use pure reflection. Rather than use:
beanWrapper.getPropertyValue(property.getName());
To use:
PropertyDescription pd = BeanUtils.getPropertyDescriptor(domainObject.getClass(), property.getName())
pd.readMethod.invoke(domainObject)
Where the pd is cached.
After fixing this the profiler still showed a lack of caching on CachedIntorspectionResults for the out of the box grails marshaller. This was due to the bad caching implementation in CachedIntrospectionResults. The work around for this was to add the correct class loader to the acceptedClassLoaders in the CachedIntrospectionResults.
public class EnhanceCachedIntrospectionResultsAcceptedClassLoadersListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
CachedIntrospectionResults.acceptClassLoader(Thread.currentThread().getContextClassLoader().getParent());
}
public void contextDestroyed(ServletContextEvent event) {
CachedIntrospectionResults.clearClassLoader(Thread.currentThread().getContextClassLoader().getParent());
Introspector.flushCaches();
}
}
Note that it was required to add the parent to the accepted class loader list rather than the current class loader. Not sure if this is specific to grails or not but this fixed the issue. I'm not sure if there may be a side effect to this fix.
In summary we went from 10 requests/sec in the original setup to 120 requests/sec after using direct reflection and fixing the CachedIntrospectionResults cache.
However the real eye opened was that if we use a 1-1 marshaller per domain class we were seeing another x2 improvement in performance over the generic marshaller where we test objects for whether they're instances of class etc. We're saving a lot of code with the generic marshaller but there's a lot more work to do to get comparable performance to writing a 1-1 marshaller.
Hopefully this will be useful to someone else who runs into this ...

entity and repository pattern with ninject, Dispose Issue

I have build my site using entity and repository pattern with ninject injection. My problem is my connections don't seem to get disposed. I have around 30 repositories (one for each table) and I get sql expiration timout preety quick. I can't use the regular using statement because the code recognize only the interface before the injection.
(in each controler I have my repositories interface instances which get injected via ninject).
I have searched the net but couldn't find a solution that was accurate for me.
can anyone please help me?
code example:
this is in the ninject controller under addBindings():
ninjectKernel.Bind<IMovieRepository>().To<MovieRepository>().InRequestScope();
and one of my repositories:
public class MovieRepository : IMovieRepository, IDisposable
{
private Entities dataContext = new Entities();
public System.Data.Entity.DbContext DbContext
{
get { return dataContext ?? (dataContext = new Entities()); }
}
public void Dispose() { dataContext.Dispose(); }
}
and in the Global.asax file:
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory() as IControllerFactory);
I would guess that your repositories (and therefore presumably your DbContexts) are being bound in transient scope, which I believe means a new one will be created every time Ninject needs to inject one somewhere. I'm not certain but I'm guessing then that these are all staying around for the lifetime of your application and maybe not being disposed.
Try binding your repositories in request scope, so that they are created and disposed per web request.
e.g.
Bind<IFooRepository>().To<ConcreteFooRepository>().InRequestScope();
From the Ninject wiki:
There are four built-in scopes available in Ninject:
Transient - A new instance of the type will be created each time one is requested. (This is the default scope). Binding method is .InTransientScope()
Singleton - Only a single instance of the type will be created, and the same instance will be returned for each subsequent request. Binding method is .InSingletonScope()
Thread - One instance of the type will be created per thread. Binding method is .InThreadScope()
Request - One instance of the type will be created per web request, and will be destroyed when the request ends. Binding method is .InRequestScope()
This kind of problem usually occur if long living objects depend on shorter living objects. E.g. A singleton service uses a repository in request scope.

Change Entity Framework database schema map after using code first

I've finished building my blog using EF and Code First.
EF was running against my local SQL Express instance, with [DBO] schema.
Now i want to publish the blog, and i have done the following :
Generetade the scripts for the tables and all objects from SQL Express and change [dbo] to my [administrator] schema from my server.
Ran the scripts against the server. No issues, all objects were created an populated just fine.
I have modified Webconfig and added my BlogContext connection string to point to the server not local sql express.
Published the site.
The error i am getting is : Invalid object name 'dbo.Articles'. - where Articles is one of my entities. It resides on my sql server, [Administrator].Articles.
As far as i can tell EF still thinks im using the DBO schema. Although i have added the connection string to point to administrator user.
How can i change the schema that EF thinks it should use?
EF will use dbo schema if you didn't configure the schema explicitly through data annotations or fluent API.
[Table("MyTable", "MySchema")]
public class MyEntity
{
}
Or
modelBuidler.Entity<MyEntity>().ToTable("MyTable", "MySchema");
Just for searchers: I am just working with EF5 .NET4.5, and
[Table("MyTable", "MySchema")]
does not work. Even if VS2012 shows there is an overload which takes 2 parameters, on build it gives the error: 'System.ComponentModel.DataAnnotations.Schema.TableAttribute' does not contain a constructor that takes 2 arguments.
But the code mapping works just fine.

Spring #Transactional Deadlock

I have the following setup.
Spring 3.0.5
Hibernate 3.5.6
MySql 5.1
To save a record in the DB via Hibernate I have the following workflow
send JSON {id:1,name:"test",children:[...]} to Spring MVC App and use Jackson to transform it into an object graph (if it is an existing instance the JSON has the proper ID of the record in the DB set
save the object in DB via service layer call (details below)
the save function of service layer interface SomeObjectService has the #Transactional annotation on it with readOnly=false and Propagation REQUIRED
the implementation of this service layer SomeObjectServieImpl calls the DAO save
method
the DAO saves the new data via a call of hibernate's merge e.g. hibernateTempate().merge(someObj)
hibernate merge loads the object first from the DB via SELECT
I have a EntityListener who is wired to spring (I used this technique Spring + EntityManagerFactory +Hibernate Listeners + Injection) and listens to #PostLoad
The listener uses a LockingServie to updates one field of someObject to set it as locked (this should actually only happen when someObject is loaded via Hibernate HQL,SQL or Criteria calls but gets called also on merge)
the LockingServie has a function lock(someObj,userId) which is also annotated with #Transactional with readOnly=false and REQUIRED
the update happens via a call of Query query = sess.createQuery("update someObj set lockedBy=:userId"); and then
query.executeUpdate();
after merge has loaded the data it start with updating someObject and inserting relevant children (<= exacely here is the point where the deadlock happens)
return JSON result (this also includes the newly created object ID) back to client.
The problem seems for me that first
the record gets loaded in a transaction
then gets changed in another (inner-)transaction
and then should get updated again with the data of the outer transaction but can't get updated because it is locked.
I can see via MySQL's
SHOW OPEN TABLES
that a child table (that is part of the object graph) is locked.
Interesting fact is that the deadlock doesn't occur on the someObj table but rather on a table that represents a child.
I am a bit lost here. Any help is more than welcome.
BTW can maybe the isolation level get me out of this problem here?
I ended up using #Bozho's HibernateExtendedJpaDialect
which is explained here >>
Hibernate, spring, JPS & isolation - custom isolation not supported
To set the isolation to READ_UNCOMMITED
#Transactional(readOnly = false, propagation = Propagation.REQUIRED, isolation=Isolation.READ_UNCOMMITTED)
public Seizure merge(Seizure seizureObj);
Not a very nice solution I know but at least this solved my problem.
If somebody wanna have a detailed description please ask...
I don't know the solution to the problem, but I would not have a transactional lock method. If at all you need to lock something manually, make it within another transactional service method.

To many EntityCollections in Entity raise "implement IConvertible" exception in RIA Services

I have a Entity object create with the Entity Framework and used in Silverlight with the RIA Services framework.
The Entity in question has two EntityCollections which are included in the IQueriable sent to the client.
The Entity looks like this:
public class Ad:Entity
{
[Include]
public EntityCollection<PublishingDates> PublishingDates {get;set;}
[Include]
public EntityCollection<Notice> Notice {get;set;}
}
The domain service method includes both collection using Include as this:
[Query]
public IQueryable<Ad> GetAds()
{
return this.ObjectContext.Ad.Include("PublishingDates").Include("Notice");
}
On the client side when the service is called and the result returned the following exception was raise : "The object must implement IConvertible".
If only one EntityCollection is included everything works fine. If both, the previously mentioned exception is raise.
[EDIT]
I use MySQL with MySQL Net Connector version 6.3.5. as the database.
I think its a bug in Net Connector, a very similar bug was reported here http://bugs.mysql.com/bug.php?id=55349
EDIT:
Im not sure this applies to your specific case but for me the latest community server (5.5.9) works a lot better. Note that this is the db not .net connector, which seems not to be involved in the errors I got.
I have the same problem now. The interesting thing is my query works excellent with linux-driven Mysql instance but doesn't work on Windows. May be you will succeed moving to Linux