Code Monkey home page Code Monkey logo

rdfbeans's Introduction

RDFBeans framework

RDFBeans is an object-RDF mapping framework for Java. It provides ORM-like databinding functionality for RDF data models with two basic techniques:

  • Classic object persistence: basic CRUD (Create, Retrieve, Update and Delete) operations on the state of JavaBean-like POJO objects

  • Dynamic proxy mechanism for transparent access of RDF data using Java interfaces mapped directly to the underlying RDF model structures

RDFBeans is built upon Eclipse RDF4J (former Sesame) API to provide object persistence with a number of RDF storage implementations, including third party RDF database solutions.

RDFBeans is based on Java Annotations mechanism. No special interfaces and superclasses is required, that guarantees minimum modifications of existing codebase and compatibility with other POJO-oriented frameworks.

Other features:

  • Built-in support of basic Java literal types mapped to standard XML-Schema literals; with ability to extend it with custom algorithms to represent domain-specific data structures
  • Cascade databinding to reduce development time and to ensure referential integrity of complex object models
  • Support of basic Java Collections, optionally represented with RDF containers
  • Inheritance of RDFBeans annotations from superclasses and/or interfaces
  • Transaction-safe model updates
  • Virtual inversed properties to model owl:inverseOf-like behavior (experimental)
  • Support of RDF namespaces

Read more

Usage

Include a Maven dependency into your project POM:

<dependencies>
        <dependency>
            <groupId>org.cyberborean</groupId>
            <artifactId>rdfbeans</artifactId>
            <version>2.2</version>
        </dependency>
</dependencies>

rdfbeans's People

Contributors

cyberborean avatar reckart avatar the-alchemist avatar wherget avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

rdfbeans's Issues

Bad performance of method create()

Hi,

I've encountered a serious performance problem within the following code snippet:

Resource beanResource = this.manager.getResource(iri, beanType, subgraphResources); //search for requested bean in subgraph(s)
result = this.manager.create(beanResource, beanType, subgraphResources); //this takes up to two seconds

Can you explain why calling create() for my annotated interface takes so much time? Is there a solution or am I doing something wrong?

Thanks in advance,

Thorben

Annotation for 'toString()' value of proxy objects

toString() methods of RDFBean proxy objects return subject IRI values, without possibility of customization.

There could be a method annotation to indicate a property for string representation of the object, for instance:

@RDF("foaf:name")
@toString
public String getName();

Thread-safe RDFBeanManager

Currently, RDFBeanManager is instantiated on a single pre-opened RepositoryConnection that cannot be shared over multiple threads by design. To enable concurrent access to a RDFBeans repository, one has to create multiple RDFBeanManager instances with connections obtained for each thread separately. This is an annoying limitation that makes development of multi-thread RDFBeans applications more complex and error-prone. This also interfering with the role of RDFBeanManager as a central application data model.

The idea is to move the per-thread RepositoryConnection management into RDFBeanManager implementation:

  • RDFBeanManager is instantiated on a Repository object instead of RepositoryConnection
  • RDFBeanManager is responsible for opening new RepositoryConnections. New connections are created as needed internally and pooled in a thread-local manner: an isolated RepositoryConnection instance is obtained by each thread to guarantee thread-safe model updates.
  • RepositoryConnection for the current thread is exposed publicly through getRepositoryConnection() method for external transaction management.
  • RDFBeanManager has an explicit close() method for closing all pooled connections.

Make use of RDF4J contexts

ATM, all operations on RDFBeans are performed with no associated context, thus the nature of RDF4J as a quad store is ignored.

It should be possible to point RDFBeanManager to use specific context of RDF4J repository, e.g. by using an optional constructor argument.

Datatype character is missing in DefaultDataTypeMapper

Hi,

I've just recognized that no mapping is defined for datatype character. In case I try to set value of type char by calling the corresponding setter of my bean I get a RDFBeanException saying:

