Grails nested domains - addAll errors to top level domain object - java

I have a Grails domain like this:
class User {
....
Address address
}
While saving the user, I want to validate the Address object as well and add all errors of Address object to the User object itself.
I am trying to write a custom validator wherein I do it.validate(), but I am not able to find a way to "addAll" the error messages of address.

This discussion below on the grails mailing list about calling validation on child objects and appends them to a single errors list that might work for you.
Form validation with children
If Address has static belongsTo = [user:User] then calling User.validate() or User.save() should also call validation on Address. I've not tried collecting errors on a child object into the parent object's errors list, but for a simple one-to-one association you may not need to, and simply display the errors something like this:
<g:if test="${user?.hasErrors() || user.address?.hasErrors()}">
<div class="errors">
<g:hasErrors bean="${user}">
<g:renderErrors bean="${user}" as="list" />
</g:hasErrors>
<g:hasErrors bean="${user?.address}">
<g:renderErrors bean="${user?.address}" as="list" />
</g:hasErrors>
</div>
</g:if>

Since this is probably a frontend related task, I would not try to fiddle with those error classes. I advance you to just call the validate function within the custom validator like this:
address(validator: { val, obj ->
val?.validate();
});
In the GUI you will find your error messages for the nested domain class within the instance of the nested domain class. Therefore you need to pass the domain class to the GSP.
<g:renderErrors bean="${address}" field="street" />
However if you really want to get a new collection having all errors inside of all nested classes you can have a look at the plugin http://www.grails.org/plugin/extended-validation. With this plugin you have an additional error set, which contains all error messages of nested domain classes (if it is configured to do like this):
user.allErrorsRecursive()
But to be honest, I have not tested it yet ;)

Related

How to retrieve a specific Member from a Discord Guild using Java JDA

I am trying to get a specific Member object from a Guild by using the following:
event.getGuild().getMember(user)
Here, user is the User object of the user I want to get the Member object from. I have also tried using the .getMemberById, using the userID instead. However, in both cases I get a null-pointer exception.
I am sure that both my User object and userID are correct, because when adding a breakpoint it does show these, but it doesn't retrieve the Member, this stays null. Am I approaching this wrong?
I have also tried putting the following in my main file where I start the bot:
JDABuilder builder = JDABuilder.createDefault(BOT_TOKEN);
builder.enableIntents(GatewayIntent.GUILD_MEMBERS);
On the Discord developer portal I have enabled both the 'Privileged Gateway Intents' options.
The documentation of Guild#getMember tells you to see also Guild#retrieveMember which can be used to load members that are not cached.
If you have an event with a getMember() or retrieveMember() method, that should be used instead. Otherwise you can do this:
guild.retrieveMember(user).queue(member -> {
... use member here
});
Other alternatives are outlined in the JDA wiki here: Gateway Intents and Member Cache Policy
Most of these retrieval methods DO NOT require the privileged intent GUILD_MEMBERS. It is only required if you want to interact with the entire member list of a server, through methods like loadMembers or findMembers for example.

Use placeholders in feature files

