Disabling dynamicReload/developmentModeWatch in Grails4/5 for DEV Environemnt - grails

I would like to disable the dynamic reload mechanism in Grails4/5.
In my case it's not effective enough so I rather avoid all the "File {} changed, recompiling..." messages
I'm very well aware of suggestions like this
to put grails.agent.enabled = false in build.gradle
but this seems not to work.
I found in the source code this if condition:
if(environment.isReloadEnabled()) {
log.debug("Reloading status: {}", environment.isReloadEnabled())
enableDevelopmentModeWatch(environment, applicationContext)
environment.isDevtoolsRestart()
}
with getting the value here:
public boolean isReloadEnabled() {
final boolean reloadOverride = Boolean.getBoolean(RELOAD_ENABLED);
getReloadLocation();
final boolean reloadLocationSpecified = hasLocation(reloadLocation);
return this == DEVELOPMENT && reloadLocationSpecified ||
reloadOverride && reloadLocationSpecified;
}
but this pretty much always evaluates to true.
The reloadLocation will always be something where reloadOverride will be always null

You can remove org.springframework.boot:spring-boot-devtools from your dependencies.

Related

Unnecessary null check in mapstruct

I'm using mapstruct in my project, and recently went to add some 'mutation analysis' using pitest.
The problem I have is that a mutant is created on some generated code, and I cannot fix my test to kill it since this is concerning null check generated by mapstruct, that are unreacheable.
ie, if I have the following mapper :
#Mapper
public abstract class MyMapper {
#Mapping(source= "someInnerObject.field", target="someField")
public abstract Bar toBar(Foo foo);
}
Mapstruck will generate something like this :
public class MyMapperImpl extends MyMapper {
#Override
public Bar toBar(Foo foo) {
if(foo == null) {
return null; // reacheable code, all is fine here.
}
Bar bar = new Bar();
bar.setSomeField(fooSomeField(foo))
return bar;
}
private String fooSomeField(Foo foo) {
if (foo == null) {
return null; // Unreacheable code, already tested in public method.
}
SomeInnerObject innerObject = foo.getSomeInnerObject()
if(innerObject == null) {
return null; // reacheable code, no problem here
}
String field = o.getField();
if(field == null) {
return null; // reacheable, no problem here.
}
return field;
}
}
As we can see, mapstruct generates a null check that is unreacheable, making it impossible to cover those line in test. The mutation analyser tries to return "" instead of null on the unreacheable line, and therefore, the mutant is never detected by my tests. This leads makes it impossible to get 100% code coverage and 100% mutation coverage.
I don't think excluding this generated code from the coverage or the mutation analysis would be a good choice, since the generated code reflect behavior that is coded as annotations in the mapper : So we would like to make sure these behaviors are correctly covered in tests.
Do someone here had the same problem, or any suggestion ?
I tried many different mapper config to get rid of the unreacheable line without success (unless I just disable all null checks, which would change my application logic).
The way MapStruct generates code doesn't allow us to skip the null check in the private method.
You can try raising an issue in the MapStruct project. However, I am not sure that it is worth spending time on skipping this null check. The JIT will in any case remove that check during runtime.
The topic about 100% code coverage and 100% mutation coverage is a topic for discussion that will lead to closing this question.

HttpContext.Current.Session keep return Object reference not set to an instance of an object on my class (MVC 5)

