Aspect-Oriented programming issue in grails . Point-cut methods are not executing - java

I am using Grails 2.4.3 . In resource.groovy I have added component-scan
xmlns aop:"http://www.springframework.org/schema/aop"
context.'component-scan'('base-package': 'com')
Then in src/groovy I have created groovy class
package com.demo.aspects.mongo.history;
import grails.transaction.Transactional
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Before
import org.aspectj.lang.annotation.After
import org.springframework.stereotype.Component
#Aspect
#Component
#Transactional
public class MongoAspectAdvice {
#After("execution(* com.demo.global.BaseOptionService.save(..))")
def afterMethod(){
println "after method execution"
}
#Before("execution(* com.demo.global.BaseOptionService.save(..))")
def beforeMethod(){
println "before method execution"
}
}
And save funtion in com.demo.global.BaseOptionService is defined as
def save(def entity){
if(entity.id == null){
entity.createdDate = new Date()
}
entity.lastUpdatedDate = new Date()
log.debug(entity)
neo4jTemplate.save(entity)
}
And BaseOptionService is extended by UserService in which BaseOptionService method is called.
UserService.groovy
class UserService extends BaseOptionService{
def addUser(username,email,role,phonenumber){
log.debug "user ===== "+username
UserCommand userCommand = new UserCommand()
userCommand.username = username
userCommand.email = email
userCommand.phonenumber = phonenumber
userCommand.role = role
if(userCommand.labels?.empty == true || userCommand.labels == null){
if(role == null){
userCommand.addLabel(null)
}else{
userCommand.addLabel("_USER")
userCommand.addLabel(role)
}
}
userCommand.isActive = true
userCommand.token = null
UserDomain user = userCommand.getUser()
log.debug "user == "+user
save(user)
return user
}
def removeLabels(id,label){
UserDomain user = findOne(id,UserDomain)
if(user.labels?.contains(label)){
user.labels.remove(label)
}
save(user)
return user
}
def serviceMethod() {
}
}
When save function is executing , I haven't seen println statement of afterMethod and beforeMethod in console and there is no error . I am not sure what wrong I am doing. Please help.

