Assert vs If in Controller - java

What is the best way to check for a value that was passed in the controller?
Is it assert or if?
if this is the sample url....
http://example.com/read/1/2
I would like to check if 1 and 2 is number and if it's null. Like if the user changed the url to http://example.com/read/1asdf/2asdfqwer
We are using assert in our company. And I'm just thinking that what will happen if it's already in production mode and assert is disabled.
Somebody give me an insight with this.

assert is intended as a debugging tool for checking conditions under you control. If it fires, it indicates a bug in your code. Checking user supplied input does not fall into this category, instead it is a feature of correct programs. Thus you should use if statements for checking user input.

Asserts are mainly used to check preconditions.
Its like if given preconditions are not mate throw AssertionError.
Checking preconditions this way is actually good practice in testing environments. Where we can make sure all preconditions are mate and satisfied.
In production environment if debug mode is not yet activated then it will surely will not harm. this statement will work as if it is commented.
In your case if you merely want to check which value is accepted at controller level use if's.
but If you want to check that as precondition and then you want throw error if these preconditions are not met and ideally in debug mode. (AssertionError.) then you can use asserts.

Instead of using assert use following logic.
#RequestMapping(value = " /read/{var1}/{var2}", method=RequestMethod.GET)
public String read(#PathVariable Integer var1,#PathVariable Integer var2){
if (var1 ==null || var2 == null) {
// do something
}
return "something";
}
I assumed you are using spring mvc.

Related

Should you assert not null with the assert statement in production code? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I've seen this question but have a few more questions about the usage of the assert keyword. I was debating with a few other coders about using assert. For this use case, there was a method that can return null if certain prerequisites are met. The code I wrote calls the method, then asserts it doesn't return null, and continues to use the returned object.
Example:
class CustomObject {
private Object object;
#Nullable
public Object getObject() {
return (object == null) ? generateObject() : object;
}
}
Now imagine I use it like this:
public void useObject(CustomObject customObject) {
object = customObject.getObject();
assert object != null;
// Do stuff using object, which would throw a NPE if object is null.
}
I was told I should remove the assert, that they should never be used in production code, only be used in testing. Is that true?
Use Objects.requireNonNull(Object) for that.
Checks that the specified object reference is not null. This method is designed primarily for doing parameter validation in methods and constructors, [...]
In your case that would be:
public void useObject(CustomObject customObject) {
object = customObject.getObject();
Objects.requireNonNull(object); // throws NPE if object is null
// do stuff with object
}
This function is made for what you want to do: explicitly mark what is not to be null. The benefit is that you find null-values right where they should not occur. You will have less troubles debugging problems caused by nulls that are passed somewhere where they shouldn't be.
Another benefit is the flexibility when using this function in contrast to assert. While assert is a keyword for checking a boolean value, Objects.requireNonNull(Object) is a function and can be embedded in code much easier.
Foo foo = Objects.requireNonNull(service.fetchFoo());
// you cannot write it in one line.
Bar bar = service.fetchBar();
assert bar != null;
service.foo(Objects.requireNonNull(service.getBar()));
// you cannot write it in one line.
Bar bar = service.getBar();
assert bar != null;
service.foo(bar);
Keep in mind that Objects.requireNonNull(Object) is only for null-checking while assert is for general assertions. So assert has different purposes: primarily testing. It has to be enabled, so you can enable it for testing and disable it in production. Use it to seperate testing-only-tests from tests, or rather checks, that are meant for production-code too.
The most important thing to remember about assertions is that they can be disabled, so never assume they'll be executed.
For backward compatibility, the JVM disables assertion validation by default. They must be explicitly enabled using either the -enableassertions command line argument, or its shorthand -ea:
java -ea com.whatever.assertion.Assertion
So, it's not a good practice to rely on them.
As assertions aren't enabled by default you can never assume they will be executed when used in the code. So you should always check for null values and empty Optionals, avoid using assertions to check inputs into a public method and instead use an unchecked exception... In general do all the checks as if the assertion wasn't there.
Surely what you are told is a blatant lie. Here's why.
Assertions are disabled by default if you just execute standalone jvm. When they are disabled, they have zero footprint, hence they will not affect your production application. However, they are probably your best friends when developing and testing your code, and most of testing framework runners enable assertions (JUnit does), so your assertion code is executed when you run your unit tests, helping you detect any potential bugs earlier (e.g. you can add asserts for some business logic boundary checks, and that will help detect some code which uses inappropriate values).
That said, as the other answer suggests, for exactly that reason (they are not always enabled) you cannot rely on assertions to do some vital checks, or (especially!) maintain any state.
For an interesting example of how you could use asserts, have a look here - at the end of the file there's a method singleThreadedAccess() which is called from the assert statement on line 201 and is there to catch any potential multithreaded access in tests.
The other answers already cover this well enough, but there are other options.
For example, Spring has a static method:
org.springframework.util.Assert.notNull(obj)
There are other libraries with their own Assert.something() methods as well. It's also pretty simple to write your own.
However, keep in mind what exceptions you throw if this is a web service. The previous method mentioned, for example, throws an IllegalArgumentException which by default in Spring returns a 500.
In the case of a web service, this is often not an internal server error, and should not be a 500, but rather a 400, which is a bad request.
Use asserts liberally whenever doing so helps catching programming mistakes i.e. bugs.
Do not use assert to catch something that might logically happen i.e. badly formatted input. Use assert only when the error is unrecoverable.
Do not put any production logic in the code that runs when the assertion is checked. If your software is well written this is trivially true but if it's not then you might have subtle side effects and different overall behavior with assertions enabled and disabled.
If your company has "testing code" and "production code" doing the same thing but as different code bases (or different stages of editing), get out of there and never come back. Trying to fix that level of incompetence is probably a waste of your time.
If your company doesn't put any assert statement outside of the code of the tests, kindly tell them that asserts are disabled in the production build and that if they aren't, fixing that mistake is now your first priority.
The value of asserts is precisely to be used inside the business logic and not only the test suite.
This makes it easy to churn out many high level tests that don't have to explicitly test many things to go through big chunks of your code and trigger all these assertions.
In a few of my projects typical tests didn't even really assert anything, they just ordered a calculation to happen based on specific input and this caused hundreds of assertions to be checked and problems to be found even in tiny pieces of logic deep down.
You can use assert any time. The debate come is when to use. For example in the guide :
Do not use assertions for argument checking in public methods.
Do not use assertions to do any work that your application requires for correct operation.