I have class to keep PowerShell session. So that I can access the powershell session without to create a new session . Below is my snippet code
public class PowerShellSession : IHttpHandler, IRequiresSessionState
{
public bool IsReusable
{
get
{
return false;
}
}
public void ProcessRequest(HttpContext context)
{
throw new NotImplementedException();
}
public PowerShell PowerShell2010()
{
if(HttpContext.Current.Session == null)
{
WSManConnectionInfoSession connExch = new WSManConnectionInfoSession();
var session = connExch.GetExchangeConnectionSession(2010);
Runspace runspace = RunspaceFactory.CreateRunspace(session);
runspace.Open();
PowerShell Shell = PowerShell.Create();
Shell.Runspace = runspace;
HttpContext.Current.Session["PowerShell2010"] = Shell;
return Shell;
}
if (HttpContext.Current.Session["PowerShell2010"] != null)
{
WSManConnectionInfoSession connExch = new WSManConnectionInfoSession();
var session = connExch.GetExchangeConnectionSession(2010);
Runspace runspace = RunspaceFactory.CreateRunspace(session);
runspace.Open();
PowerShell Shell = PowerShell.Create();
Shell.Runspace = runspace;
HttpContext.Current.Session["PowerShell2010"] = Shell;
return Shell;
}
else
{
return (PowerShell)HttpContext.Current.Session["PowerShell2010"];
}
}
}
The problem is my code always return "Object Reference not set to an instance of an object" when I try to set value to session.
Here the code to set value on session
HttpContext.Current.Session["PowerShell2010"] = Shell;
Did I do something wrong?
I have no experience using Powershell. Having said that, a big part of the problem seems to be that your if() statements are incorrect.
First you check if(HttpContext.Current.Session == null) which is TRUE if the Session object can not be found in the current context. But then you proceed by attempting to use that Session object anyway, so no wonder you get the error that you are getting.
The next one seems wrong too: if (HttpContext.Current.Session["PowerShell2010"] != null), which would be TRUE if a previous attempt to store a Powershell object was successful. But then you proceed to create and store a new Powershell object, which totally defeats the cache that you apparently wanted. You need to replace this with == null, assuming that you will find a way to get to the Session object in the first place.
And last but not least, to have a bigger chance of getting to the HTTP Session object:
make sure that Session state is enabled in your web server and/or Web.Config files;
run as much of the code above in an MVC Controller class, instead of in a Type Library class or something like that. Or pass the HTTP Session object from the MVC Controller Action-method into the Type Library method using a parameter.

Grails getter writing to database?

I am running into some behavior that I did not expect. I have an object that has a status. This object has two states, in progress and closed out. While the object is in-progress I want the status to be calculated and not saved in the database... However, once I close it out/finalize it the status needs to be saved.
The following is the way I tried to set things up:
class Assessment{
AssessmentStatus status
List<Score> scores
static hasMany = [scores: Score]
AssessmentStatus getStatus() {
if(status){
return status
}
if (!scores || event.eventDateTime.after(new Date())) {
return AssessmentStatus.PRE_EVENT
}
scores.each{
if (it.incompleteReason){
return AssessmentStatus.INCOMPLETE
}
}
if (!getPassing()) {
return AssessmentStatus.FAIL
}
return AssessmentStatus.PASS
}
Boolean getPassing() {
def passing = Boolean.TRUE
this.scores.each {score ->
if (!score.passingScore){
passing = Boolean.FALSE
}
}
return passing
}
}
As you can see with the code I was expecting to check to see I was expecting to check if status was null. If status is not null then return it. If it is null then do some other calculation. But... For some reason or another the calculated status is getting persisted to the database. Now I know I could always go in and add:
if(finalized){
return status
}
VS the if(status) and I would get the proper return. BUT... I don't want junk data in the database. Another way to do it would be to not override the getter...
My question basically boils down to. Why is overriding the getter writing to the database and is there a way around it.
All fields are persisted to the database unless you explicitly define otherwise. The fact you are overriding a getter doesn't automatically tell Grails that you do not want to persist that property to the database. To do that you must define the property as transient:
static transients = ['status']
Check out the section "Now you're saving when I don't want you to?!" Here:
http://spring.io/blog/2010/06/23/gorm-gotchas-part-1/

Use MiniProfiler only for debugging or local request