when your application start, the component scan will scan all packages for check what beans are present.
This process anyway don't instantiate the bean if it's not referenced by any other class. In other way you are telling that yes i have a MongoAspectAdvice class that is annotated with #Component so it's also a singleton but where you use it?
Try to import it in UserService.
Then if stil not working ( for check that you can put a breakpoint in that class ) add the following code to you resources.groovy:
// Place your Spring DSL code here
beans = {
mongoAspectAdvice(MongoAspectAdvice) { bean ->
bean.autowire = "byName"
}
And then import in your service:
def mongoAspectAdvice
However you can replicate this behaviour by using some grails ad-hc closures:
def beforeInterceptor = {
println "Tracing action ${actionUri}"
}
And
def afterInterceptor = {
println "Tracing action ${actionUri}"
}
Put them in BaseOptionService

Related

Problem while authenticating URL in spock testing

I have a groovy file gitClone.groovy which has a function call.
def call(credentials, url, project, branch, path, refs, noTags=false,
timeout=20)
{
}
I am writing a test for validating the 'url'. I want to write a test case which will validate if the url is correct or not. My test file is as follows:
gitCloneSpec.groovy
import com.homeaway.devtools.jenkins.testing.JenkinsPipelineSpecification;
import spock.lang.*
import java.net.URL;
public class gitCloneSpec extends JenkinsPipelineSpecification {
def gitClone = null
def check = 0
def setup() {
gitClone = loadPipelineScriptForTest("vars/gitClone.groovy")
gitClone.getBinding().setVariable( "url", "https://www.google.com/")
}
def "validate url"(){
when:
try {
URL u = new URL(url)
u.toURI()
check = 1
}
// If there was an Exception
// while creating URL object
catch (Exception e) {
check = 2;
}
then:
check == 1
}
}
Somehow url is not able to store the string "http://www.google.com" and it is throwing the exception where 'check' is getting updated with value '2'
How can I perform this test?

How to use Spring boot for local simple project?

That's a bit silly, but I'm really missing the point here. I have a Spring Boot working app, the main Application class is
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
It it is from this https://github.com/netgloo/spring-boot-samples/tree/master/spring-boot-mysql-springdatajpa-hibernate great and simple example.
It has a controller for http requests which says
#RequestMapping("/create")
#ResponseBody
public String create(String email, String name) {
User user = null;
try {
user = new User(email, name);
userDao.save(user);
}
catch (Exception ex) {
return "Error creating the user: " + ex.toString();
}
return "User succesfully created! (id = " + user.getId() + ")";
}
My question is, how do I use it like my simple local application with some logic in main() mwthod?
I tried something like
new UserController().create("test#test.test", "Test User");
but it doesn't work, though I get no errors. I just don't need any http requests/responses.
Once your application is running and your UserController() is ready to accept requested if it annotated by #Controller you can call the create method by url
ex. localhost:8080/create providing email, name as request parameters
Yes you can create sprint boot command line application.
please add the below method in Application class of spring boot
#Autowired
private UserServiceImpl userServiceImpl;
#Bean
public CommandLineRunner commandLineRunner(ApplicationContext context) {
return ((String...args) -> {
/**
*
* Call any methods of service class
*
*/
userServiceImpl.create();
});
}

Discovering test with JUnit 5 doesn't execute LoggingListener (implementation of TestExecutionListeners)

I'm using JUnit Jupiter version 5.0.0 (Release version) and I'm trying to use the test discovery feature.
The documentation of Junit can be found in 7.1.1. Discovering Tests from http://junit.org/junit5/docs/5.0.0/user-guide/#launcher-api-discovery
My implementation is:
import static org.junit.platform.engine.discovery.ClassNameFilter.includeClassNamePatterns;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage;
import org.junit.platform.launcher.Launcher;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.TestExecutionListener;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.launcher.core.LauncherFactory;
import org.junit.platform.launcher.listeners.LoggingListener;
public class MainPrueba {
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
System.out.println("Runing thread INI");
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(
selectPackage("org.package.qabootfx.test.ping")
//,selectClass(QabootfxApplicationTests.class)
)
.filters(
//includeClassNamePatterns(".*Test")
includeClassNamePatterns(".*")
)
.build();
Launcher launcher = LauncherFactory.create();
TestPlan testPlan = launcher.discover(request);
for (TestIdentifier root : testPlan.getRoots()) {
System.out.println("Root: " + root.toString());
for (TestIdentifier test : testPlan.getChildren(root)) {
System.out.println("Found test: " + test.toString());
}
}
// Register a listener of your choice
//TestExecutionListener listener = new SummaryGeneratingListener();
TestExecutionListener listener = LoggingListener.forJavaUtilLogging(); //new LoggingListener();
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
System.out.println("Runing thread END");
};
new Thread(task).start();
Thread.sleep(5000);
System.out.println("END");
}
}
Examining LoggingListener class implementation we can see that this must print to the console the results. For example:
package org.junit.platform.launcher.listeners;
#API(status = MAINTAINED, since = "1.0")
public class LoggingListener implements TestExecutionListener {
....
#Override
public void testPlanExecutionStarted(TestPlan testPlan) {
log("TestPlan Execution Started: %s", testPlan);
}
#Override
public void testPlanExecutionFinished(TestPlan testPlan) {
log("TestPlan Execution Finished: %s", testPlan);
}
...
}
and my Test class is:
public class QabootfxApplicationTest {
#Test
public void testAbout() {
System.out.println("TEST Execution.... QabootfxApplicationTests.testAbout()");
assertEquals(4, 5, "The optional assertion message is now the last parameter.");
}
}
I'm expecting see in the console something similar to:
2017-09-20 10:53:48.041 INFO 11596 --- TestPlan Execution Started: ....
2017-09-20 10:53:48.041 INFO 11596 --- TestPlan Execution Finished: ....
but I can't see nothing similar to "... TestPlan Execution Started...".
The console output is:
Runing thread INI
Root: TestIdentifier [uniqueId = '[engine:junit-jupiter]', parentId = null, displayName = 'JUnit Jupiter', legacyReportingName = 'JUnit Jupiter', source = null, tags = [], type = CONTAINER]
Found test: TestIdentifier [uniqueId = '[engine:junit-jupiter]/[class:org.package.qabootfx.test.ping.QabootfxApplicationTest]', parentId = '[engine:junit-jupiter]', displayName = 'QabootfxApplicationTest', legacyReportingName = 'org.package.qabootfx.test.ping.QabootfxApplicationTest', source = ClassSource [className = 'org.package.qabootfx.test.ping.QabootfxApplicationTest', filePosition = null], tags = [], type = CONTAINER]
TEST Executon.... QabootfxApplicationTests.testAbout()
Runing thread END
END
Could be a bug? or I'm implementing something wrong?
Why would you expect the listener created by LoggingListener.forJavaUtilLogging() to log anything at log level INFO... when the documentation explicitly states the following?
Create a LoggingListener which delegates to a java.util.logging.Logger using a log level of FINE.
If you want the LoggingListener to log messages at level INFO, you'll have to create it using the other factory method which accepts a log level like this LoggingListener.forJavaUtilLogging(Level.INFO).

