When I working with a DTO inside a ManagedBean, should I encapsulate the getters and setters?
class UserMBean {
private UserDTO user;
public String getName() {
return user.getName();
}
public void setName(String name) {
user.setName(name);
}
}
Or access directly the parametters from JSF:
<h:outputText value=#{userMBean.user.name} />
In general, people tend to use such encapsulation to hide the specific implementation of services or the structure of the model. It's an abstraction in order to make your code easier to modify without having to change the code on other places as well.
If you "flatten" your model this way, you actually just shift the knowledge of how your model looks like from the facelets to the managed bean. If you change your model now, you need to change the javacode instead of the xhtml code. One benefit in this scenario is that you now have a compile time error instead of runtime. On the other hand you kind of introduced duplicated code. Since your model is probably likely to change less often compared to service implementations, I usually "deeply" access my models in the xhtml code, because it saves time and is just more comfortable and keeps the managed beans more clean. In your simple case I would avoid the additional getter.
It is, as so often, a matter of taste and usecase specific. If you "deeply" access a property of your model through five (model) layers, and you do this in ten different places and you know that your model structure might change soon, it starts to make more sense to have a utility method to directly access this property with an additional getter in one place in a managed bean.
However there is one more case where it is necessary to offer direct access to properties. If you want to avoid someone accessing other properties. That means, you want to keep certain attributes non-accessible. Let's say your UserDTO also a property password and you don't want anyone to be able access that in your xhtml to display or change it, then roll with your second option and don't have a getUser(), but offer direct access to the username via getUserName().
Related
I have a general JSF problem, I found no nice solution for yet. See the picture for a general idea. I have a workaround solution (sorry for the typo in the image) in place that solves the problem by a listbox. However the desired solution is to display all existing versions next to each other (probably always around 1-3).
I have a view with a tree and picklist. There is a complex flow regarding the interaction between list and tree, e.g. you can only move models to subgroups, not top-level-groups and much more. I created a handler class that manages this behavior and translates it to service calls.
Now, a new requirement came up. There are several versions of this tree that should be displayed all together on one page. My gut feeling is that managing n versions in one handler is a big mess as I need to store several things in the handler already for one version.
In React, I would create a component that wraps the tree and all of the interaction. However, in JSF I'm not so sure what is the best practice here?
I would be happy about suggestions and ideas, I'm not expecting Code :)
I found a solution that fits my needs and I post it here hoping that it might help other people as well :)
So on my view I have several tree views with complex interactions. For example, if an item within the tree is moved, the operation is immediately reflected in the database. As I use JPA, I need to translate this to an entitymanager call.
The views are either displayed in a list or just one-at-a-time via a dropdown select.
Anyway, the idea is that every complex view component has its own controller with a reference to an entitymanager and a transaction, while having just one JSF handler class. If JSF would allow to create multiple handlers (like #{handler_1}, {handler_2}), the problem could be solved in a different way. But as JSF works name based and the name {#handler} always refers to the same container managed thing, this is no option.
The handler class is ViewScoped (or SessionScoped, if you prefer). For each tree component it has a ComponentController class that receives the EntityManager and the UserTransaction as well as the related data form the handler via constructor injection. This way, the handler can delegate all commands to the Controller while being DRY.
With this solution, the controller logic can be re-used regardless how many tree components exist. Each view elements binds a specific controller via handler.controllers.get(id).
All other solutions did not work for me as they are not able to perform database operations on view interactions.
Good day
This question is more of a meta question than a specific problem based question.
It is always a good idea to separate any and all DB code from view related code and view files, correct?
Thus is my assumption when using JSF correct in that:
The xhtml file forms part of the view in the MVC.
The #Named backing beans also forms part of the view.
To ensure that one can relatively painlessly migrate away from JSF to another type of tech, one would ensure to not have ANY DB code inside the #Named backing beans.
All DB code should reside in a controller / service class.
The controller / service class will contain all the DB access code and business logic. This thus forms the controller of the MVC.
The #Entity classes are used to map the DB to JPA and this thus forms the model of the MVC.
Now, if my understanding of the above is correct, what would best methods and methodologies be when handling the following scenario:
I have an XHTML file displaying JSF components (Primefaces). The lists and component linked members that link the JSF components to the Java code all resides in the #Named backing bean.
Now for argument sake, let's say that the specific form is used to CRUD a supplier's information, which of the following methods is recommended as best practices (while attemping to maintain as much seperation of concern between the View and the Controller Java code) when for instance edits were made on the XHTML form:
Enforce ZERO DB code (thus never defining or using the Entity Manager) in the #Named backing bean file). The code to persist the changes after all input validation was successfully done, will reside in the Controller. To get these values to the Controller, we will have a function looking perhaps like this (basically send all the components on the xhtml form as parameters to a function in the Controller):public void supplierService (String supName, String SupAddress, String supTel....) The problem with this of course is that one may end up running into methods that takes tens of parameters. Very ugly and difficult to maintain.
Accept that separating some DB code is not possible and every #Named file must have the required JPA DB code to persist and or merge changes to the models (however if this is considered best practice, what is the use of having Controller classes?).
Create a temporary object of the same type as the model and set the attributes of this temporary object to the values obtained from the XHTML mapped components. Then only pass this temporary object to a method in the Controller. This method in the Controller will then persist and or merge the passed object's info. However I feel this may introduce unnecessary object instantiation overhead. Also I am not 100% sure what exactly happens 'behind the scenes' when I have a model named SupplierEntity.java that is mapped via JPA to a PostgreSQL DB and I call this code: SupplierEntity tempSup = new SupplierEntity(); Will JPA via Hibernate on Wildfly actually at this point create a new entity (record in the DB), and as such I cannot use this to create a temporary object to hold the values I am passing to the Controller as a temp instance of the underlying JPA entity, or will Hibernate (using JPA 2.1) ONLY create a new record when I do em.persist(mySupplier); and thus it is safe to use this method to pass objects to the controller's persisting method, instead of passing tens of parameters to the persisting method.
Something completely different than what I mentioned above is considered to be the best practice for separating the MVC components in JSF as much as possible, while still preventing having to pass 50 parameters to the Controller.
Please as said right in the start, this is a meta question regarding best practices. If Stackoverflow is not the right forum for these questions, instead of down voting this into oblivion, please let me know where I should ask instead and I will gladly delete the question from here and create it on the right forum.
To not have to keep repeating some validations, for example, who can see a button in a certain status of a document in the worlflow, I'm using session, scope, and session variables to store the user roles and application variable to store the Status related to each area.
I was evaluating whether it would be better from a performance and build point of view to implement a managed bean, to return the user roles and the possible statuses of each participating workflow area. Would it be the best structure in fact? What do you think? I do not have much experience in java. How could I construct the structure in java, several methods, one for roles and the other for set of status associated with the area that would name the related method? You could return the results of this method in arrays, or there is a better return structure.
Thanks a lot!
My best suggestion is to adopt the pageController Methodology. Then it's more like true MVC. This has been talked about on NotesIn9 screencast many times but basically you have a java object that's bound to your XPage. In effect it's a viewScoped bean that holds all your page logic. Then you can have methods like isGroupMember(), hasRole() etc and calculate that on the pageInit. There's little need to hold onto that in sessionScope in my opinion. So for example I have this in my pageController :
public boolean isGroupMember(String groupName) {
return JSFUtil.getXSPContext().getUser().getGroups().contains(groupName);
}
So that's available to each page. BUT I don't need to copy that snippet onto every page controller. In Java you can have your page controllers extend a more generic class. so I have a "base.pageController" class. All the specific page controllers extend that. So this isGroupMember() code goes into the base and then it's available to be used on every XPage. Doing it this way gives you the ability to have generic functions like this and then hold more specific function that are only for the individual page.
You can also have a hasRole() function etc...
Recommend you check out this video : http://www.notesin9.com/2016/08/25/notesin9-196-no-dependency-page-controllers/
Also for a question like this, I recommend you just use the xpages tag. Adding others like javabeans can bring people in who know nothing about XPages and XPages is unique enough of a beast that outsiders can cause some confusion on occasion.
Problem description
At the company I work for we're implementing a web application using JSF2 and PrimeFaces. The web app is one of the front-ends hitting a bunch of business methods and a domain model created as a set of entity classes and persisted using JPA. We also have a couple of webservice methods operating on that same domain model. Because of this we want to implement as much of our validation logic as possible using bean validation on the entity level. So far everything's working out quite nice but we recently bumped into a problem I don't really know how to deal with. To improve user experience we trigger most of the bean-validation logic using AJAX (using p:ajax update="errorMessageForFieldWhatever"), for example when the user tabs out of a text field, changes a value in a dropdown, etc so that they have immediate feedback about the error. This all works fine when dealing with field/property-level constraints but I don't see how to make it work properly with class-level bean validators. Let me illustrate with an example.
Assume the following entity object, CDI bean and facelets view, and a custom bean validator which requires that MaxValue is greater than MinValue.
#Entity
#CustomClassLevelBeanValidator
public class Model {
#Min(10) int minValue; int maxValue; // getters/setters ommitted }
#Named
#SessionScoped
public class ModelBean {
#Valid private Model model; // getter and initialization ommitted }
<f:form>
min value:
<p:inputText id="minValue" value="#{modelBean.model.minValue}">
<p:ajax process="#this" update="minValueErrorMessage"/>
</p:inputText>
<p:message for="minValue" id="minValueErrorMessage"/>
max value:
<p:inputText id="maxValue" value="#{modelBean.model.maxValue}"/>
<p:message for="maxValue"/>
</f:form>
What we want to achieve is the following:
When the user tabs out of minValue, the error message for that field gets updated. This already works because of standard JSF/single-field-bean-validation integration.
When the user tabs out of EITHER minValue or maxValue, the error message for maxValue should be updated. Note that this really consists of 4 separate cases: the constraint can become valid as well as invalid through changes in minValue and the same goes for maxValue. I'm not clear how to make this work without resolving to JSF-level validation.
Current state of affairs
Direct updating of single-field error messages on ajax events already works (out of the box).
By making use of MyFaces' ExtVal component we also managed to trigger class-level validations on form submit, although all constraint violations end up in the "global errors" section (p:messages globalOnly, which makes sense since during class-level bean validation you do not specify which property failed validation).
We already implemented a solution which is functionally equivalent to what I lined out above (from a user's perspective) but I hate it. It involves a lot of process=this/update=that on the facelets side and sometimes the use of JSF-level validation thereby violating DRY since we'll have to repeat those constraints in the domain model again to make sure webservice calls are properly validated, too.
If it turns out that what we want to achieve is not possible/feasible we'll have to settle for triggering field-level constraints through AJAX and process all the cross-field stuff on form submit. It's not that bad actually but I'm hoping we can do better. Coming from a .NET background I remember this kind of stuff being reasonably easy to implement using WPF and IDataErrorInfo.
Solution requirements
An ideal solution would satisfy all of the following requirements:
Be fully implemented using Bean Validation alone, no FacesMessages etc
Allows direct feedback to the end user after editing a form field, on validation errors on that specific field and all other fields whose constraints are affected by it
Shows validation errors "where they belong", e.g. in the above example the rule "max > min" is, at least from a user's perspective, tied to the "maxValue" field. The fact that such a constraint is not strictly an error on maxValue but rather a relation between both fields doesn't really matter, I should be able to pick one of the two as the "victim" for validation and present the end user with the message "sorry, that specific field is wrong".
I understand that this is not possible in the general case having constraints over N fields some of which may not even be in the current view, but I think stuff like min > max, endDate > startDate etc could be covered.
Where to go from here?
As far as I'm aware there's nothing in JSF, BeanValidation or PrimeFaces that let's me achieve this. I'm not so sure about ExtVal, it seems designed to be very extensible but even then I wouldn't know where to start. If there's anything in any of these libraries which I completely overlooked and that let's me solve this problem, please let me know!
If not, what would it take to build a custom solution to this problem? I've thought about manually implementing this, something along the lines of a custom phaselistener which triggers all bean validators for all submitted fields in the current views and turns them into FacesMessages. However I suspect this will not be an easy task:
Standard class-level ConstraintViolations don't carry a leafBean/property-path, without that, validation error's probably can't be matched to jsf's client-ids
JSF does not apply model values if any of them fails validation. In cross-field validation scenarios it is possible that applying a single value violates a constraint, while applying all of them would make the object valid again (how does ExtVal do this? does it not follow JSF's rules?)
Do we validate during PROCESS_VALIDATIONS? If so, should we enable DISABLE_DEFAULT_BEAN_VALIDATOR context param to allow otherwise invalid model values to populate the entity?
It seems part of the problem is that JSR303 sees constraint validation as a state (an object is either valid or not) while JSF sees it as an action (no, you can't submit this form, it's invalid). Will JSF2.2 make life easier in this regard? I wouldn't mind a user submitting invalid values, we'll just make sure not to store them in the DB ourselves. At least this solves the problem of having to reset UIInput components.
The longer I think about this the more I suspect it's just not going to work the way I want it to. Still I feel kind of stupid having to tell our users that "no sorry, end date must be after start date is such a complicated business rule that we cannot give feedback directly, you'll only bump into that error when you submit the entire form." So if anyone comes up with a solution which fullfills all requirements I'd be very grateful to hear about it.
Ok I know scope questions come up all the time but I'm interested in a slightly different approach to the solution. The #ViewScope is a fantastic bridge between the #RequestScope and the #SessionScope.
However there is still a common use case (at least for me) where I really don't want to use #SessionScope but I need the data over a couple of views. A really simple case is when I have multiple datatables chained together each one depending on previous selections.
It's perfectly possible to use <f:paramView> and pass a single or even a couple of pieces of data as params in the address and then retrieve everything from the database again. I am more interested in finding a way of creating a 'snapshot' of the beans state / variables, creating the new #ViewScope and then 'restoring' the 'snapshot state' to the new bean.
Does such a thing exist? Ideas? Opinions?
I don't know if this is the 'accepted solution' but I've implemented an idea that works for me. (Feedback appreciated!)
So I have created a #SessionScoped class with a couple of static maps:
private static Map<String, Object> objectVariableMap;
// Getters, setters and methods etc. are omitted for simplicity
The idea being that I have specified a map that accepts a String as the key and an Object as the value. I've specifically not set the type of object to allow me to store any type of object in there. The caveat is that you need to be sure of the type of object when retrieving it so you can cast it back into its original type.
Now comes the time to set the data from the first #ViewScoped. I generate a random UUID (or what ever you want) as the Map key and then set the value to the object I'm working with (ie. this, or indeed any other objects you might want to pass to the next view). Save the key, value into the map and set the URL param to the key.
I'm never keen on passing data like user id's etc. in URL params (even when its encrypted). This idea has the added benefit of offering disposable URL values that have a specifiable life span.
On the receiving end (ie. The new #ViewScoped bean, or any other scope for that matter) you read in the URL param (the map key) using <f:paramView> and then use a preRenderView event to retrieve and set the Object where working with.
At this point you can choose to remove the key pair from the Map and invalidate the ability to retrieve that object or you can keep keep the key pair for a longer duration by simply updating the object if there are any changes.
UPDATE: Conceptually this has been really successful (for me at least). I've created a handfull of useful methods and classes surrounding the concept to make it more universal. If anybody wants more specific instructions or I might even create a small library if anybody wants.
You can use the CDI "Conversation Scope" for this. This is narrower than the session scope but wider than the view scope.
If the pages between which you pass parameters are a unit, you can also make them a flow in JSF 2.2 and use the flow scope.
Projects like CODI offer various other scopes that can be used between pages.