Is it possible to split a web service in to multiple classes and still provide a single path to the web service?
I know this isn't possible because of the duplicate url-pattern values. It sort of illustrates where we're wanting to go :)
<endpoint name="OneBigService"
implementation="SmallImpl1"
url-pattern="/OneBigService"/>
<endpoint name="OneBigService"
implementation="SmallImpl2"
url-pattern="/OneBigService"/>
Basically, how do avoid having one monolithic #WebService class?
Thanks!
Rob
Is it possible to split a web service in to multiple classes and still provide a single path to the web service?
No. A URI is a connection point to one web service (defined by the Port/Endpoint).
Basically, how do avoid having one monolithic #WebService class?
Well, in my opinion the real question is more when should I use several Port/Endpoint? And I would be tempted to answer: regroup/split things logically.
For example, while it make sense for a Calculator service to expose add, subtract, multiply and divide operations, I would use another service to expose a getQuote operation.
Now, you can always split the logic into several classes and delegate to them from your #WebService.
You could delegate functionality to a composed class from your web service class:
#WebService
public class OneBigService {
ISmall delegate = new SmallImpl1(); // or new SmallImpl2();
#WebMethod
public Result webMethodStuff() {
// do something with delegate
}
}
Related
I'm implementing a series of REST micro services in Java - let's call them "adapters".
Every service reads the data from a particular source type, and provides result in the same way. The main idea is to have the same interface (service contract) for all of them, to get interchangeability. I would like to avoid code duplication and reuse the service contract for the services.
And it seems that I'm reinventing the wheel. Is there a standard approach for this?
I tried to extract the service contract in form of Java interface for Spring MVC Controller class and accompanying DAO class CustomObject:
public interface AdapterController {
#RequestMapping(method = RequestMethod.GET, value = "/objects/{name}")
CustomObject getObject(#PathVariable final String name);
}
Then put them into separate Maven project, set it as a dependency in the original project, and rewrote REST controller class as following:
#RestController
public class DdAdapterController implements AdapterController {
#Override
public CustomObject getObject(String name) {
return model.getByName(name);
}
I can reuse DAO object in a client code as well, but the interface class is useless at client side.
1) Summarizing: is it OK to reuse/share service contract between different service implementations? What's the cost of this? Is there the best practice how to share service contract?
2) The next question is about service contract and consuming client. Is it OK to share the contract between service and client? Is there some tools in Java / approach for this?
This goes against the microservice mentality and in the long run is a bad idea to share code.
If you start sharing code you will slowly just build a distributed monolith, where multiple services are dependent on each other.
Many have talked about this earlier:
microservices-dont-create-shared-libraries
The evils of too much coupling between services are far worse than the problems caused by code duplication
Micro services: shared library vs code duplication
The key to build microservices is:
One service should be very good at one thing
Keep them small
Have an extremely well documented api
When you need to delete a microservice this should be done with as few needs to update other services
Avoid code sharing, and treat all libraries like 3rd party libraries even your own
Microservises should by loosely coupled = minimum dependencies.
Microservices is an
architectural style that structures an application as a collection of
services that are
Highly maintainable and testable
Loosely coupled
Independently deployable
Organized around business capabilities.
https://microservices.io/
Contract can be defined with WADL
Using contract between client and server means less bugs, less missunderstandings when implementing client. That is what the contract good for.
Service1 injects Repository1. Service2 injects Repository2.
Suppose two different scenarios:
1)
Some method of Service2 needs to retrieve data from Repository1.
Should Service2 inject Service1 or Repository1 when both of them provide respective get() method?
2) Some method of Service1 at it's end should call another method from Service2. Is it a bad practice to inject Service2 to Service1 for such needs? Is it a good practice to use event listen techniques like AOP for such needs?
There are many factors to consider here when we talked about best practices.
As a good start, try to understand the concept of SOLID principles.
Generally, it is good to have multiple classes with very focused roles that calls the other rather than combining all functionalities in one class. High reusability and least code duplication which in turn gives maintainability.
For scenario 1.)
It is perfectly fine to have a service calling another service if that business code defined in the method is the same business functionality needed by the other service. This follows the DRY principle, no redundant codes.
But it is also perfectly fine to just directly call the Dao from a service instead of calling a different service to do that for you if it is just a simple call with no further business logic. Especially if the two services are in the same module anyway, there is no strong reason to make another service a bridge class for an obvious simple single line of code unless you want to abstract it, but in your case, its just a simple get call.
For scenario 2.)
But another thing to consider is modularity and direction of dependency. If each service calls each other, there could be problem in your design, as much as possible avoid circular dependency on different modules because this could lead to spaghetti code, better to extract same code to a different class declared on common module that can be shared by many modules.
Final note, as what Robert Martin says, you won't be able to code at once the cleanest code in one round. Best codes are forged by continuous refactoring and code cleanup. To quote Robert Martin,
The Boy Scouts have a rule: "Always leave the campground cleaner than you found it."
I am not greatly experienced with this problem, but personally I would avoid coupling controllers. My first approach would be trying to create an interface that would fit all models if possible. It would then be possible to create a model that wires multiple models together to access the data you need without adding references to the controller. For instance:
Model1 implements iModel{}
Model2 implements iModel{}
ModelWrapper implements iModel{
private iModel model1;
private iModel model2;
public ModelWrapper(iModel model1, iModel model2)
{
this.model1 = model1;
this.model2 = model2;
}
public SomeDataType getSomeValue(){
SomeObject.param1 = model1.method();
SomeObject.param2 = model2.method();
return SomeObject;
}
}
I am sure there is a better way to approach the number of models passed into the constructor and also a way to search each model for the data you are looking for. If the data is not found a null reference or better a custom error could be thrown. If the implementation is consistent perhaps the wrapper could combine all models and allow access to many custom combinations. At least this way, when requirements change you can simply add an additional wrapper to get what you need without changing the current implementation.
Perhaps a more experienced developer will build on my response to provide you a better implementation, but I hope this helps.
I have the following situation:
Three concrete service classes implement a service interface: one is for persistence, the other deals with notifications, the third deals with adding points to specific actions (gamification). The interface has roughly the following structure:
public interface IPhotoService {
void upload();
Photo get(Long id);
void like(Long id);
//etc...
}
I did not want to mix the three types of logic into one service (or even worse, in the controller class) because I want to be able to change them (or shut them) without any problems. The problem comes when I have to inject a concrete service into the controller to use. Usually, I create a fourth class, named roughly ApplicationNamePhotoService, which implements the same interface, and works as a wrapper (mediator) between the other three services, which gets input from the controller, and calls each service correspondingly. It is a working approach, though one, which creates a lot of boilerplate code.
Is this the right approach? Currently, I am not aware of a better one, although I will highly appreciate to know if it is possible to declare the execution sequence declaratively (in the context) and to inject the controller with and on-the fly generated wrapper instance.
Also, it would be nice to cache some stuff between the three services. For example, all are using DAOs, i.e. making sometimes the same calls to the DB over and over again. If all the logic were into one place that could have been avoided, but now... I know that it is possible to enable some request or session based caching. Can you suggest me some example code? BTW, I am using Hibernate for the persistence part. Is there already some caching provided (probably, if they reside in the same transaction or something - with that one I am totally lost)
The service layer should consist of classes with methods that are units of work with actions that belong in the same transaction. It sounds like you are mixing service classes when they could be in the same class and method. You can inject service classes into one another when required too, rather than create another "mediator".
It is perfectly acceptable to "mix the three types of logic", in fact it is preferable if they form an expected use case/unit of work
Cache-ing I would look to use eh cache which is, I believe, well integrated with hibernate.
In another question, someone told me to implement the following in my java program. But, I am very new to Java and I do not know how to start to convert my simple program into this structure:
Data Access Layer (read/write data)
Service Layer (isolated business logic)
Controller (Link between view and model)
Presentation (UI)
dependency injection.
program to the interface:
Does that come inside some framework? Should I start learning Spring and this structure will evolve naturally? Or, can I implement above technologies one by one without using a framework?
You can implement them without a framework if you wish, but you give up whatever benefits the framework offers you.
The layering you cite is correct and independent of any framework; it's just programming to interfaces and separation of concerns. You're free to do it without Spring if you wish to minimize the number of new technologies you want to learn right now.
If you don't know what persistence is, then you shouldn't jump into Spring. Persistence means storing data in relational databases using SQL to most people. If you don't know that, I'd recommend starting there.
All the patterns books in the world won't help you if you've never used the underlying technologies.
If you've never done any of this, I'd recommend sticking to straight JDBC, servlets, and JSPs using only JSTL (no scriptlets). Anything beyond that will just be confusing.
If you had a Foo model object, with persistence, service, and view tiers, the interfaces might look like this:
package model;
/**
* A model object that's interesting from your problem's point of view
*/
public class Foo
{
}
package persistence;
/**
* CRUD operations for a Foo
*/
public interface FooDao
{
Foo find(Long id);
List<Foo> find();
void saveOrUpdate(Foo foo);
void delete(Foo foo);
}
package service;
/**
* Just a data service that wraps FooDao for now, but other use cases would
* mean other methods. The service would also own the data connection and manage
* transactions.
*/
public interface FooService
{
Foo find(Long id);
List<Foo> find();
void saveOrUpdate(Foo foo);
void delete(Foo foo);
}
package view;
/**
* A class that owns services, validates and binds input from UI, and handles routing
* to the next view once service is complete.
*/
public interface FooController
{
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response);
}
These are just interfaces, of course. You'll need to provide implementations.
You might want to check out Domain Driven Design. The Code samples are in Java. The things you listed are design related more than any specific technology.
In short:
Data Access Layer is a module of your application that provides interface to your data. Data may be in SQL database, XML, file wherever. You write interfaces and classes that provide interface to access data usually as VO or DTO via DAOs
Service Layer contains most of the use-case logic. Service layer interacts with Data Access Layer to perform tasks in given use case. I did not find a good article on introductory service layer. You may see here and there
Controller is the one that interacts with Service Layer and/or Data Access Layer and/or other controllers in order to perform a specified client's tasks. For example, a sign-off button controller will request a sign-off action/service to invalidate user's sessions on all services that user is logged on to, then it will choose an appropriate view or log-off web-page to forward user to.
Presentation is your user interface. It can be a web-page made of HTML or Java Swing window or anything that user interacts with. GUI commonly known term for it. This is what your users will be interacting with using mouse clicks, scrolls, swipes, drag-and-drop. These actions are mapped with controller which performs action based on what user performed on UI.
Dependency Injection is a way to wire various components. There are a lot of resources on web. You can look in Martin Fowler's this article. It's basically a mechanism that allows components to behave much like plug-and-play devices, if you know what plug goes where.Spring is a good implementation of dependency injection. You may not want to write your own framework, and at this stage, you should rather not. There is a Spring MVC framework that can do things for you.
But I suggest you start from very basic. Instead of jumping on jargon, read from basic. Start with a good book on application development using Java. You can also look into
Design Patterns - Gang of Four
Core J2EE Patterns
Developing a Spring Framework MVC application step-by-step
dependency Injection with the Spring Framework
You can implement all of this is you want -- it's been done many times before, but nothing prevents you from doing it again.
What would be a better use of your time is to make sure you understand the separation of concerns you listed above (which are generally right) and identify the most efficient integration of existing frameworks to leverage (e.g., Hiberante, Spring, Guice, etc). There are multiple answers for that one (and no shortage of opinions!), but all things being equal, the less frameworks you have to integrate, the easier and better fitting it's likely to be.
Spring has a very well known framework which covers many of these things, so it would be wise to start there. It also allows you to work with other frameworks (i.e., you can use selective parts of Spring). For example, you can use Spring for dependency injection and use a different MVC framework.
It is very hard to answer this question. First of all, I don't know what your program looks like. Second, I don't think 'converting' it is something that can be done, or should be done for that matter. What you're talking about are architectural concepts that the developers usually have in mind while designign the application.
If these concepts interest you, I suggest reading a bit about Model-View-Controller pattern (MVC) and service-oriented Architecture (SOA).
These are general concepts that do not apply specifically to Java. However, they are widely used in Java enterprise development. Various frameworks allow you to create applications utilizing these concepts. For example, Spring Web MVC, as others have pointed out, is part of the Spring Framework that lets you create web applications that adhere to the MVC pattern.
If your program is really simple this separation might be done by using one calss for each
category.
Data Access Layer (read/write data) -> one class for presisting laoding
Service Layer (isolated business logic) -> one calss with bussiness logic
Controller (Link between view and model) -> in simple swing app this merges with UI
Presentation (UI) -> one class for one widnow
dependency injection -> not used in small apps
program to the interface -> Your service class should use interface tah is used by other class instead of directly your serivce implementation:
if it's not as simple program you might want to have package for each category.
BUT - don't overdesign! These concepts are ment to help you manage large scale applications, not to ruin you in your programming begginigs!
My friend build a web service in java
I build one in .net
I want them to implement the same interface
then in my program change the web.config to point to one or the other.
In my mind this would be done by implementing the same interface. Not sure how it would actually be done...
Perhaps the safest way would be to generate the interface from WSDL. Describe your service(s) in a WSDL document then use 'wsimport -d src WSDL_file' (in Java).
The subtle differences between ASP.NET and Java web services will make this a hard task.
An alternative might be to create an adapter service in front of them, which exposes the same semantic interface, and has service references to both.
This adapter service can be configured to pass on commands to either the Java one or the .NET one based on the same approach of modifying the web.config. IE:
[WebMethod]
public int AddTwoNumbers(int numberA, int numberB)
{
if(useJavaService)
return javaService.AddTwoNumbers(numberA, numberB);
else
return dotnetService.AddTwoNumbers(numberA, numberB);
}
Your application can target this wrapper service, so from your application's perspective you would simply call:
int result = theService.AddTwoNumbers(5, 10);
and your application won't know if its going to hit the Java one or the .NET one.