aused by: org.cyberborean.rdfbeans.exceptions.RDFBeanException: Unexpected value to set: I
at org.cyberborean.rdfbeans.proxy.RDFBeanDelegator.toRdf(RDFBeanDelegator.java:506)
at org.cyberborean.rdfbeans.proxy.RDFBeanDelegator.setValue(RDFBeanDelegator.java:414)
at org.cyberborean.rdfbeans.proxy.RDFBeanDelegator.invoke(RDFBeanDelegator.java:131)
... 66 common frames omitted

For this reason I suggest to add an additional mapping within class DefaultDataTypeMappern (object DATATYPE_MAP). Would it be possible to map Java class character to XMLSchema.String ?

Best,

Thorben

@RDFSubject does not correctly work with namespace abbreviations

@RDFSubject used with namespace abbreviations does not create correct IRIs.

In the case of

@RDFNamespaces("persons=http://rdfbeans.example.com/persons/");
...
@RDFSubject(prefix="persons:") 
...

the IRI <persons:someid> is created, instead of <http://rdfbeans.example.com/persons/someid>.

Dynamic proxies should return default values for primitive type properties

In the current implementation, reading a primitive type property of a dynamic proxy instantiated from a RDFBean interface causes NullPointerException if the property has not been initialized. This is due to the InvocationHandler.invoke() contract:

If the value returned by this method is null and the interface method's return type is primitive, then a NullPointerException will be thrown by the method invocation on the proxy instance.

We may want to return the default values for primitive type properties instead of throwing a NPE (see https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html).

Performance Issues

I have a quick question regarding performance when invoking a method on a bean, as I will be writing my bachelor thesis on this topic.

Basically I send a HashMap with values to the server and there they are set in the corresponding bean. Before this bean is checked if it already has a value assigned for this variable and the invoke of the getter method takes 100-300ms, sometimes longer. Was there such a problem before?

Inherit @RDFBean to subclasses

Hi!

It would be very useful if @RDFBean annotations would be inherited to subclasses. Currently this does not work and throws a RDFBeanException when assigning a property value to a (sub)class that isn't explicetely annotated. The mentioned exception is thrown in the following situation:

  • Consider two interfaces A, B where B extends A.
  • A is annoted with @RDFBean, B isn't annotated
  • assigning a property value of type RDFBean to B causes the exception

Possible solution: The problem arises within the class RDFBeanInfo in method isRdfBeanClass(Object). The method makes use of ReflectionUtil.getClassAnnotation() that does currently does only consider direct parent interfaces. If their anchestor interfaces would be considered as well the problem was solved.

Get rid of ContainerType.NONE

RDFContainer.ContainerType.NONE enum constant only adds complexity, as simply absence of @RDFContainer annotation has the same effect.

URIs marshalled as Literals

I just stumbled upon this, and I think it may not be the right behaviour...

java.net.URIs are (as of the writing of this Issue) marshalled as "http://example.com"^^xsd:anyURI, i.e. as Literals (using the DatatypeMapper).

The issue is probably just the order of the checks, where special URI handling should come before conversion to a literal.

Test coverage reporting

In addition to the mere "builds and tests pass" result of Travis, it would be nice to have an idea how well the tests cover the available functionality.

There are several candidate tools in the github ecosystem, e.g. Coveralls and Codecov.

Incorrect context handling within RDFBeanDelegator

Hi,
probably I've found a bug that arises when working with different contexts. Consider the following bean definitions (reduced to skeleton):

public interface A{
	public Collection<B> getB();
}
public interface B{	
	public Collection<A> getA();
}

Now I'm using an RDFBeanManagerContext that creates A within subgraph a and B within subgraph b. Afterwards I'm persisting my data and everything works fine.

The problem arises when trying to update the previously persisted data once more by calling A.getB() in order to add additional entries for example. In this case RDFBeanDelegator tries to create instances of B (line 327). Unfortunately the correct context is not considered in this moment because the context is taken from A which results in an additional creation of statements within the wrong context (a) instead of reading the already existing statements from the correct context (b).

From my point of view the problem could be solved in the following way (consider the correct context):

  • search within the whole graphstructure (not only the current context) for a statement like B rdf:type (e.g.: rdfBeanManagerContext.getRepositoryConnection().getStatements((IRI) object, RDF.TYPE, null, false).asList().get(0).getContext())
  • this can only return one statement that reflects the context where is definition was stated
  • create a seperate RDFBeanContextManager (with correct context) and call create() on this manager --> this should return unmarshalled objects loaded from the existing statements instead of creating new statements within the wrong context.