Is this an overuse of Java asserts? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to get to grips with the use of the assert keyword in Java. As I understand it, the correct case is for verifying things that should always be true.
I'm worried that I'm overusing asserts, however.
Here's a sample:
private BodyParams() {
assert revokedDoc != null : "revokedDoc must not be null";
assert revokedDoc.getStatus() == DocumentStatus.Revoked : "document is not revoked";
assert !isBlank(revokedDoc.getDocType()) : "docType should not be blank";
assert revokedDoc.getIssuedDate() != null : "doc should have issue date";
assert revokedDoc.getSendingOrg() != null
&& !isBlank(revokedDoc.getSendingOrg().getName())
: "sending ord should exists and name should ne populated";
if (registeredUser) {
assert revokedDoc.getOwner() != null
&& !isBlank(revokedDoc.getOwner().getFirstName())
: "owner should exists and first name should be populated";
this.ownerFirstName = revokedDoc.getOwner().getFirstName();
this.docUrl = Application.PUBLIC_HOSTNAME
+ controllers.routes.DocumentActions.viewDocument(
revokedDoc.getId()
).url();
} else {
this.ownerFirstName = null;
this.docUrl = null;
}
if (revokedDoc.getStatus() == DocumentStatus.Available) {
assert !isBlank(revokedDoc.getFriendlyName())
: "friendly name should not be blank for picked-up docs";
this.friendlyName = revokedDoc.getFriendlyName();
} else {
this.friendlyName = null;
}
this.docType = revokedDoc.getDocType();
this.issueDate = revokedDoc.getIssuedDate();
this.issuerName = revokedDoc.getSendingOrg().getName();
}
In this example, it is assumed that the revokedDoc field came from the database, and correct validation was performed when it was inserted. These asserts test that assumption. Is this overkill?
edit: I should mention that this is only for development code. Assertions will not be enabled in production. I'm using the assertions to ensure that data that will be known good data from a trusted source in production behaves itself in development
It does not look right. To simplify there are two broad categories of problems that can arise and require checking the validity of a variable:
Your method receives or uses an argument that could possibly not be what you expect and your method should have appropriate argument checking and throw an IllegalArgumentException or NullPointerException or whatever if required. Example: the client code has passed in a null argument and you have no control over that code
Your method uses some of the class internals and you should have appropriate unit tests to make sure that those internals are always consistent and that your methods can use them without additional checks.
In your case, the method that creates the revokeDoc object should make sure it is in a valid state after creation and take appropriate action otherwise, for example throw an exception and roll back any changes. That way your BodyParams method can just use the object without all those asserts which clutter your code at the wrong time: if revokeDoc is not consistent it is probably too late to do something about it and should have been detected earlier.
Related post: Exception Vs Assertion
Assert is really useful to perform that should always be true inside an library or a module. It is intented to verify invariants ( control flow, internal, etc.) in your code, and it is a bad idea to use it to enforce correct use of your code (you have exceptions for that).
As a consequence, your public interface should never be based on assert : when you have a public method and you want to check input parameter, it is generally better to throw an IllegalArgumentException.
Here are some good documentation about asserts.
In your example, I think you should use exceptions instead of asserts. It's not a bad idea to perform some validity checks on data coming from a database (even if it has been validated on input) but assertion might be disabled in production code and you have to think on how you should handle such malformed content.
This could be an opinionated question. However, I'd go with the following things to decide:
Is this method exposed to outside world (via an interface, JAR file, user input field or anywhere where you could get inputs from a source that is not in your control) - then I should have a valid actual check which would result in an exception.
Am i relying on assertion for my correct execution of the code? If so, I shouldn't. At runtime, assertions are meant to be disabled.
Is this assertion always true? and if yes, am I going to use it on the off case for just debugging - then yes, use an assertion in place of a code comment. When something goes bad, enable the assertions and figure out what's wrong.
You need to consider two scenarios: development code and production code.
Since Java's assert statement is disabled by default (and adds only little overhead by checking a global static flag which is enabled by passing -ea to the VM), I would not consider this overhead since it helps you detect issues early during your development phase (assumed that you have enabled assertions in your development environment).
On the other hand, you say "... Correct validation was performed when it was inserted ..." - so, how do you know that the value has not been changed in the database meanwhile? If security matters for your system (I am just assuming it does), one basic pattern is that you must not trust anything which you get from the outside. Means, validate values you read from the database - but, in that case, assert is not the proper tool. Use normal validation code and exceptions for that.
The best practice, acording to OO metology is to check the params you receive. And create regulars checks for others. Should in your case you should get something like this:
private BodyParams(revokedDoc)
[...]
asserts of the params
if(isBlank(revokedDoc.....)
All the assets looks good, and is the way to make sure the method has everything to work. But they should be to make an aide of what's going on wrong, not to make your program work.

Am I using Java assertions right?

public Card getCard()throws IOException{
Card c = null;
String cardInfo = null;
assert readStream != null: cardInfo = readStream.readLine();
assert cardInfo != null: c = CreateCard(cardInfo);
return c;
}
I'm a little outta practice and I am trying to improve my code quality by using the assert statement to test for nulls. The way it seems to work I end up having to daisy chain my assertions because if the first thing I test for is null, then the next one is gonna be a null as well....
Here are some guidelines with regards to assertions
Don't use assertions to validate parameters of public functions.
These functions should throw NullPointerException,
IllegalArgumentException, and other relevant exceptions instead.
Since public functions will be used by other programmers, you should
make sure that they get the right errors if they mess up.
Use assertions to check preconditions and postconditions on
parameters of protected and private access methods.
Don't use assertions to check for software user errors. If you expect
the user of your web-based online sales system to enter a 10-digit
credit card number and she enters only 9 digits, don't use an assert.
Instead, throw IllegalArgumentException. If you use assert, as soon
as someone turns off assertions on your servlet container, the
checking logic in your system would go away.
Use assertions to check parameters and variables for conditions that
shouldn't happen
Use assertions to check for invalid code branches
Don't use an assertion to do any work. Assertions are developer-level
errors and shouldn't be used to repair state in the program or
perform complex logging. Also, don't forget that if a user runs the
program without assertions, the code will be gone. If that code was
critical to the functioning of the program, you could be in deep
trouble.
Don't bother internationalizing assertion error messages. Again,
since assertions are developer-level issues, internationalizing them
would be a waste of time.
Use assertions to check post conditions. If you create a method and
expect that it will never to return null to the user
The value of an assertion is that it can be ON in development and OFF in production. While on, it reveals bugs, presumably before they do much damage, prior to a release. While off, the assertions are inactive and (hopefully) sport a negligible performance impact.
I think the question to ask yourself is: "Self, does my usage of assertions meet those criteria?"

Is there a difference in compiled Java with asserts disabled between assert someBoolean(); and verifySomeBoolean(); where latter contains an assert?

I have a postcondition I want to check regularly, across many methods. I'm fairly confident that I'm using the assert correctly, i.e. only checking something to make sure my code isn't doing anything stupid, and I intend to turn off the asserts after a while. But I'm not sure that the postcondition as I've written it now is exactly the condition I'll always want. So I put it into a method. But then I encountered the following issue:
public class Foo
{
public void doSomethingRisky()
{
//...
assert someBoolean();
}
private boolean someBoolean()
{
return bar && baz;
}
}
vs.
public class Foo
{
public void doSomethingRisky()
{
//...
verifySomeBoolean();
}
private void verifySomeBoolean()
{
assert bar && baz;
}
}
I know if I compile w/ disabled assertions, the former code will have no performance hit since someBoolean() will never get called. But is Java "smart" enough that, with assertions disabled, the second form will also have no performance hit with assertions disabled?
And the more important question, obviously, is which is better practice?
I like the assert someBoolean() because it's explicit, not subject to re- or mis-interpretation, but it seems the other form might be a little more future proof, because maybe I'll want to expand the behavior of verifySomeBoolean() to do something besides asserting the same underlying boolean. Though my gut says if that were the case, I'm better off re-coding than trying to smush the old code to fit. Any words from the wise would be much appreciated.
I thought you did not compile out assertions? I thought they were compiled and could only be enabled by the JVM with java -ea.
In that case it would be up to the JVM to optimize out an empty call when -ea is not used. But you are pre-maturely optimizing. Make the code easy to understand and write. Then optimize second. Calling an empty method is not going to cause your performance issues.
Update:
As far as style, I would go with the asserts as close to the problem as possible. I wouldn't like the assert in a method just for the check.
Second, assert() and Guava Preconditions have two different applications. assert should be used to check that your world is still the world you thought it was. It's more of a assert (1+1 == 2) type of thing. You don't use assert()'s on callee parameters. You use assert to check something you know MUST be true, but are checking it anyways.
Guava Preconditions look to be what you should be using. This is input validation and is used to check for contract compliance. Things such as: checking null argument, negative numbers when only natural numbers should be used, a properly formatted string, etc.
In summary, assert() is the "Let me just make sure gravity is still here, even though I know it is" and the Preconditions is "Let me make sure I am trying to travel faster then the police allow"

spirit of a jUnit test

Suppose that you have the following logic in place:
processMissing(masterKey, masterValue, p.getPropertiesData().get(i).getDuplicates());
public StringBuffer processMissing(String keyA, String valueA, Set<String> dupes) {
// do some magic
}
I would like to write a jUnit test for processMissing, testing its behavior in event dupes is null.
Am i doing the right thing here? Should I check how method handles under null, or perhaps test method call to make sure null is never sent?
Generally speaking, what is the approach here? We can't test everything for everything. We also can't handle every possible case.
How should one think when deciding what tests to write?
I was thinking about it as this:
I have a certain expectation with the method
Test should confirm define my expectation and confirm method works under that condition
Is this the right way to think about it?
Thanks and please let me know
First, define whether null is a valid value for the parameter or not.
If it is, then yes, definitely test the behavior of the method with null.
If it is not, then:
Specify that constraint via parameter documentation.
Annotate that constraint on the parameter itself (using an annotation compatible with the tool below).
Use a static analysis tool to verify that null is never passed.
No unit test is required for the invalid value unless you're writing code to check for it.
The static analysis tool FindBugs supports annotations such as #NonNull, with some limited data-flow analysis.
I personally think it would be unnecessarily expensive within large Java codebases to always write and maintain explicit checks for NULL and corresponding, non-local unit tests.
If you want to ensure that people don't call your API with a null argument you may want to consider using annotations to make this explicit, JSR 305 covers this, and its used in Guava. Otherwise you're relying on users reading javadoc.
As for testing, you're spot on in that you can't handle every possible case, assuming you don't want to support null values, I'd say that you may want to throw an IllegalArguemntException rather than a NullPointerException so you can be explicit about what is null, then you can just test for that exception being thrown - see JUnit docs.

Categories

Resources