How to create an interface for any service in Spring Boot - java

I want all the Service classes in my backend to have CRUD methods.
For that purpose, I thought of creating an interface:
public interface ServiceCRUD {
public Object save(Object object);
...
}
And then on my service, implement it:
#Service
public class SampleService implements ServiceCRUD {
#Autowired
private SampleRepository repository;
#Override
public Sample save(Sample sample) {
return repository.save(sample);
}
...
}
I haven't touched Java in a while, but if I recall correctly, every object extend Object, so why is it that I can't use Object to have the service accept all the entities I might have?
Best regards

You can achieve such scenario using Generics
interface ServiceCRUD {
public < E > void save(E object);
}
class Sample {
private String name = "Joe";
#Override
public String toString() {
return "hello"+name;
}
}
class SampleService implements ServiceCRUD {
#Override
public < Sample > void save(Sample sample) {
System.out.print(sample.toString());
}
}
public class Main {
public static void main(String[] args) {
new SampleService().save(new Sample());
}
}
This is just an example ,you can extend it as per your use case.
See working here

Your interface declares that one is possible to save Object, i. e. any object. But your implementation declares that it cat get only Sample, that's why you get compilation error.
You should go with genetic and let each implementation to declare what kind of object it can deal with. I strongly suggest to have a look at spring data project. It will save you a lot if time

Related

Strategy Pattern two usages of #Service duplicate component name