If you have any questions, pls. just get in contact with me.

Best,

Thorben

Update:
I've checked my solution and it seems to work:
`
RepositoryResult stmtTypeOfObject =
rdfBeanManagerContext.getRepositoryConnection().getStatements((IRI) object, RDF.TYPE, null, false);
Resource ctxObject = stmtTypeOfObject.next().getContext();
RDFBeanManagerContext bm = new RDFBeanManagerContext((IRI) ctxObject, rdfBeanManagerContext);

Object proxy = bm.create((IRI) object, iface);
`
It's not a perfect solution but it solves the problem...

Incomplete/Incorrect handling of @RDFContainer properties

Hi all!
I've encountered a problem while using properties that are annotated by @RDFContainer. I've got a simple property of Java type collection that is annotated like this:

@RDFContainer(ContainerType.SEQ)
@RDF("myns:data/modification")
public Collection<DataModification> getModification();

This works perfectly well when persisting entries for the first time. Nevertheless there seems to be a bug when updating existing entries. In this case the old list entries do not get deleted completely and are kept within the database although they have no more links:

<http://test.de/s/2667379723> http://test.de/meta/property/data/modification> _:node1dl4430n8x1
_:node1dl4430n8x1 <rdf:_1> myValue 
_:node1dl4430n8x1 <rdf:type> <rdf:Seq>

Regarding the abstract example supplied only the first statement would get deleted whereas the two last onces would remain. I assume the problem has to be fixed within the method setValue() of class RDFBeanDelegator. Within line 355 and 358 it should be checked if the object of deleted statement is a list. In this case the list values should be deleted additionaly. From my point of view should the deletion even work recursively because an entry of list could be a list itsself.

It would be great if this problem could be fixed in near feature and be merged into the current development branch that does already contain the subgraph/context enhancement.

Best,

Thorben

Class hierarchy isn't considered

Hi,

I've created several (Java) beans with a simple hierarchy (e.g. A-->B). When I'm instantiating objects (a, b) of these classes and have a look at the resulting RDF statements, everything looks fine but I'm missing the type hierarchy in RDF. I do see:

A type a
B type b

but I'm missing:

B subclassOf A

I would assume that the subclass statements are generated as well because they could easily by extracted from the defined class hierarchy in Java. What do I have to do in order to get these statements generated as well?

Additional comment:

Just looked into the code and found this line within org.cyberborean.rdfbeans.impl.Marshaller that should be extended to consider the type hierarchy as well. Currently it just focusses on the concrete JavaBean type.

conn.add(subject, RDF.TYPE, type, contexts);

Inferred statements

I have refined an RDF bean which is meant to retrieve all class definitions from an OWL/RDFS ontology. That resources are classes is not always explicitly defined in the ontologies that I am trying with but rather an output of an inferencer. However, whenever RDFBeans is retrieving statements, it excludes inferred ones, e.g. :

statements = conn.getStatements(resource, predicate, null, false);

Is there are reason for excluding inferred statements?

New transactional update mechanism

Instead of having setAutocommit method, RDFBeanManager should respect current active transaction status of Sesame RepositoryConnection:

If there is no active transaction started on RepositoryConnection, RDFBeanManager automatically starts new one for every invocation of 'add', 'update' or 'delete' methods, or setXXX methods of dynamic proxies. Otherwise, model updates performed by those methods are added to the existing transaction.

allow to define an URL instead of an URI as "xxxx"ˆˆxsd:anyURI.

Cyberboreans allows you to insert Strings and URI’s.

Some of the URI’s refer to other subjects in the same VocBench register and these work fine, but other URI contain a link to an external website, like https://wetten.overheid.nl/BWBR0041292/2018-09-15.

Within VocBench these appear with a globe and the values in sparql are displayed as https://wetten.overheid.nl/BWBR0041292/2018-09-15

