I've written a Jersey-client application that interacts with two web services, one that is REST, the other that is SOAP. I use the employee data supplied by the REST service to create an new User with the SOAP service.
The REST service is a JAX-RS (Jersey) application that returns an Employee entity:
#Entity
#Table(name = "EMPLOYEE_TABLE")
#XmlRootElement
public class Employee implements Serializable {
...
}
I have not explicitly created a schema definition for the entity class.
A GET request returns a representation of the Employee entity:
GET /employees/100
<Employee id='100' providerId='3345'>
<Link type="application/xml" href="/employees/100" rel="self"/>
<Name>Doe, Dr. John</Name>
<Departments>
<Department id='10'><Name>Emergency Medicine</Name></Department>
<Department id='56'><Name>Behavioral Medicine</Name></Department>
</Departments>
</Employee>
The SOAP service (BusinessObjects Enterprise web-services SDK) provides a Java client to simplify its usage.
While I could parse the XML-representation of the Employee entity and assign it to the appropriate setters of the User class, it would probably be easier to create an Employee proxy class (with the appropriate annotations) in my Jersey client application.
Questions:
Does JAX-RS (specifically Jersey, in my case) have a mechanism to expose an entity's schema definition (XSD format)? The WADL document doesn't include this type of information.
While I could manually create a POJO-class representation that mimics the Employee resource class, I should probably be using a 'tool'. What are my options for this?
As time progresses, I may need to add additional elements to the Employee entity. Does this mean that a new version of the RESTful services needs to be created?
Assuming that Jersey can be configured to automatically generate and expose a schema definition, and that changes to the Employee would then alter the schema definition, should the Employee entity implement an interface to prevent unauthorized changes?
Concerning question 1, if your XSD is deployed in your webapp you can just navigate to it in a browser. For example, in my webapp I have an /xsd folder containing my XSD. When the app is running I can point my browser to http://localhost:8080/<app_name>/xsd/<xsd_name>.xsd and see the XSD.
Related
Let's say I have a domain model with no natural id.
class Offer {
ClientId clientId;
CompanyId companyId;
OfferDetails details;
}
Offer is loaded from database by auto-generated key. Then it is modifed e.g. by calling a business method accept, reject or renegotiate. In order to persist the offer I must have this auto-generated key. How should I connect domain entity and id from db? Right now I have an OfferId class with db id and version (I use JPA to persist the aggregate). Is there any better approach?
Right now I have an OfferId class with db id and version
The version shouldn't be part of the ID. The ID needs to be immutable.
There are several strategies to deal with ID generation, but here's the common ones:
Use a GUID which relieves the need to hit a shared data store to generate the ID.
Implement a nextId(): OfferId operation on your repository (implementation could use a DB sequence, etc.):
Offer offer = new Offer(offerRepo.nextId(), ...);
Allow the Offer class to be instantiated without an ID and configure your ORM to generate one. I'm not entirely sure about the JPA spec, but it seems that in Hibernate you can combine #IdClass and #GenerateValue annotations to map a DB-generated identity to a wrapping ID class. Have a look at this test case.
Honestly I dislike delegating the identity assignation/generation to the ORM. If you want to generate the ID from the DB I would suggest the second approach I've described, with a method on the repository (or a dedicated service) that can return the next ID.
When deploying a JavaEE application as a WAR file (using the WAS Liberty Profile application server), the mappings between application roles and user groups are defined in server.xml. We have chosen to implement security by means of an EJB bean interceptor that compares the permissions stated on a method annotation with a set of permissions that are assigned to user.
This idea is based on an an original article in Java Magazine (Secure Java EE Authentication," Java Magazine, January/February 2013).
To take the idea further, we want to map the roles associated with the user to a more granular set of permissions. Unfortunately there is (currently) no way easy to obtain the list of roles associated with a user. Two suggested methods are proposed in this stack overflow article by #Josh and #Steve.
It struck me that if I can obtain the list of roles defined by the #DeclareRoles() annotation, I could use the request.isUserInRole(role) method for each of these roles without having to maintain a separate list of roles myself.
Has anyone used this method, or are there better methods to implement a finer grained security model since the article was written?
Well, you can certainly do something like:
#Stateless
#LocalBean
#DeclareRoles({ ROLE1, ROLE2, ROLE3 })
public class IsCallerInRoleDemoSessionBean {
#Resource
private SessionContext sessionContext;
#PermitAll
public Set<String> discoverRoles() {
Set<String> roleNames = new HashSet<>();
DeclareRoles declaredRoles = IsCallerInRoleDemoSessionBean.class.getAnnotation(DeclareRoles.class);
for (String roleName : declaredRoles.value())
if (sessionContext.isCallerInRole(roleName))
roleNames.add(roleName);
return roleNames;
}
}
This is from an old Arquillian Security Demo I did for someone a few years ago.
Ideally, this would also examine super-classes as well.
Using the first example in the ServiceStack Auto Query documentation in a project structured similar to the EmailContacts sample project (i.e. separate projects for the ServiceModel and ServiceInterface), how would one register the custom route "/movies" defined by the Route attribute?
[Route("/movies")]
public class FindMovies : QueryBase<Movie>
{
public string[] Ratings { get; set; }
}
Normally, custom routes such as these can be register by passing the ServiceInterface assembly when instantiating AppHostBase:
public AppHost() : base("Email Contact Services", typeof(ContactsServices).Assembly) {}
However, the FindMovies request DTO does not have an associated service and therefore won't be included. No routes are registered.
If I pass typeof(FindMovies).Assembly instead of or in addition to typeof(ContactsServices).Assembly, then the pre-defined route will be registered (i.e. shows up in the metadata, postman, etc.) but the custom route is still not registered (i.e. does not show up in the metadata, postman, etc.).
What is the best way to register the custom route using attributes when there is no service and the ServiceModel and ServiceInterface are in separate projects?
These issues should be resolved in v4.0.24+ that's now available on MyGet.
There's a new AutoQueryFeature.LoadFromAssemblies property to specify an additional list of assemblies to scan for IQuery Request DTO's. This automatically looks in the assemblies where your other Request DTO's are defined so in most cases nothing needs to be done as it will automatically be able to find your query services.
The routes for Query DTO's should now appear on the metadata pages as well as Swagger and Postman metadata API's.
I am a fan of both Glassfish and MOXy, and it's good news for me that MOXy had been bundled into Glassfish v4.
I had read and tried a few of MOXy examples on the internet, I like the dynamic OXM_META_DATA_SOURCE part, since while providing RESTful services, the "client perspective" is very flexible than domain classes.
So here is the problem:
Different RESTful services can have different views from same domain classes, and in my work it's very common case. So there can be a lot of binding OXM metadata files for every service. And as we know a single OXM metadata file can only correspond to a single java package. So there will be much more OXM metadata files to maintain.
Back to JAX-RS, Is there any framework to design patterns or best practices to finish the mapping between OXM metadata file set and the service itself?
You can try new feature called Entity Filtering which has been introduced in Jersey 2.3. Even though Entity Filtering is not based on OXM_META_DATA_SOURCE you can achieve your goal with it:
Let's assume you have a following domain class (annotations are custom entity-filtering annotations):
public class Project {
private Long id;
private String name;
private String description;
#ProjectDetailedView
private List<Task> tasks;
#ProjectAnotherDetailedView
private List<User> users;
// ...
}
And, of course, some JAX-RS resources, i.e.:
#Path("projects")
#Produces("application/json")
public class ProjectsResource {
#GET
#Path("{id}")
public Project getProject(#PathParam("id") final Long id) {
return ...;
}
// ...
}
Now, we have 2 detailed views defined on domain class (via annotations) and the resource class. If you annotate getProject resource method with:
#ProjectDetailedView - returned entity would contain id, name, description AND a list of tasks from Project
#ProjectAnotherDetailedView - returned entity would contain id, name, description AND a list of users from Project
If you leave the resource method un-annotated the resulting entity would contain only: id, name, description.
You can find more information about Entity Filtering in the User Guide or you can directly try it in our example: entity-filtering.
Note 1: Entity Filtering works only with JSON media type (via MOXy) at the moment. Support for other media types / providers is planned to be added in the future.
Note 2: Jersey 2.3 is not integrated into any (promoted) build of GF 4.0. The next Jersey version that should be part of GF 4.0 is 2.4. We plan to release 2.4 in the next few weeks.
I'm still learning about DDD and I have these two (probably simple) questions:
If a Factory creates new object/graph/aggregate instances, but also "reconstitutes" objects/graphs from the Repository, then:
(1) Does your service layer functions/jobs/tasks/unit-of-work call into the Factory or a behavioural method on the Entity instance or a DomainService function? I'm lost as to the call stack based on the responsibility of these components.
(2) Do Entity instances even have "behavioural methods" like above? For example does a Post have p.UpdatePost(string bodyText) or is that not a concern of the domain model and so the same should be achieved with the Repository? Or the service layer function, should it be calling the Repository in this case and the entity instance simply have behavioural methods that are specific to the domain and not persistence? But then, why does it sound like "updating a post" is a domain function when that's the user's goal?
You can see I'm all over the place. Please help.
(1) Does your service layer functions/jobs/tasks/unit-of-work call into the Factory or a behavioral method on the Entity instance or a DomainService function? I'm lost as to the call stack based on the responsibility of these components.
Usually - top level retrieves necessary aggregate root and calls a function on it. Sometimes top level retrieves multiple aggregate roots and pass them to domain service, but not often because domain service is a quite strong sign that there is unrecognized aggregate root. At the end - top level ensures aggregate root is persisted.
(2) Do Entity instances even have "behavioural methods" like above? For example does a Post have p.UpdatePost(string bodyText) or is that not a concern of the domain model and so the same should be achieved with the Repository? Or the service layer function, should it be calling the Repository in this case and the entity instance simply have behavioural methods that are specific to the domain and not persistence? But then, why does it sound like "updating a post" is a domain function when that's the user's goal?
Yes, they do. Domain model should be aware of it's state changes. And that's much more beneficial as it seems at first. Great thing about this is that You gain extensibility point. If client will walk week later to You and say that he wants system to check additional things when user updates post - instead of searching every line of post.bodyText="new value", You will be able to go straight to post.UpdatePost method and attach necessary things there.
On the other hand - CRUD is not mutually exclusive with domain driven design. E.g. - in my application, management of users and their roles is uninteresting enough that I'm not even trying to model it granularly. You need to recognize parts what matters in business Your application is describing and working with.
Keep in mind that domain driven design makes sense for complex applications only. Simple blog application doesn't need it.
(3) Am I wrong in assuming that a service layer (not Domain Services) should encapsulate how an interface interacts with the Domain Layer?
As I see it - application services are more for orchestrating infrastructure. If there is no infrastructure involved - then application service loses value:
Application services basically are just facades. And every facade is bad if complexity it adds overweights problems it solves.
Inside domain:
//aggregate root is persistence ignorant.
//it shouldn't reference repository directly
public class Customer{
public string Name {get; private set;}
public static Customer Register(string name){
return new Customer(name);
}
protected Customer(string name){
//here it's aware of state changes.
//aggregate root changes it's own state
//instead of having state changed from outside
//through public properties
this.Name=name;
}
}
//domain model contains abstraction of persistence
public interface ICustomerRepository{
void Save(Customer customer);
}
Outside of domain:
public class CustomerRepository:ICustomerRepository{
//here we actually save state of customer into database/cloud/xml/whatever
public void Save(Customer customer){
//note that we do not change state of customer, we just persist it here
_voodoo.StoreItSomehow(customer);
}
}
//asp.net mvc controller
public class CustomerController{
public CustomerController(ICustomerRepository repository){
if (repository==null)throw new ArgumentNullException();
_repository=repository;
}
public ActionResult Register(string name){
var customer=Customer.Register(name);
_repository.Save(customer);
}
}