While this is a nice addition our tests which were not using Geb were left broken this is due to the fact we now need to know what port was selected for a given run of the tests. So our old test:
Was broken since the app no longer started on 8080, but we can fix that with a new property that the @Integration
annotation adds which is serverPort
so the test becomes:
If you are wondering how serverPort
is actually set you can see it happening inside IntegrationTestMixinTransformation. It will add a property to the test class with the port.
/metrics
endpoint turned on meaning every request gets tracked by default the endpoint will be available to all logged in users assuming you are using some security.
Most of the time this wouldn’t be an issue and would be very nice to have those metrics the problem comes to the fact that currently all requests with Path Variables are treated as different endpoints. So requests to /items/$id
of /items/123
and /items/333
will end up listed as two different metrics with the value of the path variable for everyone to see. This exposes more data than intended and doesn’t provide really useful metrics. Its due to an issue in Actuator GH Issue 5875. So until this is fixed I recommend turning off metrics collection all together for Grails 3.
You can do that with the following config in your application.yml
I just keep the metrics endpoint off since the health-checks are useful and something we depend on others may want to just shut of Actuator fully which can be done with:
Thanks to Ryan Vanderwerf for help on this issue.
]]>ratpack.dependency("rx")
) with RxJava such as a functional test you will start seeing the following error in the standard out:
Many of your functional tests will start failing with very unpredictable results. What is happening is any use of RxJava that runs before the Ratpacks integration will set up an execution hook meaning the strong guarantees about execution Ratpack provides will not be available leading to unpredictable behavior. This is an easy fix for the test, we just need Ratpack to setup the hook in these other tests we can simply add the following to a Spock spec:
The same initialize can be used in your favorite testing tools, it just needs to happen before the tests are run once and thats what setupSpec
gives us in Spock.
build/report/jacoco
directory.
But Grails 3 has it’s test phases split up, out of the box you will have test
and integrationTest
. Starting with the JaCoCo gradle plugin, you will get coverage for just your test
phase.
We can easily fix this by letting JaCoCo know about the phases we want reported on so we just adjust the config for the jacocoTestReport task.
]]>With Gradle the samples given all are based on the use of the great Shadow Plugin. While this is good for deployments and most local development I missed a few of the features of the application plugin.
Set up your build.gradle
with the following:
In this case we are deploying Vertx with verticles. So we set the main verticle which does our setup. I define that as variable since we will need to use it in two places once as an argument to the Vertx starter and again in the Jar manifest. You will note the main verticle includes the type in our case it is Groovy but if you are doing JavaScript you would change it there.
Now we can take advantage of the application plugin allowing us to use the simple gradle run
instead of depending on the Shadow plugin it is also faster then rebuilding the whole fat jar.
But the main reason I wanted to use the application plugin was the ability to debug easily.
That command will allow us to attach a debugger to 5005 default. With these changes Vertx 3 development fits in along side my other Grails 3 and Java 8 projects easily.
]]>While working with Grails 3 there are a few areas that don’t have plugins yet but do have Spring modules we can leverage. So I started out with the same path given for Grails 2.X.
I found that while the beans were all wired correctly and @Autowired
all worked correctly, but any mappings with @RequestMapping
where always returning a 404. Everything looked wired correctly but Grails wasn’t letting any requests through.
So I switched over to using @ComponentScan
then the requests were properly mapped and everything started working.
Using ComponentScan with Grails 3 is very easy:
This will scan the package of example.config
for any Spring components so your Spring Java configs can all live in this package and easily get picked up.
This post is the blog form of this SO Question.
]]>By default even impersonation or user switching is turned off in the plugin by default. You can easily turn it on with a config flag:
Spring Security by default will add a new role of ROLE_PREVIOUS_ADMINISTRATOR for the user while impersonating the other user. This will work in most cases but for us it was hard to reason about since we had an idea of admin which was separate from our support team who would mostly be using this tool.
So for our use we wanted our own roles. The ability to do this is exposed in the SwitchUserFilter calling SwitchUserAuthorityChanger. With an implementation of the interface you can add any roles you would like.
Example authority changer:
In Grails we set our authority changer during bootstrap.
The switch user filter is already exposed as a bean so we can just get that injected and we also exposed the authority changer as a bean so we could just inject it in bootstrap.
There are many other options to think about when allowing impersonation of users, it may even make sense to remove some roles from an impersonated user. That is easily done by simply removing roles from the list retuned from the authority changer.
]]>If you see large or multiple directories under columnFamily/snapshots/ that may indicate there are stale snapshots that can be cleaned up. We will want to check when these snapshots where created so inside the snapshots directory of the column family run
Each of those are snapshots but you will notice 4f37dcd0-c7fa-11e4-b5ae-5f969a9b23c8 is stale, we can now clean that up with the nodetool clearsnapshot command.
That will take care of removing the stale snapshot you should see disk space recovered immediately.
You can also look in the logs for failed repairs we see something like the following:
In that case the bad snapshot would be 72e69720-b959-11e4-9b55-39152d07d3bf.
]]>The simple solution is to simply turn off transactions for integration tests, that solution will work but tends to lead to data pollution in downstream tests. Burt Beckwith has a solution in his post An Alternative Approach for Grails Integration Tests. Using this solution we can rebuild the database for each test.
In general most of the time you can use the default transactional testing behavior, therefore we want to only use this method some of the time. To achieve this effect we will modify Burt’s original solution slightly.
You’ll notice we extend a company.IntegrationSpec there isn’t anything special in that just a base integration spec class that can hold our shared testing code such as bootstrapping methods and security methods. Since our data bootstrap logic is set up there we can share the same initial setup across both our normal integration test and our new non-transactional integration specs.
The main time we started to need this new testing method was when doing custom propagation of hibernate transactions.
Since this will require a new transaction we will not be able to see the inserts that have happened in the default transaction. We do many of our reads as read only and force a new transaction when we are more read heavy during an operation.
In general anytime you are working directly with transaction rollbacks or propagation it best to test those things directly without having Grails inject an extra transaction in there for you.
]]>We found an issue while running both of these in production. Over time the number of sessions reported by App Info would grow extremely large. It turns out that having the App Info plugin track sessions for you when the sessions are shared via memcached can lead to the plugin holding onto references to sessions that have been destroyed on other severs.
So at this time we can’t use the App Info plugin session tracking with the Memcached Session Manager, since it leads to a memory leak as all those sessions have references inside the plugin and can never be garbage collected.
We can simply turn off the session tracking with the following code:
But note this config change effect will effect how a war is made so you can’t simply override this in production you will need a new war built.
Below is our memory graph before and after the change:
]]>Ratpack Promises are very easy to work with, there are just a few key points:
What we are doing here is giving a closure to the promise that once the value is ready the closure will be called with the value passed in as a parameter. We can also be very explicit in what we are getting back from the promise.
If some error occurs while trying to get the value for the then
block the exception will be thrown. Which can be picked up by some error handler down the chain.
So for this works great when dealing with the happy path and wanting exceptions. But we also may want to deal with failures to fulfill the promise. So to do this we start with onError
instead of then
.
onError
will pass in a throwable to the closure that you can log or do whatever work you would like in the case of a failure.
Ratpack promises won’t actually try to generate the value until the then
block is called at the end of the current execution. This is done to allow for deterministic asynchronous operations.
What will happen in Ratpack is we will always get the exception “bang!”, because the get request will not even get started until the doWork
block of execution is finished. Once finished having a then{}
will trigger a background thread to start generating the value.
You shouldn’t try to attach more than once to a Promise, as what ends up happening is two different promise instances will execute in the background and what we want is only to deal with that value once. So don’t do the following:
Starting in Ratpack 0.9.9 the above code should actually throw an error.
]]>Above you can see how we model our “upsert”. If a value isn’t found for the given where clause it will insert it.
You must use all parts of a Primary Key for an updates where cluase given a CQL Table with a compound key:
We can not do the following query:
You will get an InvalidQueryException
:
But the following will upsert:
]]>This issues may have nothing to do with the actual dependency but an issue in your local m2 cache. The quick answer is to just delete ~/.groovy/grapes
and ~/.m2/repository
. But doing this will force you to re-download dependencies.
To only delete the cache for items giving you an issue you just need to delete the correct directories in both m2 and grapes cache. So for our Guava example you would do the following:
After that you should be able to run the groovy script normally.
]]>This is easily fixed by adding New Relic annotations to services and libraries.
At this point your code is ready to give more detailed transactions, but the agent on the server must also be configured to accept custom tracing. The config option for this is not available from the web so you must update the newrelic.yml
file. Set enable_custom_tracing
to true
.
Now you will get any custom tracing added to your application as well as custom tracing from libraries.
]]>Start using package in between and the problem will go away.
]]>The difference in my case was the need to use the Grails service, I went with providing the service in the resources.groovy file. Below is the example file of what I used.
My resources.groovy
Snip from CustomUserDetailsService.groovy
]]>We are using the Grails Spring Security SAML Plugin on a Tomcat server. In my case this was happening because we were doing SSL offloading on the load balancer. So if you look at the logs there should be an error log with the intended destination and the recipient endpoint.
In my case the first error was only different by http vs https. The fix for that was simply to apply the scheme attribute to that connector in tomcat. At which point everything was matching except that the port was now being added as 80 in my endpoint and that wasn’t in the intended endpoint. The fix for this was just to add the proxyPort to the connector as well.
So to fully support the OpenSAML on tomcat with SSL offloading I configured the connector as seen below. Take note of the scheme and proxyPort being set.
]]>Also if you want to poke around the other beans available this is a great post to check out: Spring Beans from the Grails Console .
]]>I was able to quickly fix the error by removing my data directory and starting fresh as this is just my development environment that works great for me. You can find your data directory in the cassandra.yaml file ($DSE_HOME/resources/cassandra/conf/cassandra.yaml), look for the data_file_directories entry. Mine was set to /var/lib/cassandra/data so I just ran the following and started cassandra fresh and everything is back to working order.
]]>