Grails: how to call a service and the service name from a string

I want to call services dynamically so the service name will get as a string value, we can list all the services names in the grails project by using the code below.
import org.codehaus.groovy.grails.plugins.metadata.GrailsPlugin
for (type in ['service']) {
for (artifactClass in ctx.grailsApplication."${type}Classes") {
def clazz = artifactClass.clazz
def annotation = clazz.getAnnotation(GrailsPlugin)
if (annotation) {
println "$type $clazz.name from plugin '${annotation.name()}'"
}
else {
println "$type $clazz.name from application"
}
}
}
Here we will get artifactClass of the service.Is there any option to call the service by using this idea.Please help me.
You can get the bean for the service from the applicationContext
//inject application context bean
def applicationContext
//to use
applicationContext."${yourServiceName}".serviceMethod()
You can get the bean of your service this way:
import grails.util.Holders
...
YourService yourService =
(YourService)Holders.grailsApplication.mainContext["yourService"]

How to log the active configuration in a Spring Boot application?

I would really like to use YAML config for Spring Boot, as I find it quite readable and useful to have a single file showing what properties are active in my different profiles. Unfortunately, I'm finding that setting properties in application.yml can be rather fragile.
Things like using a tab instead of spaces will cause properties to not exist (without warnings as far as I can see), and all too often I find that my active profiles are not being set, due to some unknown issue with my YAML.
So I was wondering whether there are any hooks that would enable me to get hold of the currently active profiles and properties, so that I could log them.
Similarly, is there a way to cause start-up to fail if the application.yml contains errors? Either that or a means for me to validate the YAML myself, so that I could kill the start-up process.
In addition to other answers: logging active properties on context refreshed event.
Java 8
package mypackage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
#Slf4j
#Component
public class AppContextEventListener {
#EventListener
public void handleContextRefreshed(ContextRefreshedEvent event) {
printActiveProperties((ConfigurableEnvironment) event.getApplicationContext().getEnvironment());
}
private void printActiveProperties(ConfigurableEnvironment env) {
System.out.println("************************* ACTIVE APP PROPERTIES ******************************");
List<MapPropertySource> propertySources = new ArrayList<>();
env.getPropertySources().forEach(it -> {
if (it instanceof MapPropertySource && it.getName().contains("applicationConfig")) {
propertySources.add((MapPropertySource) it);
}
});
propertySources.stream()
.map(propertySource -> propertySource.getSource().keySet())
.flatMap(Collection::stream)
.distinct()
.sorted()
.forEach(key -> {
try {
System.out.println(key + "=" + env.getProperty(key));
} catch (Exception e) {
log.warn("{} -> {}", key, e.getMessage());
}
});
System.out.println("******************************************************************************");
}
}
Kotlin
package mypackage
import mu.KLogging
import org.springframework.context.event.ContextRefreshedEvent
import org.springframework.context.event.EventListener
import org.springframework.core.env.ConfigurableEnvironment
import org.springframework.core.env.MapPropertySource
import org.springframework.stereotype.Component
#Component
class AppContextEventListener {
companion object : KLogging()
#EventListener
fun handleContextRefreshed(event: ContextRefreshedEvent) {
printActiveProperties(event.applicationContext.environment as ConfigurableEnvironment)
}
fun printActiveProperties(env: ConfigurableEnvironment) {
println("************************* ACTIVE APP PROPERTIES ******************************")
env.propertySources
.filter { it.name.contains("applicationConfig") }
.map { it as EnumerablePropertySource<*> }
.map { it -> it.propertyNames.toList() }
.flatMap { it }
.distinctBy { it }
.sortedBy { it }
.forEach { it ->
try {
println("$it=${env.getProperty(it)}")
} catch (e: Exception) {
logger.warn("$it -> ${e.message}")
}
}
println("******************************************************************************")
}
}
Output like:
************************* ACTIVE APP PROPERTIES ******************************
server.port=3000
spring.application.name=my-app
...
2017-12-29 13:13:32.843 WARN 36252 --- [ main] m.AppContextEventListener : spring.boot.admin.client.service-url -> Could not resolve placeholder 'management.address' in value "http://${management.address}:${server.port}"
...
spring.datasource.password=
spring.datasource.url=jdbc:postgresql://localhost/my_db?currentSchema=public
spring.datasource.username=db_user
...
******************************************************************************
I had the same problem, and wish there was a debug flag that would tell the profile processing system to spit out some useful logging. One possible way of doing it would be to register an event listener for your application context, and print out the profiles from the environment. I haven't tried doing it this way myself, so your mileage may vary. I think maybe something like what's outlined here:
How to add a hook to the application context initialization event?
Then you'd do something like this in your listener:
System.out.println("Active profiles: " + Arrays.toString(ctxt.getEnvironment().getActiveProfiles()));
Might be worth a try. Another way you could probably do it would be to declare the Environment to be injected in the code where you need to print the profiles. I.e.:
#Component
public class SomeClass {
#Autowired
private Environment env;
...
private void dumpProfiles() {
// Print whatever needed from env here
}
}
Actuator /env service displays properties, but it doesn't displays which property value is actually active. Very often you may want to override your application properties with
profile-specific application properties
command line arguments
OS environment variables
Thus you will have the same property and different values in several sources.
Snippet bellow prints active application properties values on startup:
#Configuration
public class PropertiesLogger {
private static final Logger log = LoggerFactory.getLogger(PropertiesLogger.class);
#Autowired
private AbstractEnvironment environment;
#PostConstruct
public void printProperties() {
log.info("**** APPLICATION PROPERTIES SOURCES ****");
Set<String> properties = new TreeSet<>();
for (PropertiesPropertySource p : findPropertiesPropertySources()) {
log.info(p.toString());
properties.addAll(Arrays.asList(p.getPropertyNames()));
}
log.info("**** APPLICATION PROPERTIES VALUES ****");
print(properties);
}
private List<PropertiesPropertySource> findPropertiesPropertySources() {
List<PropertiesPropertySource> propertiesPropertySources = new LinkedList<>();
for (PropertySource<?> propertySource : environment.getPropertySources()) {
if (propertySource instanceof PropertiesPropertySource) {
propertiesPropertySources.add((PropertiesPropertySource) propertySource);
}
}
return propertiesPropertySources;
}
private void print(Set<String> properties) {
for (String propertyName : properties) {
log.info("{}={}", propertyName, environment.getProperty(propertyName));
}
}
}
If application.yml contains errors it will cause a failure on startup. I guess it depends what you mean by "error" though. Certainly it will fail if the YAML is not well formed. Also if you are setting #ConfigurationProperties that are marked as ignoreInvalidFields=true for instance, or if you set a value that cannot be converted. That's a pretty wide range of errors.
The active profiles will probably be logged on startup by the Environment implementation (but in any case it's easy for you to grab that and log it in your launcher code - the toString() of teh Environment will list the active profiles I think). Active profiles (and more) are also available in the /env endpoint if you add the Actuator.
In case you want to get the active profiles before initializing the beans/application, the only way I found is registering a custom Banner in your SpringBootServletInitializer/SpringApplication (i.e. ApplicationWebXml in a JHipster application).
e.g.
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder)
{
// set a default to use when no profile is configured.
DefaultProfileUtil.addDefaultProfile(builder.application());
return builder.sources(MyApp.class).banner(this::printBanner);
}
/** Custom 'banner' to obtain early access to the Spring configuration to validate and debug it. */
private void printBanner(Environment env, Class<?> sourceClass, PrintStream out)
{
if (env.getProperty("spring.datasource.url") == null)
{
throw new RuntimeException(
"'spring.datasource.url' is not configured! Check your configuration files and the value of 'spring.profiles.active' in your launcher.");
}
...
}

Categories

Resources