Implemented a strategy pattern very simple with the help of Spring Boot:
I have an interface:
public interface IOneStrategy {
void executeTheThing();
}
I have an implementation of the strategy One like this:
#Service("FIRST")
public class OneStrategyFirst implements IOneStrategy {
#Override
public void executeTheThing() {
System.out.println("OneStrategyFirst.executeTheThing");
}
}
I have a class which consumes the injected implementations:
#Service
public class ExecuteStrategyOne {
private Map<String, IOneStrategy> strategies;
public void executeStrategyOne(String name) {
if (!strategies.containsKey(name)) {
throw new IllegalArgumentException("The key " + name + " does not exist.");
}
strategies.get(name).executeTheThing();
}
}
and those implementations will be injected by Spring boot automatically by using the name FIRST, 'SECOND' etc. (assuming that this is simply a String etc. works very well.).
But now I want to implement another strategy via second interface:
public interface ITwoStrategy {
void executeTheThing();
}
and the executing service for the strategy:
#Service
public class ExecuteStrategyTwo {
private Map<String, ITwoStrategy> strategies;
...
}
and now the problematic part, because my application uses the same name which should be made part of the key of the above map I want to use the following:
#Service("FIRST")
public class TwoStrategyFirst implements ITwoStrategy {
#Override
public void executeTheThing() {
System.out.println("TwoStrategyFirst.executeTheThing");
}
}
This will of course result into an exception based on the duplicate bean name. The name FIRST is really needed to make the difference between the implementation.
I already found things about #Qualifier which I could use instead of #Service(FIRST)
#Service
#Qualifier(FIRST)
public class TwoStrategyFirst implements ITwoStrategy {
#Override
public void executeTheThing() {
System.out.println("TwoStrategyFirst.executeTheThing");
}
}
which unfortunately does not inject the classes into the map by using the name of the qualifier just by the name of the class which is not what I intended to do.
Does exist a solution to get the key of the map in the strategy execution the same as with the #Service("FIRST")?
I could use a solution via using the Qualifier annotation like this:
#Service
#Qualifier(FIRST)
public class TwoStrategyFirst implements ITwoStrategy {
...
}
And based on that there is a more or less easy solution via a bit of code:
#Service
public class ExecuteStrategyTwo {
private Map<String, ITwoStrategy> strategies;
public ExecuteStrategyOne(List<ITwoStrategy> strategies) {
this.strategies = strategies.stream()
.collect(
Collectors.toMap(k -> k.getClass().getDeclaredAnnotation(Qualifier.class).value(), Function.identity()));
}
This will inject all implementation into the list of the constructor and will be translated into the map by using the qualifier annotation.

Constructor DTO container pattern

Has anyone seen a pattern whereby Java constructor parameters are created using a DTO object and then injected into the class using Spring? I believe it is an anti-pattern but am curious if there is a reasonable case where it could be used.
In my mind the ideal thing to do is refactor the code so the need for the single constructor object is redundant.
What's everyones thoughts?
My particular example is of the form:
#Service
public class MyClass {
private MyClassConstructorDto constructorDependencyContainer;
#Autowired
public MyClass(MyClassConstructorDto constructorDependencyContainer) {
this.constructorDependencyContainer = constructorDependencyContainer;
}
public void doSomething() {
constructorDependencyContainer.getCoolDependency().performThing();
}
}
with supporting class
#Component
public class MyClassConstructorDto {
private CoolDependency coolDependency;
public MyClassConstructorDto(CoolDependency coolDependency) {
this.coolDependency = coolDependency;
}
public CoolDependency getCoolDependency() {
return coolDependency;
}
}

Spring & Java Generics - Getting instance of one service in abstract controller

I have a typed service interface:
public interface BaseArticleService<T extends BaseArticle> {
T getById(Long id);
}
And have two interfaces which extends it:
public interface AccArticleService extends BaseArticleService<AccArticle> {
}
public interface ExpArticleService extends BaseArticleService<ExpArticle> {
Long getCount();
}
Then I have a similar architecture for controllers:
public abstract class BaseArticleController<T extends BaseArticle> {
#Autowired
BaseArticleService<T> baseArticleService;
}
And:
#Controller
#RequestMapping(value = "/exp/articles")
public class ExpArticleController extends BaseArticleController<ExpArticle> {
}
#Controller
#RequestMapping(value = "/acc/articles")
public class AccArticleController extends BaseArticleController<AccArticle> {
}
Now if I want to get my ExpArticleService instance of the BaseArticleService that is injected in my BaseController, how can I achieve this?
If I do this:
public BaseArticleService<ExpArticle> getExpArticleService() {
return super.baseArticleService;
}
then I cannot call my getCount() method like getExpArticleService().getCount()
And cannot do this neither:
public ExpArticleService getExpArticleService() {
return super.baseArticuloService;
}
So what's the solution? Maybe inject another ExpArticleService in my ExpArticleController?
When using DI you are by definition relying on the interface. If you inject BaseArticleService then the only method available to you are the methods defined in this interface. In your case T getById(Long id);
Your way is not a bad way, you have a generic super class which allow you to initialise the interface with different parameters very easily, but you shouldn't expect to explicitely get any of the specific implementation. (maybe you could check and cast but it is not clean there).
As already stated you should extract the specific implementation in another class and directly inject this one in the controller requiring it. Keep your generic though, it is a nice way to to handle all the parametrized methods that will be shared between your controllers

Changing Guice bindings at runtime

I would like to be able to change the Guice injections at runtime to support multiple injections based on user input. This is what I would like to achieve:
public interface IDao {
public int someMethod();
}
public class DaoEarth implements IDao {
#Override
public int someMethod(){ ... }
}
public class DaoMars implements IDao {
#Override
public int someMethod(){ ... }
}
public class MyClass {
#Inject
private IDao myDao;
public int myMethod(String domain) {
//If Domain == Earth, myDao should be of the type DaoEarth
//If Domain == DaoMars, myDao should be of the type DaoMars
}
}
I was thinking of writing my own Provider, but I don't know how to use that provider to change my bindings at runtime. Any input is welcome and appreciated :)!
Update
Here's what I currently came up with, it's not as pretty as I'd like, so I'm still looking for feedback
public class DomainProvider {
#Inject #Earth
private IDaoProvider earthDaoProvider;
#Inject #Mars
private IDaoProvider marsDaoProvider;
public IDaoProvider get(Domain domain){
switch (domain){
case EARTH:
return earthDaoProvider;
case MARS:
return marsDaoProvider;
}
}
public IDaoProvider get(String domain){
Domain parsedDomain = Domain.valueOf(domain.toUpperCase());
return get(parsedDomain);
}
}
//MarsDaoProvider would be equivalent
public class EarthDaoProvider implements IDaoProvider {
#Inject #Earth
private IDao earthDao;
public IDao getDao() {
return earthDao;
}
}
// This means that in "MyClass", I can do:
public class MyClass {
#Inject
private DomainProvider domainProvider;
public int myMethod(String domain) {
IDaoProvider daoProvider = domainProvider.get(domain);
IDao dao = daoProvider.getDao();
//Now "dao" will be of the correct type based on the domain
}
}
//Of course elsewhere I have the bindings set like
bind(IDao.class).annotatedWith(Earth.class).to(EarthDao.class);
Your version is almost perfect as it is: You're going to need to inject some kind of object that returns one or the other based on code you write, and don't need assisted injection or anything like that. That said, you can skip some of the boilerplate:
public class DomainProvider {
// Just inject Providers directly without binding them explicitly.
#Inject #Earth Provider<IDao> earthDaoProvider;
#Inject #Mars Provider<IDao> marsDaoProvider;
public Provider<IDao> get(Domain domain){
switch (domain){
case EARTH:
return earthDaoProvider;
case MARS:
return marsDaoProvider;
}
}
public Provider<IDao> get(String domain){
Domain parsedDomain = Domain.valueOf(domain.toUpperCase());
return get(parsedDomain);
}
}
Your MyClass in that case would be exactly identical. Here, Provider is either the one-method generic interface com.google.inject.Provider, or the equivalent builtin javax.inject.Provider that it extends. Read more about Guice Providers on the relevant Guice wiki topic.
bind(IDao.class).annotatedWith(Earth.class).to(EarthDao.class);
// You can now inject "#Earth IDao" and also "#Earth Provider<IDao>".
Basically, if you bind a key Foo (to a class, provider, #Provides method, or instance), you automatically get to inject either a Foo or Provider<Foo> with no additional work. Providers are also a great way to ensure that you get a new instance with every call to get, if that's what you want; with your original, you'll always get the same instance of EarthDao or MarsDao for any given DomainProvider you inject. (If you have a scoped binding like #Singleton, Guice will respect that too; Provider just lets Guice get involved, rather than reusing a plain old Java reference.)
This means you can skip your custom EarthDaoProvider and MarsDaoProvider, unless you really need to perform any external initialization on them—at which point you'd probably be better off calling bind(EarthDao.class).toProvider(EarthDaoProvider.class) so the preparation also happens when injecting EarthDao directly. You could also just have DomainProvider return an IDao instance directly by calling get on the appropriate Provider, and be assured that it'll be a new instance every time.

Accessing external source from DAO implementation

Consider following simple DAO example:
public abstract class DAOFactory
{
public abstract AccountDAO getAccountDAO();
public abstract MessageDAO getMessageDAO();
public static DAOFactory getDAOFactory(int whichFactory)
{
// depending on whichFactory
return new SpecificDAOFactory();
}
}
public interface AccountDAO
{
public void add(Account account);
public void delete(Account account);
public int authenticate(Account account); // another source!
}
public interface MessageDAO
{
//other methods
}
All above mentioned methods have to be implemented using the same data source, except AccountDAO.authenticate().
Authentication information available at the other data source and should be pluggable in turn (e.g. could be SQL, LDAP, etc.). At the same time, authentication data source is independent from the DAO data source, i.e. whichFactory could be A, B or C while authentication source X or Y.
From interface design point of view, authenticate fits nicely into AccountDAO. But from implementation point of view I feel uncomfortable.
What would be better design which will provide clear data access layer interface and implementation?
Data access objects tend to follow the same structure and pattern, so you might want to consider creating a higher level class encapsulating this shared logic. I will highlight with an example, please note that I am omitting interfaces because I rarely find them useful at the DAO level.
Base DAO class:
public class BaseDAO<T> {
private Class<T> clazz;
public BaseDAO(Class<T> clazz) {
super();
this.clazz = clazz;
}
public T find(Long id) { ... }
public List<T> findAll() { ... }
public T create(T entity) { ... }
public T update(T entity) { ... }
public void delete(T entity) { ... }
}
A derived DAO for a hypothetical Account object
public class AccountDAO extends BaseDAO<Account> {
public AccountDAO() {
super(Account.class);
}
public List<Account> findByAccountStatus(String status) { ... }
}
As you can see, you greatly minimize the amount of code in derived DAO's. With this setup you do not need to use a factory, just initialize your DAO's directly.
As far as your second question, I would not place an authenticate method on the Account DAO. Authentication should be dealt with at a higher level of abstraction (fits very nicely in the service layer), even if it eventually retrieves some information from the data access layer.

Categories