So the issue is whether one can make a difference between sending an URI-object which is the subject of another set of triples from sending an URI that links to an URL as a link to an article on a website?

My Solution in rdfbeans can be provided, after this issue is submitted

Javadoc update

Javadoc should reflect recent API updates (migration to RDF4J) and converted to Markdown.

Support for literals with language tag ?

Hi, is there any support / best practices for dealing with language tags on literals ?
And more specifically, mapping/updating properties with multiple literals with a different language tag (e.g. dcterms:title in multiple languages ?)
Thanks

Better handling when a resource has several types

Currently, RDFBeans is looking for a binding for the first rdf:type it sees. This may lead to the situation where there is a binding available for the resource, but is not realized. We should probably check all types to see if a binding is available for any of them.

Support of `Optional`

The framework should support instances of Optional class in getter return and setter argument types.

@RDF("urn:someTitle")
Optional<String> getTitle(); 
void setTitle(Optional<String> title);

Existing context is not considered when calling setter

Hi,
I'm wondering why an update of statements does not consider their existing context. I've got a set of statements that was correctly created within a named graph. When retrieving these statements later on and trying to update them, the existing statements are kept untouched but instead new statements generated whithin the default graph.

I've got the following situation:

dm = obj.getModification() //dm was already created earlier within a special context/named graph
dm.setDate(new Date()); /does not update existing statement - creates new one in default context instead

I would expect the existing statement to be updated in its original context instead of creating a new one within default graph/context

Am I doing something wrong or is this an issue?

Best,

Thorben

Pluggable class binding strategy

Currently, binding RDF Types to RDFBeans Java classes are performed by a built-in procedure based on adding special triples to the underlying RDF model. There are scenarios when the user may want to change the way it works:

  • To have better control over the implementation: i.e. specify another Repository and/or context for binding data
  • To implement a custom strategy (like static binding)

There should be a pluggable mechanism for Java class binding, similar to the one we have for datatypes (DatatypeMapper).

Anonymous RDFBeans by menas of interfaces

Hi all,

I'm using RDFBeans (annotated interfaces) with success and would like to make use of anonymous/blank nodes now. I've followed every step from the documentation, but everytime I'm trying to assign an anonymous bean to another bean (calling setter of property) it throws an exception saying, that @RDFSubject annotation is missing. My code is:

KT aBean = this.manager.create(ID_UNKNOWN, beanType);
aBean.setId(null); //reset to make anonymous - id not set
bBean.setProp(aBean); //throws exception

I've tried a second way to solve my problem. This time I've explictely created an anonymous node and tried to create the bean afterwards:

Resource r = SimpleValueFactory.getInstance().createBNode();
Context ctx = this.manager.create(r, Context.class);

Unfortunately, this appraoch resulted in a different exception:
java.lang.ClassCastException: org.eclipse.rdf4j.model.impl.SimpleBNode cannot be cast to org.eclipse.rdf4j.model.IRI

As none of my solutions work I'm guessing that anonymous RDFBeans only work for classes and not for interfaces. Is that right? Or could someone tell me what I am doing wrong and point me into the correct direction?

Thanks in advance,

Thorben

Annotations everywhere

Right now, the @RDF or @RDFSubject annotation need to be on the getter of a property. It would be much more convenient if they could also be on the field or setter.

getAll() throws exception

Hi all,

I'm using interfaces (not classes) while working with RDFBeans. When accessing my persisted beans via getAll() and trying to iterate the results I get the following exception:

Caused by: java.lang.NoSuchMethodException: ()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
... 66 common frames omitted

As interfaces do not have an constructor I do understand the error, of course. But would except that some proxy magic is in place to enable the iteration. How can I make the iteration work? Here is the code I'm using:

public static void toList(CloseableIteration<? extends Individual, Exception> iter, List results) {
try {
while(iter.hasNext()) {
Individual individual = iter.next();
results.add(individual);
}
}catch(Exception ex) {
logger.error("Building result list from iterator.", ex);
}
}

Documentation should reflect move to RDF4J

Currently the Documentation talks about RDFBeans being based on RDF2Go, which is no longer the case (it now uses RDF4J). This should be brought up to date before a release.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.