Micronoaut ServerStartupEvent callback not called in startup? - startup

Just started to experiment with MN M3. Created a minimal Groovy service with the following code:
package test2
import groovy.transform.CompileStatic
import io.micronaut.context.event.ApplicationEventListener
import io.micronaut.runtime.Micronaut
import io.micronaut.runtime.server.event.ServerStartupEvent
#Singleton
#CompileStatic
class Application implements ApplicationEventListener<ServerStartupEvent> {
static void main(String[] args) {
println "Start"
Micronaut.run(Application.class)
}
#Override
void onApplicationEvent(ServerStartupEvent event) {
println "Boo!"
}
}
I get the "Start" but the startup event callback is never called:
Start
10:35:54.066 [main] INFO io.micronaut.runtime.Micronaut - Startup
completed in 897ms. Server Running: http://localhost:32034
I think this is the appropriate way to deal with initialization in MN?

Turns out Groovy has its own #Singleton annotation which was used by default. You need to import:
import javax.inject.Singleton
Might be a good idea to emphasize this somewhere in the docs.

Related

Apache beam Initializer

In my dataflow job, I need to initialize a Config factory and log certain messages in an audit log before actual processing begins.
I have placed the Config factory initialization code + audit logging in a parent class PlatformInitializer and extending that in my Main Pipeline class.
public class CustomJob extends PlatformInitializer implements Serializable {
public static void main(String[] args) throws PropertyVetoException {
CustomJob myCustomjob = new CustomJob();
// Initialize config factories
myCustomjob.initialize();
// trigger dataflow job
myCustomjob.parallelRead(args);
}
as a result, I had to also implement Serializable interface in my Pipeline class because beam was throwing error - java.io.NotSerializableException: org.devoteam.CustomJob
Inside PlatformInitializer, I have an initilize() method that contains initialization logic for config factory and also log some initial audit messages.
public class PlatformInitializer {
public void initialize() {
// Configfactory factory = new Configfactory()
// CustomLogger.log("JOB-BEGIN-EVENT" + Current timestamp )
}
}
My question is - is this right way to invoke some code that needs to be called before pipeline begins execution?
If you need the initialized object at runtime (not at the pipeline construction time), you should move your initialization logic to a Beam DoFn. DoFn has a number of method annotations that could be used to denote methods that should be executed in different lifecycle phases. Setup and StartBundle annotations might be useful for your use-case. See here for more details.

Cannot import package in unit tests for a Jenkins Shared Library

I'm attempting to create unit tests for a JenkinsShared library using Gradle in order to run the test tasks.
I've followed this tutorial which upon conclusion one has a working test suite for a shared library for functions within the vars folder (with the unit tests in src/test/groovy/*Test.groovy).
However, in our internal shared jenkins library we followed a more object oriented style and isolated functionality into a package of classes in the format: src/org/company/*.groovy.
The problem arises when attempting to import said package into a unit test class. In the tutorial, the functions are imported using the loadScript method this method fails when loading a class which is dependent on another file.
Take the class:
package tests
import org.junit.*
import com.lesfurets.jenkins.unit.*
import static groovy.test.GroovyAssert.*
import org.company.UtilFactory
class UtilFactoryTest extends BasePipelineTest {
#Test
void testCall() {
def util = UtilFactory.getUtil("hello")
assertEquals true, true
}
}
src/org/company/UtilFactory.groovy
package org.company
class UtilFactory implements Serializable {
static Util instance
static Util getUtil(script=null) {
if (!(UtilFactory.instance)) {
if (!script) {
// Throws an exception if on the first call to getUtil the
// script parameter is null.
throw new ScriptUndefinedException("script parameter null on initial call to getUtil")
}
UtilFactory.instance = new Util(script)
}
return UtilFactory.instance
}
}
class ScriptUndefinedException extends Exception {
// Parameterless Constructor
public ScriptUndefinedException() {}
// Constructor that accepts a message
public ScriptUndefinedException(String message)
{
super(message);
}
}
Which gives me the exception:
jenkins-utilities/src/test/groovy/UtilFactoryTest.groovy: 7:
unable to resolve class org.company.UtilFactory
# line 7, column 1.
import org.company.UtilFactory
This may be more of a Gradle issue than a JenkinsShared Library. I've just spent a good portion of my day trying to figure out exactly what I'm doing wrong to no avail.
I would really appreciate any help to guide me in the right direction.
This library may be helpful getting your shared libraries to work in the unit test https://github.com/stchar/pipeline-sharedlib-testharness

How to create "Mandatory" spock extension

I am using Spock in combination with Geb for web browser testing.
I have created the "stepThrough" extension by following the instructions found here:
Spock Stepwise - Keep running testsuite after single failure
That works all fine and well, but I would like to make a new annotation. That sets a a geb feature method to "Mandatory" meaning that if this feature method fails I would like to stop execution of the rest of the test.
I like the stepThrough annotation because if one test case fails I can continue with the rest of my testing, but if something like login fails, then I would want to stop the testing because obviously nothing else would work if Login fails.
This is what I have so Far but it does not seem to be working. Where have I gone wrong?
Here is the Annotation class
import org.spockframework.runtime.extension.ExtensionAnnotation
import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#ExtensionAnnotation(ManditoryExtension.class)
#interface Manditory {}
Here is the extension:
class ManditoryExtension extends AbstractAnnotationDrivenExtension<Manditory>{
void visitFeatureAnnotation(Manditory annotation, FeatureInfo feature) {
skipFeaturesAfterFirstFailingFeature(feature)
}
private void skipFeaturesAfterFirstFailingFeature(final FeatureInfo feature){
feature.getParent().getBottomSpec().addListener(new AbstractRunListener() {
void error(ErrorInfo error) {
if (!error.getMethod().equals(feature)) return
for (FeatureInfo feat : feature.getSpec().getFeatures())
feat.setSkipped(true)
}
})
}
}

Context & Dependency Injection : How to inject implementation of an interface?

I am at beginner stage of CDI and trying to inject the implementation of interface using field injection as below:
AutoService.java
package com.interfaces;
public interface AutoService {
void getService();
}
BMWAutoService.java
package com.implementations;
import javax.inject.Named;
import com.interfaces.AutoService;
#Named("bmwAutoService")
public class BMWAutoService implements AutoService {
public BMWAutoService() {
// TODO Auto-generated constructor stub
}
#Override
public void getService() {
System.out.println("You chose BMW auto service");
}
}
AutoServiceCaller.java
package com.interfaces;
public interface AutoServiceCaller {
void callAutoService();
}
AutoServiceCallerImp.java
package com.implementations;
import javax.inject.Inject;
import javax.inject.Named;
import com.interfaces.AutoService;
import com.interfaces.AutoServiceCaller;
public class AutoServiceCallerImp implements AutoServiceCaller {
#Inject
#Named("bmwAutoService")
private AutoService bmwAutoService;
public AutoServiceCallerImp() {
}
#Override
public void callAutoService() {
bmwAutoService.getService();
}
}
TestDisplayMessage.java
package com.tests;
import com.implementations.AutoServiceCallerImp;
import com.interfaces.AutoServiceCaller;
public class TestDisplayMessage {
public TestDisplayMessage() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
AutoServiceCaller caller = new AutoServiceCallerImp();
caller.callAutoService();
}
}
When I run TestDisplayMessage.java , the expected result would be "You chose BMW auto service" but I get NullPointerException as below :
Exception in thread "main" java.lang.NullPointerException
at com.implementations.AutoServiceCallerImp.callAutoService(AutoServiceCallerImp.java:21)
at com.tests.TestDisplayMessage.main(TestDisplayMessage.java:16)
Couldn't figure out exactly what I am missing here. Please help.Thanks in advance.
Ok, it seems you misunderstood the concept of CDI a bit - the idea is that you leave the bean lifecycle to CDI container. That means CDI will create a dispose beans for you. In other words, you are not supposed to create beans by calling new. If you do that, CDI does not know about it and will not inject anything into it.
If you are in SE environment, which I think you are since you use main method to test, you want to use Weld (CDI implementation) SE artifact (I guess you do that).
There, you will need to start the CDI container. Note that if you were developing a classical EE application on a server, you don't do this, because the server will handle it for you. Now, the very basic way to boot Weld SE container is:
Weld weld = new Weld();
try (WeldContainer container = weld.initialize()) {
// inside this try-with-resources block you have CDI container booted
//now, ask it to give you an instance of AutoServiceCallerImpl
AutoServiceCallerImpl as = container.select(AutoService.class).get();
as.callAutoService();
}
Now, second issue with your code. The usage of #Named is intended for EL resolution. E.g. in JFS pages, so you can access the bean directly. What you probably want is to differentiate between several AutoService implementations and choose a given one. For that CDI has qualifiers. Check this documentation section for more information on how to use them.

Override property in application.groovy with external config in grails 3

There is no grails.config.locations property in grails 3 anymore, now Grails 3 uses Spring's property source concept instead, but how can I achieve the same behavior in grails 3 as it was in previous versions? Suppose I want to override some property property.to.be.overridden in application.grovy file with my external configuration file. How can I do it?
The equivalent of grails.config.locations is spring.config.location
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-application-property-files
Here is an example specifying configuration locations while launching a jar from the command line(These same arguments can be used inside of your ide)
java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
Also since you mention wanting to override properties it's useful to learn the way Spring Boot handles profile specific property files(Multiple profiles may also be specified)
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-profile-specific-properties
I solved this a slightly different way, so I could load an external YAML file.
Application.groovy
package com.mycompany.myapp
import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean
import org.springframework.context.EnvironmentAware
import org.springframework.core.env.Environment
import org.springframework.core.env.PropertiesPropertySource
import org.springframework.core.io.FileSystemResource
import org.springframework.core.io.Resource;
class Application extends GrailsAutoConfiguration implements EnvironmentAware {
static void main(String[] args) {
GrailsApp.run(Application)
}
#Override
void setEnvironment(Environment environment) {
String configPath = System.properties["myapp.config.location"]
if (configPath) {
Resource resourceConfig = new FileSystemResource(configPath);
YamlPropertiesFactoryBean propertyFactoryBean = new YamlPropertiesFactoryBean();
propertyFactoryBean.setResources(resourceConfig);
propertyFactoryBean.afterPropertiesSet();
Properties properties = propertyFactoryBean.getObject();
environment.propertySources.addFirst(new PropertiesPropertySource("myapp.config.location", properties))
}
}
}
Then I specify the YAML file when I run it
command line
java -jar -Dmyapp.config.location=/etc/myapp/application.yml build/libs/myapp-0.1.war

Resources