I am trying to understand the spring data solr showcase project.
https://github.com/christophstrobl/spring-data-solr-showcase
After spending quite a bit of time, I could not find how the productRepository is implemented and injected in https://github.com/christophstrobl/spring-data-solr-showcase/blob/master/src/main/java/org/springframework/data/solr/showcase/product/ProductServiceImpl.java
#Service class ProductServiceImpl implements ProductService {
private static final Pattern IGNORED_CHARS_PATTERN = Pattern.compile("\\p{Punct}");
private ProductRepository productRepository;
#Autowired
public void setProductRepository(ProductRepository productRepository) {
this.productRepository = productRepository;
}
The ProductRepository is defined as interface (https://github.com/christophstrobl/spring-data-solr-showcase/blob/master/src/main/java/org/springframework/data/solr/showcase/product/ProductRepository.java) and I did not find any code implementing this interface
interface ProductRepository extends SolrCrudRepository<Product, String> {
#Highlight(prefix = "<b>", postfix = "</b>")
#Query(fields = { SearchableProductDefinition.ID_FIELD_NAME,
SearchableProductDefinition.NAME_FIELD_NAME,
SearchableProductDefinition.PRICE_FIELD_NAME,
SearchableProductDefinition.FEATURES_FIELD_NAME,
SearchableProductDefinition.AVAILABLE_FIELD_NAME },
defaultOperator = Operator.AND)
HighlightPage<Product> findByNameIn(Collection<String> names, Pageable page);
#Facet(fields = { SearchableProductDefinition.NAME_FIELD_NAME })
FacetPage<Product> findByNameStartsWith(Collection<String> nameFragments, Pageable pagebale);
}
Below is how the spring context is configured:
https://github.com/christophstrobl/spring-data-solr-showcase/blob/master/src/main/java/org/springframework/data/solr/showcase/Application.java
If anyone could point me to the direction where this interface is implemented and injected, that would be great.
The showcase makes use of Spring Data repository abstractions using query derivation from method name. So the infrastructure provided by Spring Data and the Solr module take care of creating the required implementations for you. Please have a look at the Reference Documentation for a more detailed explanation.
The showcase itself is built in a way that allows you to step through several stages of development by having a look at the diffs transitioning from one step to the other. So having a look at Step 2 shows how to make use of Custom Repository Implementation, while Step 4 demonstractes how to enable Highlighting using #Highlight.
The goal of Spring Data is to reduce the amount of boilerplate coding (means to reduce repetition of code).
For the basic methods like save,find the implementation will provide by spring and spring will create beans(Objetcs) for these interfaces. To tell the spring that these are my repositories inside this package, we are writing #EnableJpaRepositories(basePackeges="com.spring.repositories") or <jpa:repositories base-package="com.acme.repositories"/> for JPA repositories
Foring solr repositores we have to write #EnableSolrRepositories(basePackages="com.spring.repositories" or <solr:repositories base-package="com.acme.repositories" /> Spring will create objetcs for these interfaces, we can inject these interface objetcs using #Autowire annotation.
Example:
#Service
Pulic class SomeService{
#Autowire
private SampleRepository;
/* #postConstruct annotation is used to execute method just after creating bean
and injecting all dependencies by spring*/
#PostConstruct
public void postConstruct(){
System.out.println("SampleRepository implementation class name"+ SampleRepository.getClass());
}
}
The above example is to see the implementation class of SampleRepository interface (This class is not user defined, it is class given by spring).
For reference documentation link http://docs.spring.io/spring-data/solr/docs/2.0.2.RELEASE/reference/html/. Try to read this simple documentation you can get more knowlede on spring-data.
Related
I am trying to use the in built methods of MongoRepository<T,ID> interface to interact with mongo.
interface MovieRepository : MongoRepository<Movie, String> {
}
But when I try to implement the "MovieRepository" using class. Its asking me to implement all the member functions defined in "MongoRepository" as well
class ControllerClass(private val MovieRepository: MovieRepository): MovieRepository {}
This is what i get when i initialize my controller class:
Class 'ControllerClass' is not abstract and does not implement abstract member public abstract fun <S : Movie!> save(entity: S): S
Is there any way so that i do not need to defined all those MongoRepository's functions again in my ControllerClass?
You don't usually implement a repository interface yourself: you let Spring do it for you!
First, you define your interface, as you have done:
interface MovieRepository : MongoRepository<Movie, String> {
// Add any abstract methods you'll need here…
}
Then, you autowire a property of that type. In Kotlin, you can either do it in the primary constructor, e.g.:
#Controller
class ControllerClass #Autowired constructor(
private val movieRepository: MovieRepository
) {
// …code…
}
Or as a plain property. (In this case, because you can't specify an initial value, you have to make the property a var; it must either be nullable — requiring !! everywhere you use it — or, better, make it lateinit.)
#Controller
class ControllerClass {
#Autowired private lateinit var movieRepository: MovieRepository
// …code…
}
Spring will then create some synthetic class implementing that interface, and set your property to it. (You don't need to worry about how it does that — just as you don't need to worry about all the other magic it does, much of which involves creating synthetic subclasses. That's why Spring objects generally need to be made open — and why there's a Spring plugin which takes care of doing that.)
It's more usual to use the repository in a service class, and then call that from your controller class — at least, that pattern tends to scale better, and be easier to follow and to test. But doing so directly should work too. Either way, you can call whichever repository method you need, e.g. movieRepository.findAll().
See the Spring docs; they use Java, but it's mostly trivial to convert to Kotlin.
How can I add a specific code in the implementations of methods that are listed in jparepository of spring data jpa without creating a new method in an interface that extending jparepository.
I want to edit the body of some methods listed in jparepository.
for example in save method body:
add[system.out.println("before persisting");] just before calling persist method
and [system.out.println("after persisting");] just after a persist calling
Thanks
You can introduce some aspect. It will provide you implement whatever you want.
You can see similar example here
Spring AOP + JPARepository
Something similar to this
#Aspect
#Component
#Configurable
public class AuditLogAspect {
#Pointcut("execution(* org.springframework.data.repository.CrudRepository+.save(*))")
public void whenSaveOrUpdate() {};
#Before("whenSaveOrUpdate() && args(entity)")
public void beforeSaveOrUpdate(JoinPoint joinPoint, BaseEntity entity) {...}
}
I'm writing a custom implementation for a Spring Data JPA repository. So I have:
MyEntityRepositoryCustom => interface with the custom methods
MyEntityRepositoryUmpl => implementation of the above interface
MyEntityRepository => standard interface which extends JpaRepository and MyEntityRepositoryCustom
My problem is this: within the implementation of MyEntityRepositoryUmpl I need to access the entity manager that was injected into Spring Data. How to get it?
I can use #PersistenceContext to get it autowired, but the problem is that this repository must work in an application that sets up more than one persistence units. So, to tell Spring which one I need, I would have to use #PersistenceContext(unitName="myUnit"). However, since my repositories are defined in a reusable service layer, I can't know at that point what will be the name of the persistence unit that the higher-level application layer will configure to be injected into my repositories.
In other words, what I would need to do is to access the entity manager that Spring Data itself is using, but after a (not so quick) look at Spring Data JPA documentation I couldn't find anything for this.
Honestly, the fact that the Impl classes are totally unaware of Spring Data, although described as a strength in Spring Data manual, is actually a complication whenever you need to access something that is usually provided by Spring Data itself in your custom implementation (almost always, I would say...).
Since version Spring Data JPA 1.9.2 you have access to EntityManager through JpaContext, see: http://docs.spring.io/spring-data/jpa/docs/1.9.2.RELEASE/reference/html/#jpa.misc.jpa-context.
Example:
#Component
public class RepositoryUtil
{
#Autowired
private JpaContext jpaContext;
public void deatach(T entity)
{
jpaContext.getEntityManagerByManagedType(entity.getClass()).detach(entity);
}
}
P.S.
This approach will not work if you have more than one EntityManager candidate for some Class, see implementation of JpaContext#getEntityManagerByManagedType -> DefaultJpaContext#getEntityManagerByManagedType.
The best I could find is to set up a "convention": my repositories declare that they expect a persistence unit named myConventionalPU to be made available. The application layer then assigns that alias to the entity manager factory that it sets up and injects into Spring Data, so my custom implementations can receive the correct EMF with autowiring by using that alias. Here's an excerpt of my application context:
<bean id="myEntityManagerFactory" name="myConventionalPU"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
[...]
</bean>
<jpa:repositories base-package="com.example"
entity-manager-factory-ref="myEntityManagerFactory"
transaction-manager-ref="transactionManager" />
And within my custom implementation:
#PersistenceContext(unitName = "myConventionalPU")
private EntityManager em;
I opened DATAJPA-669 with this requirement.
Spring Data JPA uses Auto configuration classes to auto generate entityManagerFactory, dataSource and transactionManager.
If you want get access to entityManager and control the instantiation and settings, you need to define your own PersistenceConfiguration. Below is the sample code using Java Config
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = { "com.test.repositories.*" })
public class PersistenceJpaConfig {
#Autowired
JpaVendorAdapter jpaVendorAdapter;
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setName("testdb")
.setType(EmbeddedDatabaseType.HSQL)
.build();
}
#Bean
public EntityManager entityManager() {
return entityManagerFactory().createEntityManager();
}
#Bean
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource());
lef.setJpaVendorAdapter(jpaVendorAdapter);
lef.setPackagesToScan("com.test.domain.*");
lef.afterPropertiesSet();
return lef.getObject();
}
#Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory());
}
}
If you have multiple data sources, follow this article.
I am using Spring-Data-JPA and in my persistence tier use both Repositories to access the database and then sometimes use
1) the Service class with repositories within it, and then autowire the service
2) autowiring the repository directly
Do both approaches behave in the same way? What is the difference between using the Repository directly versus using the Repository from within a service?
Repository:
package com.me.repository;
import com.me.myentities.MyEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {
}
Service:
package com.me.service;
import com.me.entities.*;
import org.springframework.stereotype.Service;
import com.me.repository.*;
import javax.annotation.Resource;
#Service
public class MyService {
#Resource
private MyEntityRepository myEntityRepository ;
public void update(MyEntity myEntity)
{
myEntityRepository.save(myEntity);
}
}
Either way you're working with the same sort of concrete Repository object, which is created by Spring when the container loads. And if you don't do anything with scoping, you're working with references to the exact same object.
Do do the approaches work the same way? If the service does nothing but make a pass-through call to the delegate Repository, then it's not going to result in any different end behavior. And if this pass-through behavior is all the Service does, it doesn't have an inherent reason for existing.
Spring Data JPA provides standard ways to add custom behavior to the Repositories, or to restricting the behavior of the repository to a smaller set of methods. The Spring Data JPA documentation (while brief) provides demonstrations of these techniques.
The end result is the same but generally you'll find working directly with a Repository more concise.
I start loving OSGi services more and more and want to realize a lot more of my components as services. Now I'm looking for best-practice, especially for UI components.
For Listener-relations I use the whiteboard-pattern, which IMHO opinion is the best approach. However if I want more than just notifications, I can think of three possible solutions.
Imagine the following scenario:
interface IDatabaseService {
EntityManager getEntityManager();
}
[1] Whiteboard Pattern - with self setting service
I would create a new service interface:
interface IDatabaseServiceConsumer {
setDatabaseService(IDatabaseService service);
}
and create a declarative IDatabaseService component with a bindConsumer method like this
protected void bindConsumer(IDatabaseServiceConsumer consumer) {
consumer.setDatabaseService(this);
}
protected void unbindConsumer(IDatabaseServiceConsumer consumer) {
consumer.setDatabaseService(null);
}
This approach assumes that there's only one IDatabaseService.
[Update] Usage would look like this:
class MyUIClass ... {
private IDatabaseService dbService;
Consumer c = new IDatabaseServiceConsumer() {
setDatabaseService(IDatabaseService service) {
dbService = service;
}
}
Activator.registerService(IDatabaseServiceConsumer.class,c,null);
...
}
[2] Make my class a service
Image a class like
public class DatabaseEntryViewer extends TableViewer
Now, I just add bind/unbind methods for my IDatabaseService and add a component.xml and add my DatabaseEntryViewer. This approach assumes, that there is a non-argument constructor and I create the UI components via a OSGi-Service-Factory.
[3] Classic way: ServiceTracker
The classic way to register a static ServiceTracker in my Activator and access it. The class which uses the tracker must handle the dynamic.
Currently I'm favoring the first one, as this approach doesn't complicated object creation and saves the Activator from endless, static ServiceTrackers.
I have to agree with #Neil Bartlett, your option 1 is backward. You are in effect using an Observer/Observable pattern.
Number 2 is not going to work, since the way UI objects lifecycles are managed in RCP won't allow you to do what you want. The widget will have to be created as part of the initialization of some sort of view container (ViewPart, Dialog, ...). This view part is typically configured and managed via the Workbench/plugin mechanism. You should work with this, not against it.
Number 3 would be a simple option, not necessarily the best, but simple.
If you use Spring DM, then you can easily accomplish number 2. It provides a means to inject your service beans into your UI Views, Pages, etc. You use a spring factory to create your views (as defined in your plugin.xml), which is configured via a Spring configuration, which is capable of injecting your services into the bean.
You may also be able to combine the technique used by the SpringExtensionFactory class along with DI to accomplish the same thing, without introducing another piece of technology. I haven't tried it myself so I cannot comment on the difficulty, although it is what I would try to do to bridge the gap between RCP and OSGi if I wasn't already using Spring DM.