I would like to use placeholders in a feature file, like this:
Feature: Talk to two servers
Scenario: Forward data from Server A to Server B
Given MongoDb collection "${db1}/foo" contains the following record:
"""
{"key": "value"}
"""
When I send GET "${server1}/data"
When I forward the respone to PUT "${server2}/data"
Then MongoDB collection "${db2}/bar" MUST contain the following record:
"""
{"key": "value"}
"""
The values of ${server1} etc. would depend on the environment in which the test is to be executed (dev, uat, stage, or prod). Therefore, Scenario Outlines are not applicable in this situation.
Is there any standard way of doing this? Ideally there would be something which maintains a Map<String, String> that can be filled in a #Before or so, and runs automatically between Cucumber and the Step Definition so that inside the step definitions no code is needed.
Given the following step definitions
public class MyStepdefs {
#When("^I send GET "(.*)"$)
public void performGET(final String url) {
// …
}
}
And an appropriate setup, when performGET() is called, the placeholder ${server1} in String uri should already be replaced with a lookup of a value in a Map.
Is there a standard way or feature of Cucumber-Java of doing this? I do not mind if this involves dependency injection. If dependency injection is involved, I would prefer Spring, as Spring is already in use for other reasons in my use case.
The simple answer is that you can't.
The solution to your problem is to remove the incidental details from your scenario all together and access specific server information in the step defintions.
The server and database obviously belong together so lets describe them as a single entity, a service.
The details about the rest calls doesn't really help to convey what you're
actually doing. Features don't describe implementation details, they describe behavior.
Testing if records have been inserted into the database is another bad practice and again doesn't describe behavior. You should be able to replace that by an other API call that fetches the data or some other process that proves the other server has received the information. If there are no such means to extract the data available you should create them. If they can't be created you can wonder if the information even needs to be stored (your service would then appear to have the same properties as a black hole :) ).
I would resolve this all by rewriting the story such that:
Feature: Talk to two services
Scenario: Forward foobar data from Service A to Service B
Given "Service A" has key-value information
When I forward the foobar data from "Service A" to "Service B"
Then "Service B" has received the key-value information
Now that we have two entities Service A and Service B you can create a ServiceInformationService to look up information about Service A and B. You can inject this ServiceInformationService into your step definitions.
So when ever you need some information about Service A, you do
Service a = serviceInformationService.lookup("A");
String apiHost = a.getApiHost():
String dbHost = a.getDatabaseHOst():
In the implementation of the Service you look up the property for that service System.getProperty(serviceName + "_" + apiHostKey) and you make sure that your CI sets A_APIHOST and A_DBHOST, B_APIHOST, B_DBHOST, ect.
You can put the name of the collections in a property file that you look up in a similar way as you'd look up the system properties. Though I would avoid direct interaction with the DB if possible.
The feature you are looking for is supported in gherkin with qaf. It supports to use properties defined in properties file using ${prop.key}. In addition it offers strong resource configuration features to work with different environments. It also supports web-services

xp:checkbox breaks programme

On an XPage I have placed a checkbox group:
<xp:checkBoxGroup
value="#{employeeBean.employee.concern}"
disabled="#{employeeBean.employee.editable eq false}">
<xp:selectItem itemLabel="yes"></xp:selectItem>
<xp:selectItem itemLabel="no"></xp:selectItem>
<xp:selectItem itemLabel="maybe"></xp:selectItem>
</xp:checkBoxGroup>
I have binded the value of the control to field in my Proposal class via a managed bean.
The field concern is of type string and has its out of the box getters and setters.
The problem is whenever I include the data-binding and change values the complete XPage SSJS fails. I do not get an error in the console (server, web client).
Does this have something to do with the type of value the checkbox returns or should I change the type of field in my class?
One thing that springs to mind is the employee object. If this is not set (i.e. there is an instance of the object) then it will fail with a null pointer exception.
In your case it is quite valid the concern field is of type String - obviously you will need a getConcern() and setConcern(String value) method.
Now the real problem is that you cannot see what the server thinks is wrong!
The best way to get to that is to look at the stack traces in the logs. And by far the easiest way to do that is to install the "XPages Log File Reader" application from OpenNTF.org
But my guess is that you haven't created an employee object prior to calling the getEmployee() method to return it ;-)
/John

Lifefay freemarker ADT: methods unavailable?

