I would like to design an interface for accessing JPA data directly from within the Spring Boot application and also over REST.
Here is the interface for REST
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(#Param("name") String name);
}
This interface works correctly for REST access from an HTTP client.
I would also like to pre-populate the database by calling repository.save() from the Application class and then use findByLastName() to retrieve the list of names.
What is the way for this?
Related
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 creating a web app using JEE7. My question is about the architecture of my application. Basically, I have several entity classes (business class) that represent what will be stored in my database. For example I've got an entity class Book and an entity class Comic.
To access the database I want to create an EJB (kindda like the DAO design pattern). And here is my problem, I couldn't find a precise answer online.
Should I create one #remote interface and one #stateless class with all the methods to add/delete/get/update for both the Book class and the comic class ?
Or should I create 2 #remote interfaces and 2 #stateless classes (2 EJB), one for each entity class ?
Because lets imagine I create a bigger web app. If I have 100 entity classes, with the first method I'll have one huge EJB but with the second I'll have 100 EJB with their interfaces. I think the second is better but I'm not sure. What do you think ?
Why not just use one stateless bean and one remote interface?
A very nice feature of remote beans is, that they can be generic, so basically at minimum you only need one interface and one remote bean at all (see SimpleEntity and its remote bean).
I use a mix of a very generic remote bean DAO to read simple entities and some specific beans for entities which need more logic on CUD operations. Following i just extracted the minimum interfaces to reproduce it.
If i create a new table and entity it can immediately be used at the remote client.
Entities
/*
* Complex entity with enhanced CRUD logic
*/
public class Foo implements Entity { }
/*
* Simple entity without complex CRUD logic
*/
public class Bar implements SimpleEntity { }
Interface
public interface Entity { }
public interface SimpleEntity extends Entity { }
/*
* Generic entity DAO interface, for remote beans and other datasources
*/
public interface IEntityDAO<T extends Entity>
{
public T get(Class<T> type, long id);
public T update(T t);
}
/*
* Generic remote bean interface for a JNDI service locator lookup
*/
public interface EntityDAOBeanRemote<T extends Entity> extends IEntityDAO<T> { }
Stateless remote Beans
/*
* 'abstract' base class for stateless DAO beans
*/
public class AEntityDAOBean<T extends Entity> implements EntityDAOBeanRemote<T>
{
public T get(Class<T> type, long id)
{
Session session = // obtain current hibernate session
return id == (T) session.createCriteria(type).add(Restrictions.idEq(id)).uniqueResult();
}
public T update(T t, long id)
{
Session session = // obtain current hibernate session
session.update(t);
return t; // return updated instance
}
}
/*
* Generic stateless remote DAO bean implementation
*/
#Stateless(mappedName = "SimpleEntityDAOBean")
#Remote(EntityDAOBeanRemote.class)
public class SimpleEntityDAOBean extends AEntityDAOBean<SimpleEntity> implements EntityDAOBeanRemote<SimpleEntity>
{
// empty since all methods are from parent class
}
/*
* Foo specific remote DAO bean
*/
#Stateless(mappedName = "FooDAOBean")
#Remote(EntityDAOBeanRemote.class)
public class FooDAOBean extends AEntityDAOBean<SimpleEntity> implements EntityDAOBeanRemote<Foo>
{
#Override
public Foo update(Foo foo)
{
// make specific foo things and update
return foo;
}
}
Client
Using JNDI at your client you can call the bean using a JNDI service locator pattern like:
EntityDAOBeanRemote<Foo> fooDAOBeanRemote = jndiServiceLocator
.getEntityDAOBeanRemote(Foo.class);
EntityDAOBeanRemote<Bar> barDAOBeanRemote = jndiServiceLocator
.getEntityDAOBeanRemote(Bar.class);
Client JSF
With generic JSF converters and a generic extension of a DAO for a GUI framework (such as PrimeFaces LazyDataModel) it saves a lot of time making new entities quickly accessible in JSF beans and editable in the GUI.
Java EE application architecture is obviously a massive topic, but a common approach would be to create a Session EJB to expose general API calls to your client and then use a coarse grain Entity EJB to handle your persistent data. These Entity EJBs can manage a number of finer grained Java objects and classes that map onto your database structure.
This might be a good place to start:
https://docs.oracle.com/cd/A87860_01/doc/java.817/a83725/entity1.htm
Building an endpoint and client with Spring MVC and Feign Client (with spring cloud). I had the thought that since both ends need to have the same annotations - and that they have to be pretty much in sync. Maybe I could define them in an interface and have the two ends implement that.
Testing it out I was somewhat surprised that it actually works for the Spring Web end.
But it I cannot find a way to do the same for a Feign client.
I basically have the interface:
#RequestMapping("/somebaseurl")
public interface ServiceInterface {
#RequestMapping(value = "/resource/{identifier}", method = RequestMethod.POST)
public SomeResource getResourceByIdentifier(String identifier);
}
And then the RestController
#RestController
public class ServiceController implements ServiceInterface {
public SomeResource getResourceByIdentifier(#PathVariable("identifier") String identifier) {
// Do some stuff that gets the resource
return new SomeResource();
}
}
And then finally the Feign Client
#FeignClient("serviceName")
public interface ServiceClient extends ServiceInterface {
}
The Feign client seems to not read the inherited annotations. So is there some other way I can accomplish the same thing? Where I can make the ServiceInterface into Feign client without annotating it directly?
This is possible as of Feign 8.6.0. From the Spring Cloud docs:
Feign Inheritance Support
Feign supports boilerplate apis via single-inheritance interfaces. This allows grouping common operations
into convenient base interfaces. Together with Spring MVC you can
share the same contract for your REST endpoint and Feign client.
UserService.java
public interface UserService {
#RequestMapping(method = RequestMethod.GET, value ="/users/{id}")
User getUser(#PathVariable("id") long id);
}
UserResource.java
#RestController
public class UserResource implements UserService {
}
UserClient.java
#FeignClient("users")
public interface UserClient extends UserService {
}
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.
Currently in my application we are using GWT RequestFactory. We have multiple EntityProxy. Couple of finder method returns List from service layer. Since we are using pagination in our application we are returning pre-configured number of EntityProxy in List. We requires total number of EntityProxy also for showing in pagination UI for which we are making separate request. We want to create some wrapper object which encapsulates List and totalRecord count in single class. So in single request we can get both List and record count. What is best to do this using requestfactory ? Note : I am beginner in GWT RequestFactory.
The answer of Umit is quite correct. I would only add a layer that abstracts the pagination handling. This comes useful when you have your BasicTables and BasicLists to address all data through the same interface PageProxy (eg. for pagination)
public interface PaginationInfo extends ValueProxy {
public int getTotalRecords();
//either have the manual page info
public int getPageNumber();
//or use the count API on GAE (returned by your db request as a web safe String)
public String getCount();
}
public interface PageProxy extends ValueProxy {
public PaginationInfo getPageInfo();
}
public interface MyEntityProxy extends EntityProxy {}
public interface MyEntityPageProxy extends PageProxy {
public List<MyEntityProxy> getEntities();
}
Well you can use something along this lines:
public interface MyEntityProxy extends EntityProxy {}
public interface MyEntityPageProxy extends ValueProxy {
public List<MyEntityProxy> getEntities();
public int getTotalRecords();
}
It would be better to use a generic PageProxy interface (i.e. MyEntityPageProxy<T extends EntityProxy>) however because of this bug it's not possible or at least only through a workaround.
So for each EntityProxy you want to have Paginationsupport you have to create a separate PageProxy interface.