spring-projects / spring-data-commons

Spring Data Commons. Interfaces and code shared between the various datastore specific implementations.
https://spring.io/projects/spring-data
Apache License 2.0
778 stars 675 forks source link

Introduce separate Spring Data Commons API project for Pageable, Page, and other interfaces [DATACMNS-1054] #1500

Open spring-projects-issues opened 7 years ago

spring-projects-issues commented 7 years ago

Benjamin Schmeling opened DATACMNS-1054 and commented

When using Spring Data, the Pageable and Page interfaces are often part of a project's public API. If you extract your API into a separate project in order to decouple it from the underlying implementation, you will introduce a dependency to Spring Data Commons (that's okay since it contains the aforementioned interfaces) but also to its transitive dependencies Spring Core and Spring Beans.

If you use Page and Pageable in your API project and want to avoid introducing dependencies to Spring Core and Spring Beans you would have to redefine the interfaces and transform them back and forth to Spring interfaces in order to leverage Spring Data's paging and sorting features.

Currently, if you want to use Page and Pageable in your API and want to avoid introducing dependencies to Spring Core and Spring Beans you would have to redefine the interfaces and transform the back and forth to Spring interfaces in order to leverage Spring Data's paging and sorting features.

That said, I would propose to introduce something like an additional Spring Data Commons Api project to which you could move all technology neutral interfaces of Spring Data (maybe there are other potential candidates). To move the Page interface into a future Spring Data Commons Api the dependency to org.springframework.core.convert.converter.Converter would have to be removed.


No further details from DATACMNS-1054

spring-projects-issues commented 7 years ago

Oliver Drotbohm commented

That's good feedback and we've been thinking about splitting up Commons for quite a while already, we've just never been sure where to draw the lines as a typical Spring Data user would end up just including all of the modules again. So feedback like this is appreciated.

I am still torn on the effort this creates VS. the gain we get. On your downside, there's basically the need to manually exclude the Spring artifacts from your dependency. With the current arrangement, I don't think you can get rid off spring-core as we heavily use the assertion types provided by Spring. On our downside, we'd have to relatively artificially keep some types in our codebase free from core Spring dependencies, which creates effort and hardly anyone cares about as people usually just use Spring Data as application level library.

What also plays into this is that an API artifact would definitely need to include core repository interfaces as well, as they are the types that make up the API of Spring Data, not Page and Pageable necessarily. Within those, we have a couple of references to Spring Framework that we can't easily get rid of (e.g. @Indexed).

Is there a real practical benefit in being able to get rid off the dependencies to spring-beans and spring-core given the fact that the types we depend on are very unlikely to change, i.e. even using a library that depends on Spring Data Commons just for compiling and using Pageable with a different major version of Spring shouldn't be a problem.

To round things off: the 2.0 branch already gets rid of Converter in Page in favor of the (now available as we compile with JDK 8 compatibility) Function type

spring-projects-issues commented 7 years ago

Benjamin Schmeling commented

To clarify the project structure. There are at least two artifacts:

A Java client which wants to consume the services should ideally just rely on the interfaces defined in Service-api.jar. The implementation can be Service-impl.jar or any other possible implementation of the interfaces defined in Service-api.jar (such as an implementation of the interfaces which will delegate the business logic to some remote cloud services). That is why we should avoid any dependent libraries introduced by the framework which was used by the implementation (in this case Spring Data).

However, when removing Page and Pageable from the service interfaces in order to get rid of the dependencies, Page and Pageable types must be replaced by some custom types holding the page data. This is especially cumbersome if you add a REST interface implemented with Spring MVC on top of your services because you would profit from using Spring Page and Pageable. In this case you would face the following:

This scenario should motivate the requirement I've described in this ticket.

So as far as I can imagine, at least for this scenario, we won't need to include any repository interface into Service-api.jar.

Good to hear that Converter is removed from Page though and many thanks for your response!

spring-projects-issues commented 7 years ago

Oliver Drotbohm commented

If I get you right, your API project could just include Spring Data Commons and manually exclude spring-core and spring-beans and then just use Page and Pageable, right? So while I get what you're after and applaud the intention, I think this it's way less effort to do just that instead of a split up of the JAR. Especially as you might be perfectly fine with Page and Pageable but I'm pretty sure other would then like to see additional types moved into that to-be-created JAR

spring-projects-issues commented 7 years ago

Benjamin Schmeling commented

Yes that would be acceptable for my scenario. To see whether it is possible we must analyse all dependencies from Page and Pageable. I've learned that with the new 2.0 branch the converter has already been removed. Furthermore, there might be other dependencies from classes referenced by Page and Pageable such as Sort and Order which we should take into consideration.

Generally, the decision of splitting your Spring Data Commons jar into implementation and api could still be an interesting option. One advantage would be to avoid the introduction of new dependencies for Pageable and Page in the future. I think it would be helpful to find other pros and cons for such a decision and to hear the oppinion from other people who faced a similar requirement like me

spring-projects-issues commented 7 years ago

Benjamin Schmeling commented

I've collected a list of interfaces which would be interesting candidates for a separate api jar, to get a feeling on how many interfaces we are talking about:

spring-projects-issues commented 7 years ago

Benjamin Schmeling commented

In the meantime, I've tested your "manual exclusion approach" with the new 2.0 version. I've excluded spring-core and spring-beans from the data-commons dependency in my example projects as follows:

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-commons</artifactId>
    <version>2.0.0.BUILD-SNAPSHOT</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </exclusion>
    </exclusions>
</dependency>

The results of my test showed that I could use Pageable, Page, Slice, Sort, Order, and Direction without any compile errors. So I can finally say that it works and is sufficient for the Service-api.jar artifact case.

In summary, introducing a Spring Data Commons API project would probably cause too much overhead in this regard. As a small step into the right direction I would propose to move the above mentioned classes/interfaces in package org.springframework.data.domain to a new package org.springframework.data.domain.api. This would clarify the separation between Spring-independent classes/interfaces and their implementation/Spring-specific classes. The classes PageRequest and PageImpl, for example, would stay in the org.springframework.data.domain package. They must not be used in the Service-api.jar artifact because they depend on org.springframework.util.Assert;. It is only safe to use classes/ interfaces from the org.springframework.data.domain.api outside a Spring context.

Btw. I saw that the (unnecessary?) imports for org.springframework.core.convert.converter.Converter are still there in classes Page and Slice

spring-projects-issues commented 3 years ago

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.