I'm developing a web application using MVC architectural pattern.
Struts2 (version 2.3.24) is used for the Business Logic and Presentation Layer
Spring (version 4.1.0) is the dependency injection engine
Hibernate (version 3.6.10) is used for the Data Layer.
I have to create a PaginationFactory class that I can dynamically use for the various section of the application. I've several examples on google and StackOverflow... But mostly old stuff like this question.
Any ideas on how implement this function with using something more modern? Maybe with JQuery and Ajax as support?
I suggest for you to use Spring Data Jpa, it's already have implemented pagination.
Your repository will look like this:
public interface MedicamentRepository extends JpaRepository<Medicament, Integer> {}
You can extend, as example, PagingAndSortingRepository interface, if you don't need some of methods that JpaRepository provides.
public class SomeClass{
#Autowired
public MedicamentRepository medicamentRepo;
public void someMethod(){
//in spring data jpa, page count starts from 0;
PageRequest pageRequest = new PageRequest(pageNumber,
pageSize); //also have sorting
org.springframework.data.domain.Page<Medicament> page = medicamentRepo.findAll(pageRequest);
}
}
you can read more here
Related
With spring boot 2.6.0 (or above) is it possible to generate a rest client from a a controller interface?
Im wondering if its possible to build spring application like this following use case.
Spring application A needs to call spring application B rest interface
Spring application B is a multimodule project that produces server jar, and a api jar
Spring application A imports the B's API jar
Spring application A uses controller interface from B Api jar to make a rest client based on spring annotations.
B Api jar:
#RestsController
public interface MyApplicationAPI {
#GetMapping("/api/some-endpoint)
public SomeDto someEndpoint(SomeDTO obj);
}
B server jar:
public class BApplicationAPIImpl implements MyApplicationAPI {
public SomeDto someEndpoint(SomeDTO obj) {
return xxx;
And finally within A application:
MyApplicationAPI restClient = Some.magic(MyApplicationAPI.class, "http://bappurl.com")
SomeDto response = restClient.someEndpoint(param);
I believe that framework RestEasy supports similar approach, but you have to rely on JAXRS annotations.
Is there anything like that for spring framework? Or even better is there anything like this within spring already - i would prefer to rely on spring inhouse libraries and tools, rather than importing entire resteasy and jaxrs.
Spring Framework 6 (and Spring Boot 3) will have declarative HTTP interfaces (see documentation). However, they won't use the same annotations as controllers, but separate ones. So your example where you use the same interface for both controller and client won't be possible.
Code snippet from the documentation:
interface RepositoryService {
#GetExchange("/repos/{owner}/{repo}")
Repository getRepository(#PathVariable String owner, #PathVariable String repo);
// more HTTP exchange methods...
}
Initialization (the Some.magic() part in your question) can be done with WebClient. As can be seen in the same documentation:
WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
HttpServiceProxyFactory factory = WebClientAdapter.createHttpServiceProxyFactory(client);
factory.afterPropertiesSet();
RepositoryService service = factory.createClient(RepositoryService.class);
I'm new to Spring WebFlux reactive. I use R2DBC postgresql. I have a repository like that:
public interface BookRepository extends ReactiveCrudRepository<Book, Long> {
}
Now I want to add custom method to query by many complicated conditions:
public interface CustomBookRepository extends BookRepository {
Flux<Book> findByVeryComplicatedCondition(MyCriteriaDto criteria);
}
My implementation:
public class CustomBookRepositoryImpl extends CustomBookRepository {
//How to get it?
EntityManager em;
#Override
public Flux<Book> findByVeryComplicatedCondition(MyCriteriaDto criteria) {
Query query = em.createQuery("SELECT b from Book b WHERE (VERY COMPLICATED CONDITIONS)");
//What next?
}
}
My questions are in the code above:
How to obtain an EntityManager?
How to get Flux from HQL query I built?
When I ask these questions, I mean "How to do this with Spring reactive/r2dbc way", not "How to do this normal way with JDBC"
Spring Data R2DBC is not backed by a fully-fledged ORM framework like Hibernate. Therefore there are no such things as EntityManager and no possibility to write JQL/HQL queries.
However, one can still use native queries to define more complex methods, e.g.
interface MyRepository extends ReactiveCrudRepository<...> {
#Query("SELECT b from Book b WHERE (VERY COMPLICATED CONDITIONS)")
Flux<...> find(...);
}
If you want to use Hibernate/JPA JPQL like query in your project, consider Hibernate Reactive.
I have written an article to describe how to use Hibernate Reactive with Spring (BTW, I have contributed a patch to register SmallRye in Spring framework, so at the end of this article, you can skip to register MutinyAdapter in ReactiveAdapterRegistry ).
Spring Data has no plan to integrate Hibernate Reactive, so there is no Repository support.
Hibernate Reactive depends on Vertx reactive drivers, it does not support R2dbc.
HibernateReactive supports another ReactiveStreams implemetnation from Redhat - Smallrye Munity.
In a post last august sbzoom proposed a solution to make spring-data-mongoDB multi-tenant:
"You have to make your own RepositoryFactoryBean. Here is the example from the Spring Data MongoDB Reference Docs. You would still have to implement your own MongoTemplate and delay or remove the ensureIndexes() call. But you would have to rewrite a few classes to make sure your MongoTemplate is called instead of Spring's."
Did anybody implement this or something equivalent?
There's quite a few ways to skin the cat here. It essentially all boils down to on which level you'd like to apply the tenancy.
Basics
The basic approach is to bind some kind of key identifying the customer on a per-thread basis, so that you can find out about the customer the current thread of execution deals with. This is usually achieved by populating a ThreadLocal with some authentication related information as you can usually derive the tenant from the logged in user.
Now if that's in place there's a few options of where to apply the tenant knowledge. Let me briefly outline the most common ones:
Multi-tenancy on the database level
One way to separate data for multiple clients is to have individual databases per tenant. Spring Data MongoDB's core abstraction for this is the MongoDBFactory interface. The easiest way here is to override SimpleMongoDbFactory.getDb(String name) and call the parent method with the database name e.g. enriched by the tenant prefix or the like.
Multi-tenancy on the collection level
Another option is to have tenant specific collections, e.g. through tenant pre- or postfixes. This mechanism can actually be leveraged by using the Spring Expression language (SpEl) in the #Document annotation's collectionName attribute. First, expose the tenant prefix through a Spring bean:
#Component("tenantProvider")
public class TenantProvider {
public String getTenantId() {
// … implement ThreadLocal lookup here
}
}
Then use SpEL in your domain types #Document mapping:
#Document(collectionName = "#{tenantProvider.getTenantId()}_accounts"
public class Account { … }
SpEl allows you to refer to Spring beans by name and execute methods on them. MongoTemplate (and thus the repository abstraction transitively) will use the mapping metadata of the document class and the mapping subsystem will evaluate the collectionName attribute to find out about the collection to interact with.
I had a similar approach to Oliver Gierke.
At least on database-level. https://github.com/Loki-Afro/multi-tenant-spring-mongodb
You should be able to do things like this:
MultiTenantMongoDbFactory.setDatabaseNameForCurrentThread("test");
this.personRepository.save(createPerson("Phillip", "Wirth", ChronoUnit.YEARS.between(
LocalDate.of(1992, Month.FEBRUARY, 3),
LocalDate.now())));
System.out.println("data from test: " + this.personRepository.findAll());
// okay? fine. - lets switch the database
MultiTenantMongoDbFactory.setDatabaseNameForCurrentThread("test666");
// should be empty
System.out.println("data from test666: " + this.personRepository.findAll());
for springboot 2.3.3
overriding doGetMongoDatabase helped to achieve multi tenancy
protected MongoDatabase doGetMongoDatabase(String dbName) {
}
https://github.com/jose-m-thomas/mongo_multi_tenancy_spring_boot_2_3_3
Full featured multi-tenant/tenancy with Spring Boot + MongoDB + Spring MVC with shared/global database configuration.
https://github.com/arun2pratap/multitenant-spring-mongodb
I'm trying to get used to how JSF works with regards to accessing data (coming from a spring background)
I'm creating a simple example that maintains a list of users, I have something like
<h:dataTable value="#{userListController.userList}" var="u">
<h:column>#{u.userId}</h:column>
<h:column>#{u.userName}</h:column>
</h:dataTable>
Then the "controller" has something like
#Named(value = "userListController")
#SessionScoped
public class UserListController {
#EJB
private UserListService userListService;
private List<User> userList;
public List<User> getUserList() {
userList = userListService.getUsers();
return userList;
}
}
And the "service" (although it seems more like a DAO) has
public class UserListService {
#PersistenceContext
private EntityManager em;
public List<User> getUsers() {
Query query = em.createQuery("SELECT u from User as u");
return query.getResultList();
}
}
Is this the correct way of doing things? Is my terminology right? The "service" feels more like a DAO? And the controller feels like it's doing some of the job of the service.
Is this the correct way of doing things?
Apart from performing business logic the inefficient way in a managed bean getter method, and using a too broad managed bean scope, it looks okay. If you move the service call from the getter method to a #PostConstruct method and use either #RequestScoped or #ViewScoped instead of #SessionScoped, it will look better.
See also:
Why JSF calls getters multiple times
How to choose the right bean scope?
Is my terminology right?
It's okay. As long as you're consistent with it and the code is readable in a sensible way. Only your way of naming classes and variables is somewhat awkward (illogical and/or duplication). For instance, I personally would use users instead of userList, and use var="user" instead of var="u", and use id and name instead of userId and userName. Also, a "UserListService" sounds like it can only deal with lists of users instead of users in general. I'd rather use "UserService" so you can also use it for creating, updating and deleting users.
See also:
JSF managed bean naming conventions
The "service" feels more like a DAO?
It isn't exactly a DAO. Basically, JPA is the real DAO here. Previously, when JPA didn't exist, everyone homegrew DAO interfaces so that the service methods can keep using them even when the underlying implementation ("plain old" JDBC, or "good old" Hibernate, etc) changes. The real task of a service method is transparently managing transactions. This isn't the responsibility of the DAO.
See also:
I found JPA, or alike, don't encourage DAO pattern
DAO and JDBC relation?
When is it necessary or convenient to use Spring or EJB3 or all of them together?
And the controller feels like it's doing some of the job of the service.
I can imagine that it does that in this relatively simple setup. However, the controller is in fact part of the frontend not the backend. The service is part of the backend which should be designed in such way that it's reusable across all different frontends, such as JSF, JAX-RS, "plain" JSP+Servlet, even Swing, etc. Moreover, the frontend-specific controller (also called "backing bean" or "presenter") allows you to deal in a frontend-specific way with success and/or exceptional outcomes, such as in JSF's case displaying a faces message in case of an exception thrown from a service.
See also:
JSF Service Layer
What components are MVC in JSF MVC framework?
All in all, the correct approach would be like below:
<h:dataTable value="#{userBacking.users}" var="user">
<h:column>#{user.id}</h:column>
<h:column>#{user.name}</h:column>
</h:dataTable>
#Named
#RequestScoped // Use #ViewScoped once you bring in ajax (e.g. CRUD)
public class UserBacking {
private List<User> users;
#EJB
private UserService userService;
#PostConstruct
public void init() {
users = userService.listAll();
}
public List<User> getUsers() {
return users;
}
}
#Stateless
public class UserService {
#PersistenceContext
private EntityManager em;
public List<User> listAll() {
return em.createQuery("SELECT u FROM User u", User.class).getResultList();
}
}
You can find here a real world kickoff project here utilizing the canonical Java EE / JSF / CDI / EJB / JPA practices: Java EE kickoff app.
See also:
Creating master-detail pages for entities, how to link them and which bean scope to choose
Passing a JSF2 managed pojo bean into EJB or putting what is required into a transfer object
Filter do not initialize EntityManager
javax.persistence.TransactionRequiredException in small facelet application
It is a DAO, well actually a repository but don't worry about that difference too much, as it is accessing the database using the persistence context.
You should create a Service class, that wraps that method and is where the transactions are invoked.
Sometimes the service classes feel unnecessary, but when you have a service method that calls many DAO methods, their use is more warranted.
I normally end up just creating the service, even if it does feel unnecessary, to ensure the patterns stay the same and the DAO is never injected directly.
This adds an extra layer of abstraction making future refactoring more flexible.
I'm about to create a stock-standard rest CRUD api and have taken note of the handy CrudRepository class given in the spring-data framework. I'm planning on also using spring to declare #RequestMappings to hook up the default crud operations to their URL counterparts (e.g. /customer/{id} --> CrudRepository.findOne({id}), etc).
Is there a spring utility class to acheive this or will i need to roll my own?
Ah ha! What I'm looking for is a org.springframework.data.rest.core.annotation.RepositoryRestResource located in the spring data rest webmvc project. maven co-ordinates: "org.springframework.data:spring-data-rest-webmvc"
an example extract from the documentation:
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(#Param("name") String name);
}
enter code here
This repository is an interface and will allow you to perform various operations involving Person objects. It gets these operations by > extending the PagingAndSortingRepositry interface defined in Spring Data Commons.
At runtime, Spring Data REST will create an implementation of this interface automatically. Then it will use the #RepositoryRestResource > annotation to direct Spring MVC to create RESTful endpoints at /people.