Per-Data store inheritance strategies in DataNucleus JDO? - jdo

I interface with two data stores, one of them is RDMS and the other one is LDAP. What I want to do is to have a hierarchy persisted using "superclass-table" in the RDBMS and "complete-table" in LDAP.
Is such a thing possible? That is, can you specify multiple inheritance strategies, separately for each data store in the *.orm files or am I forced to use a single inheritance strategy?
I couldn't find this information in the documentation of DataNucleus, they only thing I'm sure of is that you can put inheritance elements in an .orm file instead of the .jdo but that still doesn't answer my question...
The hierarchy is rather simple and consists of an abstract class and several subclasses like this:
abstract class Foo implements IFoo
{
...
}
class Foo1 extends Foo
{
...
}
class Foo2 extends Foo
{
...
}
...
I tried to configure inheritance in the two *.orm files AND in the .jdo file (having in mind that it's going to get overriden by the former) but I get an exception
Caused by: org.datanucleus.metadata.InvalidMetaDataException: Class "...Foo1..." has been specified with an inheritance strategy of "superclass-table", yet no superclass exists or none exists with its own table!
at org.datanucleus.metadata.AbstractClassMetaData.validateUserInputForInheritanceMetaData(AbstractClassMetaData.java:903)
at org.datanucleus.metadata.ClassMetaData.populate(ClassMetaData.java:214)
at org.datanucleus.metadata.MetaDataManager$1.run(MetaDataManager.java:2393)
at java.security.AccessController.doPrivileged(Native Method)
at org.datanucleus.metadata.MetaDataManager.populateAbstractClassMetaData(MetaDataManager.java:2387)
at org.datanucleus.metadata.MetaDataManager.populateFileMetaData(MetaDataManager.java:2224)
at org.datanucleus.jdo.metadata.JDOMetaDataManager.loadMetaDataForClass(JDOMetaDataManager.java:741)
at org.datanucleus.jdo.metadata.JDOMetaDataManager.getMetaDataForClassInternal(JDOMetaDataManager.java:353)
at org.datanucleus.jdo.metadata.JDOMetaDataManager$MetaDataRegisterClassListener.registerClass(JDOMetaDataManager.java:184)
at javax.jdo.spi.JDOImplHelper.registerClass(JDOImplHelper.java:376)
I then tried to remove the inheritance elements from the .jdo but the enhancer fails with the following message:
Class "...Foo1..." has been specified to use an inheritance strategy of "superclass-table", persisting to the table of class ...Foo..., however this class doesnt have a discriminator specified.
The individual configurations are correct (new-table with discriminator at base-class and superclass-table at subclasses for the first case and complete-table only at base-class for the second).

You can put that information in the orm file, yes, and indeed that does answer your question since you have one ORM file for RDBMS, and one for LDAP. So package-rdbms.orm, and package-ldap.orm, and then simply set persistence property "javax.jdo.option.Mapping" to either "rdbms" or "ldap". Simple

Related

ndb.PolyModel as an ancestor of a regular entity -- bad idea?

I'd like to make a ndb.PolyModel child entity an ancestor of another ndb.Model entity, because I need the child entity to be strongly consistent for queries.
Something about this makes me nervous. Is this a bad idea?
From what I understand, the secret sauce behind a ndb.PolyModel is that instances of it have a special property called 'class'.
This is a repeated property of strings of all the class names in the inheritance chain, which ndb then uses to instantiate the appropriate subclass when it pulls it out of datastore.
The key for each instance will still be of the parent class.
So for the following example:
class Animal(ndb.PolyModel):
class Cat(Animal):
class Dog(Animal):
If you do
d = Dog(...)
d.put()
d.key will still be something like ndb.Key('Animal', 123456789)
In your Datastore Viewer, you will only have an Animal table and not a Dog table nor a Cat table.
So I would imagine you should be safe to use ndb.Key('Animal', 123456789) as the ancestor for some other model.

Determine whether an instance is an instance of a data class

Given the following classes
abstract class SomeAbstractClass { abstract val name: String }
data class DataClass( override val name: String ) : SomeAbstractClass()
class NoDataClass( override val name: String ) : SomeAbstractClass()
For any instance of SomeAbstractClass, can I determine whether it is a data class without relying on type checking?
Some background: this seemed the best way of combining inheritance and data classes to me, as suggested in a different answer. Now, within the initializer block of SomeAbstractClass, I want to throw an exception in case the derived type is not a data class to ensure 'correct' (immutable) implementations of derived types.
Using reflection, the Kotlin class description (KClass) can be obtained using the ::class syntax on the instance you want to investigate (in your case, this::class in the initializer block of the abstract class). This gives you access to isData:
true if this class is a data class.
However, as Oliver points out, data classes can still contain var members, so you likely also want to check whether all member variables (and their member variables recursively) are defined as val to ensure immutability of all deriving classes.

I want to detect if a JVM Class is a Kotlin class or not

I want to do special functionality if I encounter a Kotlin class as compared to a generic Java class. How can I detect if it is a Kotlin class?
I was hoping that calling someClass.kotlin would throw an exception or fail if the class wasn't Kotlin. But it wraps Java classes just fine. Then I noticed that if I do someClass.kotlin.primaryConstructor it seems to be null for all java classes even if they have a default constructor, is that a good marker? But can that return null for a Kotlin class as well?
What is the best way to say "is this a Kotlin class?"
Kotlin adds an annotation to all of its classes, and you can safely check for its existence by name. This is an implementation detail and could change over time, but some key libraries use this annotation so it is likely to be ok indefinitely.
fun Class<*>.isKotlinClass(): Boolean {
return this.declaredAnnotations.any {
it.annotationClass.qualifiedName == "kotlin.Metadata"
}
}
Can be used as:
someClass.isKotlinClass()
The class kotlin.Metadata is not accessed directly because it is marked internal in the Kotlin runtime.
While the other answer may work (possibly outdated), many reflection features will not work on file classes or generated classes (lambdas, etc).
However, there is a parameter in the #Metadata annotation that can tell you if the class is what you are looking for:
A kind of the metadata this annotation encodes. Kotlin compiler recognizes the following kinds (see KotlinClassHeader.Kind):
1 Class
2 File
3 Synthetic class
4 Multi-file class facade
5 Multi-file class part
The class file with a kind not listed here is treated as a non-Kotlin file.
#get:JvmName("k")
val kind: Int = 1
We can take advantage of this to make sure we are only getting real classes:
val Class<*>.isKotlinClass get() = getAnnotation(Metadata::class.java)?.kind == 1
I can confirm this works in 1.6.20

How Can I make Spring-MVC #PropertySources load first, before any other configuration

I have a spring-mvc application that is using java configuration, not xml. There are #Configuration annotations sprinkled through several files. In particular, there is a #PropertySources annotation in one file in a class that implements WebMvcConfigurerAdapter. There are two classes which contain an #Autowired Environment variable. One of these classes is itself a #Configuration class, and I would like it to have access to the fully-loaded Environment at the time it runs.
This isn't happening. When this code executes, the Environment is still null. I've tried reordering the #ComponentScan packages, tried moving the #PropertySources annotation, and nothing has helped me load the property sources in time.
I want this to happen first, before any other configuration.
What must I do to make it so?
UPDATE: After trying many things, including the Order annotation, I find the problem seems to be not so much that the #PropertySources are being loaded too late as that a class I have that is derived from org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer is being loaded too soon. Nothing in my code even references this class but Spring is somehow deciding that this, above all other classes, must be initialized first. No amount of messing around with #Order seems to change this. This in spite of the javadocs, which indicate that the behavior I want is the default:
Caveats
Subclasses of AbstractDispatcherServletInitializer will register their
filters before any other Filter. This means that you will typically
want to ensure subclasses of AbstractDispatcherServletInitializer are
invoked first. This can be done by ensuring the Order or Ordered of
AbstractDispatcherServletInitializer are sooner than subclasses of
AbstractSecurityWebApplicationInitializer.
You can use ContextInitializer, catch the moment when Boot prepared its environment and "inject" your property source programmatically as you want.
If you have a ConfigurableApplicationContext then it provides a ConfigurableEnvironment, which contains the propertySources as a list. If you want your PropertySource to rule all above the others than add it as first. If you want to place it to a special position then you can add it before an other, identified by its "name".
public class ConfigInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext ctx) {
// rule over all the others:
ctx.getEnvironment().getPropertySources().
addFirst(new ResourcePropertySource("file:/etc/conf/your_custom.properties"));
// rule over application.properties but not argument or systemproperties etc
ctx.getEnvironment().getPropertySources().
addBefore("applicationConfig: [classpath:/application.properties]",
new ResourcePropertySource("classpath:your_custom.properties"));
// names can be discovered by placing a breakpoint somewhere here and watch
// ctx.getEnvironment().getPropertySources().propertySourceList members,
// each has a name ...
}
}
You can bring into play this class by:
registering it in the application.properties :
context.initializer.classes=a.b.c.ConfigInitializer
or from application start :
new SpringApplicationBuilder(YourApplication.class).
initializers(new ConfigInitializer()).
run(args);
By the way this is a proper way to inject more of your custom properties, like properties coming from a database or a different host etc...
Not that I am an expert in Java config but maybe:
Spring 4 utilizes this feature in its #PropertySource annotation. To
remind you, #PropertySource annotation provides a mechanism for adding
a source of name/value property pairs to Spring's Environment and it
is used in conjunction with #Configuration classes.
Taken from: http://blog.codeleak.pl/2013/11/how-to-propertysource-annotations-in.html
Are you using #PropertySource or #PropertySources?
Have You tried 'order' property for spring bean initialisation?

Class with PersistenceCapable annotation gets Attempt to store an instance of a non persistable type

Using ObjectDB
[ObjectDB 2.4.1] javax.jdo.JDOUserException
Attempt to store an instance of a non persistable type com.A
#PersistenceCapable
public abstract class B
{
...
#Embedded
protected com.A a = new A();
}
Unfortunately we have been using class A from a library for many years and don't have source available anymore and I cannot put PersistenceCapable annotation on com.A.java. What can I do?
Edit
I think the answer is to add package.jdo for class A. But I still don't understand why is JDO making me either add annotation or make an entry in .jdo file for every class that i want to persist. I wish this could somehow be driven by Serializable interface.
Serialization in ObjectDB is disabled by default, in order to encourage using JPA/JDO persistable types (entity classes, persistence capable classes, embeddable classes), which are more efficient, whenever possible.
However, when serialization is required you can enable it, as explained in the ObjectDB manual.
and then you should be able to store instances of serializable instances in your ObjectDB database.

Resources