Java Optional why not an ifNotPresent method? - java-8

I was wondering why on the Java8 API the Optional class have the method ifPresent(Consumer< T> consumer) and not the ifNotPresent(Runnable** consumer)?
What's the intent of the API? Isn't it to emulate the functional pattern matching?
** Java doesn't have a zero argument void functional interface...

As Misha said, this feature will come with jdk9 in the form of a ifPresentOrElse method.
/**
* If a value is present, performs the given action with the value,
* otherwise performs the given empty-based action.
*
* #param action the action to be performed, if a value is present
* #param emptyAction the empty-based action to be performed, if no value is
* present
* #throws NullPointerException if a value is present and the given action
* is {#code null}, or no value is present and the given empty-based
* action is {#code null}.
* #since 9
*/
public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) {
if (value != null) {
action.accept(value);
} else {
emptyAction.run();
}
}

Related

How to disable retry in spring boot without removing it?

i have 2 methods in class:
#Retryable(maxAttemptsExpression="${retry.maxAttempts}", backoff=#Backoff(delayExpression = "${retry.delay}", multiplierExpression = "${retry.multiplier}"))
public void foo() {
/**some body**/
}
#Recover
public void fooRecover() {
/**some body**/
}
In some cases i need to disable retrying, but maxAttempts can't be equals zero, so i can't simply do it. So how to correctly disable retrying in some cases?
#Retryable annotation has a property exceptionExpression where you can specify SpEL expression that evaluates to true or false.
/**
* Specify an expression to be evaluated after the
* {#code SimpleRetryPolicy.canRetry()} returns true - can be used to conditionally
* suppress the retry. Only invoked after an exception is thrown. The root object for
* the evaluation is the last {#code Throwable}. Other beans in the context can be
* referenced. For example: <pre class=code>
* {#code "message.contains('you can retry this')"}.
* </pre> and <pre class=code>
* {#code "#someBean.shouldRetry(#root)"}.
* </pre>
* #return the expression.
* #since 1.2
*/
String exceptionExpression() default "";
So if you want to disable retry you can inject boolean string parameter with value "false"
#Retryable(exceptionExpression = "${retry.shouldRetry}", ...other stuff...)
I think the problems are on the conditions. In which case you want to retry and which you want to stop?
So then you can define the value=?Exception.class in the annotation.
For example:
#Retryable(value=MUST_RETRY_EXCEPTION.class)
public void foo() {
if (condition) {
throw new MUST_RETRY_EXCEPTION(...);
}
if (condition2) {
throw new NO_RETRY_EXCEPTION(...);
}
}
remove #Retryable, you simply don't want what code dose then remove it

Symfony API-Platform Assert\Choice does not work on setter

