I use spring aop to intercept the invocation of method.
Then I defined an annotation TestParam
#Target({ElementType.PARAMETER})
#Retention(RetentionPolicy.RUNTIME)
public #interface TestParam{}
And I try to add this annotation to a parameter in method.
public class Test {
public void test(String abc, #TestParam String def) {
}
}
I try to intercept the invocation
#Around
public Object intercept(ProceedingJoinPoint proceedingJoinPoint) {
Signature signature = proceedingJoinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
Method method = methodSignature.getMethod();
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
Annotation annotation = parameter.getAnnotation(TestParam.class);
if (annotation != null) {
// how can I can the value of this parameter
}
}
}
Then how can I get the value of the parameter who is annotationned with #TestParam?
I want to get the parameter's value, not the value of annotation.
Here is an MCVE with package names, imports etc. Just copy & paste.
Marker annotation:
package de.scrum_master.app;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Target(PARAMETER)
#Retention(RUNTIME)
public #interface TestParam {}
Driver application:
package de.scrum_master.app;
public class Test {
public void test(String abc, #TestParam String def) {}
public void toast(#TestParam String def) {}
public void doSomething(String abc, String def) {}
public int doSomethingElse(#TestParam int number, String abc, #TestParam String def) {
return number * 2;
}
public static void main(String[] args) {
Test test = new Test();
test.test("foo", "bar");
test.toast("cheers");
test.doSomething("foo", "bar");
test.doSomethingElse(11, "bar", "zot");
}
}
Aspect:
package de.scrum_master.aspect;
import java.lang.annotation.Annotation;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import de.scrum_master.app.TestParam;
#Aspect
public class MyAspect {
#Around("execution(public * *(.., #de.scrum_master.app.TestParam (*), ..))")
public Object doAwesomeStuff(ProceedingJoinPoint thisJoinPoint) throws Throwable {
System.out.println(thisJoinPoint);
Object[] methodArgs = thisJoinPoint.getArgs();
int numArgs = methodArgs.length;
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
for (int i = 0; i < numArgs; i++) {
Annotation[] annotations = annotationMatrix[i];
for (Annotation annotation : annotations) {
if (annotation.annotationType() == TestParam.class) {
//System.out.println(" annotation = " + annotation);
System.out.println(" annotated parameter value = " + methodArgs[i]);
}
}
}
return thisJoinPoint.proceed();
}
}
Console log:
execution(void de.scrum_master.app.Test.test(String, String))
annotated parameter value = bar
execution(void de.scrum_master.app.Test.toast(String))
annotated parameter value = cheers
execution(int de.scrum_master.app.Test.doSomethingElse(int, String, String))
annotated parameter value = 11
annotated parameter value = zot
Related
Suppose I have an annotation as following:
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface DBOperation
{
boolean isReadOperation() default true;
}
Then in the Aspect, how could I want to write two pointcuts, one for all the method annotated with #DBOperation(isReadOperation=true) and one for #DBOperation(isReadOperation=false)?
The syntax is actually pretty straightforward. Here is an MCVE:
Marker annotation:
package de.scrum_master.app;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Retention(RUNTIME)
#Target(METHOD)
public #interface DBOperation {
boolean isReadOperation() default true;
}
Driver application:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
Application application = new Application();
application.doSomething();
application.readValue("name");
application.writeValue("name", "John Doe");
}
public void doSomething() {}
#DBOperation
public int readValue(String fieldName) {
return 11;
}
#DBOperation(isReadOperation = false)
public String writeValue(String fieldName, Object value) {
return "dummy";
}
}
Aspect:
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class DBOperationAspect {
#Before("execution(#de.scrum_master.app.DBOperation(isReadOperation=true) * *(..))")
public void interceptRead(JoinPoint joinPoint) throws Throwable {
System.out.println("Read operation: " + joinPoint);
}
#Before("execution(#de.scrum_master.app.DBOperation(isReadOperation=false) * *(..))")
public void interceptWrite(JoinPoint joinPoint) throws Throwable {
System.out.println("Write operation: " + joinPoint);
}
}
Console log:
Read operation: execution(int de.scrum_master.app.Application.readValue(String))
Write operation: execution(String de.scrum_master.app.Application.writeValue(String, Object))
I am trying to use the getSlingScriptHelper().getService in my project but it keeps returning null. I have done this in other projects and the implementation is similar. We are using sightly on AEM 6.3 in the project. My code below:
FOOModel :
public class FOOModel extends WCMUsePojo {
private static final Logger LOGGER = LoggerFactory.getLogger(FOOModel.class);
private String foo;
#Override
public void activate() throws Exception{
FOOInterface fooInterface = getSlingScriptHelper().getService(FOOInterface.class);
LOGGER.info("FOOInterface value is : " + fooInterface);
}
public String getFoo() {
return foo;
}
}
FooInterface :
public interface FOOInterface {
public String getFoo();
}
FOO Implementation :
#Component(metatype = true, immediate = true, label = "FOO Configuration", description = "OSGi Configuration FOO")
#Service(FOOInterface.class)
public class FOOImpl implements FOOInterface {
#Property(label = "FOO", description = "FOO to be provided")
public static final String FOO_URL = "foo.url";
private String foo;
#Activate
public void activate(ComponentContext componentContext){
Dictionary<?, ?> props = componentContext.getProperties();
this.foo = PropertiesUtil.toString(props.get(FOO_URL), StringUtils.EMPTY);
}
#Override
public String getSsoUrl() {
return foo;
}
}
The logs show "FOOInterface value is : null".
I've tried the sling model with class injection method but it did not work either.
EDIT : I have found that the service is not active. Attaching screenshot for the bundle status.
Most probably your FOOInterface service is not active. You can check /system/console/components to see its status.
The bundle that includes that service might not be properly installed. You can check its status at /system/console/bundles.
From the Autofac documentation I can see how to get all registrations for a class T:
public T[] ResolveAll<T>()
{
return _container.Resolve<IEnumerable<T>>().ToArray();
}
But when I only have the Type available, how can I get the equivalent results?
public Array ResolveAll(Type service)
{
return _container.Resolve( ???
}
I am trying to implement a wrapper class which has a pre-defined interface.
EDIT
For quick reference, the answer from Matthew Watson (with relevant ideas from David L) is:
public Array ResolveAll(Type service)
{
var typeToResolve = typeof(IEnumerable<>).MakeGenericType(service);
return _container.Resolve(typeToResolve) as Array;
}
Here is an example. I've added asserts to prove that the types returned from ResolveAll<T>(this IContainer self) are the same (and in the same order) as those returned from ResolveAll(this IContainer self, Type type):
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Autofac;
using Autofac.Core;
namespace AutofacTrial
{
public abstract class Base
{
public abstract string Name { get; }
public override string ToString()
{
return Name;
}
}
public sealed class Derived1: Base
{
public override string Name
{
get
{
return "Derived1";
}
}
}
public sealed class Derived2: Base
{
public override string Name
{
get
{
return "Derived2";
}
}
}
public sealed class Derived3: Base
{
public override string Name
{
get
{
return "Derived3";
}
}
}
static class Program
{
static void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<Derived1>().As<Base>();
builder.RegisterType<Derived2>().As<Base>();
builder.RegisterType<Derived3>().As<Base>();
var container = builder.Build();
var array1 = container.ResolveAll(typeof(Base));
var array2 = container.ResolveAll<Base>();
Trace.Assert(array1.Length == 3);
Trace.Assert(array2.Length == 3);
for (int i = 0; i < array1.Length; ++i)
{
Trace.Assert(array1[i].GetType() == array2[i].GetType());
Console.WriteLine(array1[i]);
}
}
public static T[] ResolveAll<T>(this IContainer self)
{
return self.Resolve<IEnumerable<T>>().ToArray();
}
public static object[] ResolveAll(this IContainer self, Type type)
{
Type enumerableOfType = typeof(IEnumerable<>).MakeGenericType(type);
return (object[]) self.ResolveService(new TypedService(enumerableOfType));
}
}
}
The underling implementation is the same
I also used Reflector to look at the implementation of Resolve<IEnumerable<T>>(), and it winds up doing this:
public static TService Resolve<TService>(this IComponentContext context, IEnumerable<Parameter> parameters)
{
return (TService) context.Resolve(typeof(TService), parameters);
}
which calls:
public static object Resolve(this IComponentContext context, Type serviceType, IEnumerable<Parameter> parameters)
{
return context.ResolveService(new TypedService(serviceType), parameters);
}
So the two must be equivalent, since they are implemented that way.
You can invoke _container.Resolve by calling your wrapped method via reflection (MSDN), but in doing so you will lose your compile-time type safety.
public class Container
{
public T[] ResolveAll<T>()
{
return _container.Resolve<IEnumerable<T>>().ToArray();
}
public object ResolveAllGeneric(Type t)
{
MethodInfo method = GetType().GetMethod("ResolveAll")
.MakeGenericMethod(new Type[] { t });
return method.Invoke(this, new object[] { });
}
}
I am writing a MVC application in java. Currently I am trying to write a test for my RESTfullController. The problem arises when I am trying to the get() trying to work. I get back a 404 instead of a 202. I have invested a lot of time in order to figure this out but could not. I will post my controller and the ControllerTest here
package com.bestbuy.supportspace.videolibrary.web;
import com.bestbuy.supportspace.videolibrary.config.WebAppInitializer;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
/**
* User: nikhil.thakur
* Date: 12/18/13
*/
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {WebAppInitializer.class})
#WebAppConfiguration
public class RestfullControllerTest {
private MockMvc mockMvc;
#SuppressWarnings("SpringJavaAutowiringInspection")
#Autowired
protected WebApplicationContext wac;
#Before
public void setup() {
this.mockMvc = webAppContextSetup(this.wac).build();
}
#Test
public void testFindAll() throws Exception {
mockMvc.perform(get("/rest/videos/"))
.andExpect(status().isOk());
// .andExpect(jsonPath("$", hasSize(4)));
}
}
The controller that I am trying to test is
package com.bestbuy.supportspace.videolibrary.web;
import com.bestbuy.supportspace.videolibrary.entity.Video;
import com.bestbuy.supportspace.videolibrary.services.LookupService;
import com.bestbuy.supportspace.videolibrary.services.VideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
#Controller
#RequestMapping("/")
public class RESTfulController {
#Autowired
LookupService lookupService;
#Autowired
VideoService videoService;
#RequestMapping("keywords")
public
#ResponseBody
String findAllKeywords() {
return lookupService.findAllKeywords().toString();
}
#RequestMapping("subjects")
public
#ResponseBody
String findAllSubjects() {
return lookupService.findAllSubjects().toString();
}
#RequestMapping("presenters")
public
#ResponseBody
String findAllPresenters() {
return lookupService.findAllPresenters().toString();
}
#RequestMapping(value = "videos", method = RequestMethod.GET, produces = "application/json")
public
#ResponseBody
String findAllVideos() {
return videoService.findAll().toString();
}
#RequestMapping(value = "videos/findVideosByKeywordsIdIn", method = RequestMethod.GET, produces = "application/json")
public
#ResponseBody
String findVideosByKeywordsIdIn(#RequestParam(value = "keywords") String keywords) {
return videoService.findVideosByKeywordsIdIn(getListOfIntegers(keywords)).toString();
}
#RequestMapping(value = "videos/findByPresentersIdIn", method = RequestMethod.GET, produces = "application/json")
public
#ResponseBody
String findByPresentersIdIn(#RequestParam(value = "presenters") String presenters) {
return videoService.findByPresentersIdIn(getListOfIntegers(presenters)).toString();
}
#RequestMapping(value = "videos/findBySubjectsIdIn", method = RequestMethod.GET, produces = "application/json")
public
#ResponseBody
String findBySubjectsIdIn(#RequestParam(value = "subjects") String subjects) {
return videoService.findBySubjectsIdIn(getListOfIntegers(subjects)).toString();
}
#RequestMapping(value = "videos/findByKeywordsIdInAndPresentersIdInAndSubjectsIdIn", method = RequestMethod.GET, produces = "application/json")
public
#ResponseBody
String findByKeywordsIdInAndPresentersIdInAndSubjectsIdIn(#RequestParam(value = "keywords") String keywords, #RequestParam(value = "presenters") String presenters, #RequestParam(value = "subjects") String subjects) {
return videoService.findByKeywordsIdInAndPresentersIdInAndSubjectsIdIn(getListOfIntegers(keywords), getListOfIntegers(presenters), getListOfIntegers(subjects)).toString();
}
#RequestMapping(value = "videos/findByKeywordsIdInAndPresentersIdIn", method = RequestMethod.GET, produces = "application/json")
public
#ResponseBody
String findByKeywordsIdInAndPresentersIdIn(#RequestParam(value = "keywords") String keywords, #RequestParam(value = "presenters") String presenters) {
return videoService.findByKeywordsIdInAndPresentersIdIn(getListOfIntegers(keywords),getListOfIntegers(presenters)).toString();
}
#RequestMapping(value = "videos/findBySubjectsIdInAndPresentersIdIn", method = RequestMethod.GET, produces = "application/json")
public
#ResponseBody
String findBySubjectsIdInAndPresentersIdIn(#RequestParam(value = "subjects") String subjects, #RequestParam(value = "presenters") String presenters) {
return videoService.findBySubjectsIdInAndPresentersIdIn(getListOfIntegers(subjects),getListOfIntegers(presenters)).toString();
}
#RequestMapping(value = "videos/findBySubjectsIdInAndKeywordsIdIn", method = RequestMethod.GET, produces = "application/json")
public
#ResponseBody
String findBySubjectsIdInAndKeywordsIdIn(#RequestParam(value = "subjects") String subjects, #RequestParam(value = "keywords") String keywords) {
return videoService.findBySubjectsIdInAndKeywordsIdIn(getListOfIntegers(subjects),getListOfIntegers(keywords)).toString();
}
#RequestMapping(value = "video/{videoId}", method = RequestMethod.GET, produces = "application/json")
public
#ResponseBody
String readVideo(#PathVariable Integer videoId, Model model) {
Assert.notNull(videoId);
return videoService.findOne(videoId).toString();
}
#RequestMapping(value = "video/{videoId}", method = RequestMethod.PUT, consumes = "application/json", produces = "application/json")
public
#ResponseBody
String updateVideo(#RequestBody Video video, #PathVariable Integer videoId, Model model) {
Assert.notNull(video);
return videoService.save(video).toString();
}
#RequestMapping(value = "video", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
public
#ResponseBody
String createVideo(#RequestBody Video video, Model model) {
Assert.notNull(video);
return videoService.save(video).toString();
}
private List<Integer> getListOfIntegers(String keywords) {
List<Integer> ids = new ArrayList<Integer>();
for (String id : keywords.split(";") ) {
new Integer(id);
}
return ids;
}
}
Note that when i access "http://:8080/rest/videos/ " then I do see an output on the page.
My WebAppInitializer looks like this.
package com.bestbuy.supportspace.videolibrary.config;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
/**
* #author nikhil.thakur
* #since 12/12/13
*/
public class WebAppInitializer implements WebApplicationInitializer {
public static final String CONFIG_PACKAGE = "com.bestbuy.supportspace.videolibrary.config";
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.scan(CONFIG_PACKAGE);
addHttpMethodFilter(servletContext);
ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.addMapping("/rest/*");
servlet.setLoadOnStartup(1);
servletContext.addListener(new ContextLoaderListener(ctx));
}
private void addHttpMethodFilter(ServletContext servletContext) {
FilterRegistration.Dynamic httpMethodFilter = servletContext.addFilter("HttpMethodFilter", new HiddenHttpMethodFilter());
httpMethodFilter.addMappingForUrlPatterns(null, false, "/*");
}
}
mockMvc.perform(get("/rest/videos/"))
I'm pretty sure that in your case "rest" is the name / url part of the application. It's irrelevant for the test. Just use "/videos".
I've been struggling with passing Java objects from Java through JSNI (gwt-exporter generated) into Java and wonder if anybody can help?
I am creating an object in Java ("Person"), passing it to a JSNI method ("displayPerson") that invokes a Java method exposed with gwt-exporter ("CommonService.displayPerson"); however the parameter to the last stage becomes null.
If I pass a String it works OK; it's just with my objects I hit the problem.
Person is defined in a GWT application JAR inherited by the other GWT application.
Thanks for looking,
Mike
GWT application
package com.anstis.pluginserver.client;
import com.anstis.plugincommon.shared.Person;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
public class PluginServer implements EntryPoint {
public void onModuleLoad() {
GWT.create(CommonService.class);
onLoadImpl();
RootPanel.get("container").add(getButton());
}
private native void onLoadImpl() /*-{
if ($wnd.jscOnLoad && typeof $wnd.jscOnLoad == 'function') $wnd.jscOnLoad();
}-*/;
private Button getButton() {
Button btn = new Button("Click!");
btn.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
Person p = new Person();
p.setName("Smurf");
p.setAge(500);
displayPerson(p);
}
});
return btn;
}
private native void displayPerson(Person person) /*-{
// The below displays shows 'person' is not null
alert("PluginServer.displayPerson.person is " + (person != null ? "not " : "") + "null");
try {
var pluginServer = new $wnd.com.anstis.pluginserver.CommonService();
// The below displays shows 'pluginServer' is not null
alert("PluginServer.displayPerson.pluginServer = " + pluginServer);
pluginServer.displayPerson(person);
} catch(err) {
alert(err);
}
}-*/;
}
CommonService.java
package com.anstis.pluginserver.client;
import org.timepedia.exporter.client.Export;
import org.timepedia.exporter.client.Exportable;
import com.anstis.plugincommon.shared.Person;
import com.anstis.plugincommon.shared.PluginCallback;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
#Export
public class CommonService implements Exportable {
public void displayPerson(Person person) {
//The below shows 'person' *IS* null
Window.alert("CommonService.displayPerson.person is "
+ (person != null ? "not " : "") + "null");
Window.alert("Name=" + person.getName());
}
}
Person.java
package com.anstis.plugincommon.shared;
import org.timepedia.exporter.client.Exportable;
public class Person implements Exportable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
You need no to implement Exportable for Person class.
public class Person {
and it works.
If anybody else stumbles across this question, I now have a working example at git://github.com/manstis/gwt-plugins.git