I would like to use the MiniProfiler for my MVC3 application, so I followed Scott Hanselman's blog post
My Global.asax.cs file has the necessary changes like in the source's MVC sample.
But I would like to measure a particular call in my controller.
So I put this code in controller:
if (Request.IsLocal)
{
var profiler = MiniProfiler.Current;
using (profiler.Step("SelectUserDetail Function"))
{
user = UserService.SelectUserDetail(userId);
}
}
I suspect my code will never in production environment as I'm wrapping this block in a Request.IsLocal check.
How can I do this check for only for local call or if I run in debug mode? At any case, it should execute the user = UserService.SelectUserDetail(userId) statement.
If I understand your question correctly, you're only wanting to call MiniProfiler's .Step() extension method when running locally (or debugging), correct?
If so, this kinda defeats the purpose of MiniProfiler, which is to have all this instrumentation available for production code, without impacting production.
I'm confident you can simply do this in your code:
using (MiniProfiler.Current.Step("SelectUserDetail Function"))
{
user = UserService.SelectUserDetail(userId);
}
and it will have virtually no impact on your app; we literally do this hundreds of times in our code here on Stack Overflow without issue (as well as every single database query).
You should only need to have your checks when a new request comes in:
protected void Application_BeginRequest()
{
if (Request.IsLocal) { MiniProfiler.Start(); }
}
When you're running in production, any calls to MiniProfiler.Current.Step() will return nothing, since the profiler is null (the beauty of extension methods).
If you still want to prevent any using statements from appearing in your production code, you should familiarize yourself with preprocessor directives. See this question, as well. However, I would strongly advise against them for this purpose, as it isn't necessary.
I usually create something like DebugHelper static class and define there:
public static class DebugHelper
{
private static bool? _isDebugEnabled = false;
public static bool IsDebug
{
get
{
if (!_isDebugEnabled.HasValue)
{
_isDebugEnabled = false;
#if DEBUG
_isDebugEnabled = true;
#endif
}
//may be extra rules like check for some debug key in HttpContext.Current etc.
return _isDebugEnabled.Value;
}
set { _isDebugEnabled = value; }
}
public static bool IsDevEnvironment
{
get
{
string environment = settingsService.GetSettingByKey<string>("environment");
return environment == "dev";
}
}
public static bool IsTestEnvironment
{
get
{
string environment = settingsService.GetSettingByKey<string>("environment");
return environment == "test";
}
}
DebuHelper allows me easily switch on/switch off debug mode, logging, tracing etc. add extra output or whatever for dev and test environment

Grails Custom Validation - Query inside validation check - What happens while updating?

I have a custom validator like -
validator: { userEmail, userAccount ->
if (userAccount.authenticationChannel == "ABC") {
boolean valid = true;
UserAccount.withNewSession {
if (UserAccount.findByEmail(userEmail)){
valid = false;
}
else if (UserAccount.findByName(userEmail)) {
valid = false;
}
...
So basically, I need some validation based on some condition and in my validation I need to execute a query.
But, now if I do -
def admin = new UserAccount(firstname:'Admin',email:'admin#example.com')
admin.save(flush:true)
admin.addToAuthorities("ADMIN").save(flush:true)
It fails.
Grails is running the validation, even on update and since email exists validation fails. How is this different if I do
email {unique:true}
Is Grails saying that I cannot write a custom validator which checks uniqueness.
Not sure if this is your issue or not, but when I tried to create a validation like this (ie. one that does queries against the database), I would get a StackOverflowError. The reason is that, when you run a query (like findByEmail), Hibernate will try to flush the session, which will cause it to validate all transient objects, which in turn calls your custom validator again, resulting in infinite recursion.
The trick to prevent this is to set the flush mode of the session to "manual" for a short time while running the queries. This prevents Hibernate from trying to flush the session before running the queries. The side-effect is that your query won't return entities you created in the current session but haven't been persisted (flushed) back to the database yet.
UserAccount.withNewSession { session ->
session.flushMode = FlushMode.MANUAL
try {
if (UserAccount.findByEmail(userEmail)){
valid = false;
}
else if (UserAccount.findByName(userEmail)) {
valid = false;
}
}
finally {
session.setFlushMode(FlushMode.AUTO);
}
}
See UniqueConstraint for an example of how this is done.
An alternative might be to do the checks in the save method.
def save = {
..
if (some_checks_succeed(userEmail, userAccount)) {
admin.save(flush: true)
}
..
}
def some_checks_succeed = { String userEmail, String userAccount ->
boolean valid = true;
if (userAccount.authenticationChannel == "ABC") {
UserAccount.withNewSession {
if (UserAccount.findByEmail(userEmail)) {
valid = false;
} else if (UserAccount.findByName(userEmail)) {
valid = false;
}
..
}
return valid
}
Some modifications might be necessary, but the above code gives you an example
Thanks. I could get this to work.The admin.save() calls validation both on insert and update. I handled both the cases (insert and update) and was able to get this working.
Thanks

Resources