My app has a very standard user comment feature with also standard possibility for any visitor to mark comments as inappropriate.
In the resolution process for these marked comments the admin will decide which action to take, between no action, edit the comment or remove it.
The CommentReport entity includes Assert\Choice to allow only the 3 choices above.
The issue is that it is accepting any string.
On the Comment entity the set up is as follows:
....
* graphql={
* "withCustomArgsMutation"={
* "security"="is_granted('ROLE_ADMIN')",
* "mutation"=CommentReputationTypeResolver::class,
* "args"={
* "id"={"type"="ID!"},
* "resolutionType"={"type"="String!"},
* },
* "denormalization_context"={"groups"={"put-resolution"}},
* "normalization_context"={"groups"={"get"}}
* },
.....
/**
* #ORM\OneToMany(targetEntity=CommentReport::class, mappedBy="comment")
* #Groups({"get", "get-admin", "get-owner", "put-resolution"})
*/
private $commentReports;
Then the CommentReports entity:
class CommentReport
{
const RESOLUTION_TYPES = [
'no_action',
'edit',
'remove',
];
.....
/**
* #ORM\Column(type="string", length=10, nullable=true)
* #Assert\NotBlank(
* message="commentReport.resolutionType.notBlank",
* groups={"put-resolution"}
* )
* #Assert\Choice(
* choices=CommentReport::RESOLUTION_TYPES,
* message="commentReport.resolutionType.choice",
* groups={"put-resolution"}
* )
* #Groups({"get-admin", "put-resolution"})
*/
private $resolutionType;
Then on the DeserializeStage the request is intercepted to handle the setting of each individual CommentReport made for that Comment:
/Stage/DeserializeStage.php
if ($this->isAdmin($user) && $resourceClass === 'App\Entity\Comment' && $operationName === 'withCustomArgsMutation') {
// get all comment reports
$commentReports = $deserializeObject->getCommentReports();
foreach($commentReports as $report) {
$report->setResolutionType($context['args']['input']['resolutionType']);
}
}
All of this works but I can input any string and it will be accepted.
Of course, the expected result would be that Symfony would throw an exception for any string not on the RESOLUTION_TYPES array.
For info, this is the front-end mutation that triggers input:
`mutation putCommentReport(
$commentId: ID!
$resolutionType: String!
) {
withCustomArgsMutationComment(input: {
id: $commentId
resolutionType: $resolutionType
}){
comment{
id
}
}
}`;
As #Jeroen van der Laan pointed out, the validation group annotation was missing on the operation, which should be as follows;
App\Entity\Comment
* graphql={
* "withCustomArgsMutation"={
* "security"="is_granted('ROLE_ADMIN')",
* "mutation"=CommentReputationTypeResolver::class,
* "args"={
* "id"={"type"="ID!"},
* "resolutionType"={"type"="String!"},
* },
* "normalization_context"={"groups"={"get"}},
* "validation_groups"={"put-resolution"}
* },
Additionally, the Valid() assertion needs to be added to the CommentReport relation on Comment:
/**
* #ORM\OneToMany(targetEntity=CommentReport::class, mappedBy="comment")
* #Assert\Valid()
* #Groups({"get", "get-admin", "get-owner"})
*/
private $commentReports;

Both ArtBox and TrimBox on a page in iText7

Its not possible to put a artbox and trimbox on a page with iText7.0.5.0
The source states then only a trimbox or a ArtBox can exist on a page.
This is not true, they can exist both on a page.
Line 615 of PdfPage.java
/**
* Sets the TrimBox object, that define the intended dimensions of the finished page after trimming.
*
* #param rectangle the {#link Rectangle} object to set, expressed in default user space units.
* #return this {#link PdfPage} instance.
*/
public PdfPage setTrimBox(Rectangle rectangle) {
if (getPdfObject().getAsRectangle(PdfName.ArtBox) != null) {
getPdfObject().remove(PdfName.ArtBox);
Logger logger = LoggerFactory.getLogger(PdfPage.class);
logger.warn(LogMessageConstant.ONLY_ONE_OF_ARTBOX_OR_TRIMBOX_CAN_EXIST_IN_THE_PAGE);
}
put(PdfName.TrimBox, new PdfArray(rectangle));
return this;
}
/**
* Sets the ArtBox object, that define the extent of the page’s meaningful content
* (including potential white space) as intended by the page’s creator.
*
* #param rectangle the {#link Rectangle} object to set, expressed in default user space units.
* #return this {#link PdfPage} instance.
*/
public PdfPage setArtBox(Rectangle rectangle) {
if (getPdfObject().getAsRectangle(PdfName.TrimBox) != null) {
getPdfObject().remove(PdfName.TrimBox);
Logger logger = LoggerFactory.getLogger(PdfPage.class);
logger.warn(LogMessageConstant.ONLY_ONE_OF_ARTBOX_OR_TRIMBOX_CAN_EXIST_IN_THE_PAGE);
}
put(PdfName.ArtBox, new PdfArray(rectangle));
return this;
}
Proposed solutions:
/**
* Gets the {#link Rectangle} object specified by page's ArtBox, that define the extent of the page’s
* meaningful content (including potential white space) as intended by the page’s creator.
*
* #return the {#link Rectangle} object specified by page's ArtBox, expressed in default user space units.
* CropBox by default.
*/
public Rectangle getArtBox() {
Rectangle artBox = getPdfObject().getAsRectangle(PdfName.ArtBox);
return artBox == null ? getCropBox() : artBox;
}
/**
* Sets the TrimBox object, that define the intended dimensions of the finished page after trimming.
*
* #param rectangle the {#link Rectangle} object to set, expressed in default user space units.
* #return this {#link PdfPage} instance.
*/
public PdfPage setTrimBox(Rectangle rectangle) {
put(PdfName.TrimBox, new PdfArray(rectangle));
return this;
}

Cannot create async method which return ElementArrayFinder for E2E tests

I have a class where I want to make a async method which will return ElementArrayFinder. I need exactly this type, not ElementFinder[] because my waiters based on it and I can wait element which isn't present now in DOM. Below you can find a simple example of the structure. At row 'return this.collection;' i have an error:
[ts]
Type 'any[]' is not assignable to type 'ElementArrayFinder'.
Property 'browser_' is missing in type 'any[]'.
I tried to cast result in a different way and tried to use Promise.resolve, but no success. Could somebody help me with this case?
export class Test {
private grid1: ElementFinder;
private grid2: ElementFinder;
get collection1(): ElementArrayFinder {
return this.grid1
.element(by.css('tbody'))
.all(by.tagName('tr'));
}
get collection2(): ElementArrayFinder {
return this.grid2
.element(by.css('tbody'))
.all(by.tagName('tr'));
}
public async getCollection(): Promise<ElementArrayFinder> {
if (await this.collection.count() === 0) {
return this.collection1;
}
return this.collection2;
}
}
Bug report
Node Version: v8.2.1
Protractor Version: 5.2.0
I found the answer in file element.d.ts file.
/**
* Retrieve the elements represented by the ElementArrayFinder. The input
* function is passed to the resulting promise, which resolves to an
* array of ElementFinders.
*
* #alias element.all(locator).then(thenFunction)
* #view
* <ul class="items">
* <li>First</li>
* <li>Second</li>
* <li>Third</li>
* </ul>
*
* #example
* element.all(by.css('.items li')).then(function(arr) {
* expect(arr.length).toEqual(3);
* });
*
* // Or using the shortcut $$() notation instead of element.all(by.css()):
*
* $$('.items li').then(function(arr) {
* expect(arr.length).toEqual(3);
* });
*
* #param {function(Array.<ElementFinder>)} fn
* #param {function(Error)} errorFn
*
* #returns {!webdriver.promise.Promise} A promise which will resolve to
* an array of ElementFinders represented by the ElementArrayFinder.
*/
then<T>(fn?: (value: ElementFinder[] | any[]) => T | wdpromise.IThenable<T>, errorFn?: (error: any) => any): wdpromise.Promise<T>;
Based on this documentation ElementArrayFinder type is resolved by .then to the ElementFinder[]. That's why I cannot create method which return ElementArrayFinder type in promise, but can create method which simply return ElementArrayFinder type.

Is there a function like _compile_select or get_compiled_select()?

Looks like _compile_select is deprecated and get_compiled_select is not added to 2.1.0. Are there any other functions like those two? And also I am curious. Is there any particular reason to not adding get_compiled_select() to Active Record and removing _compile_select?
I've added get_compiled_select() to DB_active_rec.php and it seems to work without problem, but i wouldn't remove _compile_select() since it's used in many other methods.
The pull request for adding this method is here, with some other useful methods like:
get_compiled_select()
get_compiled_insert()
get_compiled_update()
get_compiled_delete()
https://github.com/EllisLab/CodeIgniter/pull/307
if you want just the method, it's just this:
/**
* Get SELECT query string
*
* Compiles a SELECT query string and returns the sql.
*
* #access public
* #param string the table name to select from (optional)
* #param boolean TRUE: resets AR values; FALSE: leave AR vaules alone
* #return string
*/
public function get_compiled_select($table = '', $reset = TRUE)
{
if ($table != '')
{
$this->_track_aliases($table);
$this->from($table);
}
$select = $this->_compile_select();
if ($reset === TRUE)
{
$this->_reset_select();
}
return $select;
}

Resources