I'm trying to work on some ADT for asset publisher (Documents and Media type), but I often have a message telling me that :
Expression assetRenderer.getDataRepositoryId is undefined
or
Expression assetRenderer.getFileEntryId is undefined
I found some threads where people said that we must add
velocity.engine.restricted.classes=
velocity.engine.restricted.variables=
freemarker.engine.restricted.classes=
freemarker.engine.restricted.variables=
in portal-ext.properties to get some more classes and variables available, but still I'm not able to call some methods and i don't know why.
I did a
${assetRenderer.getClassName()}
which returns: com.liferay.portlet.documentlibrary.model.DLFileEntry
So I should be able to use any DLFileEntry class public methods (and extended classes), right?
What do I miss?
Asset renderer renders asset entries of the given class (ei. JournalArticle or DLFileEntry in your case). Asset renderer itself is not instance of the given class (in Java sense). It is always instance of com.liferay.portlet.asset.model.AssetRenderer.
To get instance of the related DLFileEntry, you must use DLFileEntryLocalService to find it.
<#-- Obtains instance of DLFileEntryLocalService -->
<#assign DLFileEntryLocalService = serviceLocator.findService("com.liferay.portlet.documentlibrary.service.DLFileEntryLocalService") />
<#-- Function returning underlying DLFileEntry for the given AssetEntry -->
<#function getDLFileEntry assetEntry>
<#return DLFileEntryLocalService.getDLFileEntry(assetEntry.getClassPK())/>
</#function>
Please note, that you need to enable the usage of serviceLocator explicitly by setting freemarker.engine.restricted.variables= in portal-ext.properties.

Using Stripes, what is the best pattern for Show/Update/etc Action Beans?

I have been wrestling with this problem for a while. I would like to use the same Stripes ActionBean for show and update actions. However, I have not been able to figure out how to do this in a clean way that allows reliable binding, validation, and verification of object ownership by the current user.
For example, lets say our action bean takes a postingId. The posting belongs to a user, which is logged in. We might have something like this:
#UrlBinding("/posting/{postingId}")
#RolesAllowed({ "USER" })
public class PostingActionBean extends BaseActionBean
Now, for the show action, we could define:
private int postingId; // assume the parameter in #UrlBinding above was renamed
private Posting posting;
And now use #After(stages = LifecycleStage.BindingAndValidation) to fetch the Posting. Our #After function can verify that the currently logged in user owns the posting. We must use #After, not #Before, because the postingId won't have been bound to the parameter before hand.
However, for an update function, you want to bind the Posting object to the Posting variable using #Before, not #After, so that the returned form entries get applied on top of the existing Posting object, instead of onto an empty stub.
A custom TypeConverter<T> would work well here, but because the session isn't available from the TypeConverter interface, its difficult to validate ownership of the object during binding.
The only solution I can see is to use two separate action beans, one for show, and one for update. If you do this however, the <stripes:form> tag and its downstream tags won't correctly populate the values of the form, because the beanclass or action tags must map back to the same ActionBean.
As far as I can see, the Stripes model only holds together when manipulating simple (none POJO) parameters. In any other case, you seem to run into a catch-22 of binding your object from your data store and overwriting it with updates sent from the client.
I've got to be missing something. What is the best practice from experienced Stripes users?
In my opinion, authorisation is orthogonal to object hydration. By this, I mean that you should separate the concerns of object hydration (in this case, using a postingId and turning it into a Posting) away from determining whether a user has authorisation to perform operations on that object (like show, update, delete, etc.,).
For object hydration, I use a TypeConverter<T>, and I hydrate the object without regard to the session user. Then inside my ActionBean I have a guard around the setter, thus...
public void setPosting(Posting posting) {
if (accessible(posting)) this.posting = posting;
}
where accessible(posting) looks something like this...
private boolean accessible(Posting posting) {
return authorisationChecker.isAuthorised(whoAmI(), posting);
}
Then your show() event method would look like this...
public Resolution show() {
if (posting == null) return NOT_FOUND;
return new ForwardResolution("/WEB-INF/jsp/posting.jsp");
}
Separately, when I use Stripes I often have multiple events (like "show", or "update") within the same Stripes ActionBean. For me it makes sense to group operations (verbs) around a related noun.
Using clean URLs, your ActionBean annotations would look like this...
#UrlBinding("/posting/{$event}/{posting}")
#RolesAllowed({ "USER" })
public class PostingActionBean extends BaseActionBean
...where {$event} is the name of your event method (i.e. "show" or "update"). Note that I am using {posting}, and not {postingId}.
For completeness, here is what your update() event method might look like...
public Resolution update() {
if (posting == null) throw new UnauthorisedAccessException();
postingService.saveOrUpdate(posting);
message("posting.save.confirmation");
return new RedirectResolution(PostingsAction.class);
}

Categories

Resources