Invoke method in Func when passed as parameter - reflection

I was creating a Func as parameter input to another method, but how do I invoke that?
The following code describes my work:
I call Foo with:
Foo(x => x.SlidingExpiration(TimeSpan.FromSeconds(50)));
My method Foo:
public void Foo(Func<CacheExpiration, TimeSpan> cacheExpiration)
{
....
inside here I want to call RefreshCache, but how?.. cacheExpiration.??
}
The CacheExpiration :)
public class CacheExpiration
{
TimeSpan timeSpan;
bool sliding;
public TimeSpan SlidingExpiration(TimeSpan ts)
{
this.timeSpan = ts;
this.sliding = true;
return ts;
}
public TimeSpan AbsoluteExpiration(TimeSpan ts)
{
this.timeSpan = ts;
return ts;
}
public bool RefreshCache(MetaObject mo)
{
//some logic....
return true;
}
}

var ts = cacheExpiration(yourCacheExpiration);

If I'm reading this correctly then the Func cacheExpiration takes a CacheExpiration instance and returns a TimeSpan. So I could see the body of Foo being:
TimeSpan ts = cacheExpiration.SlidingExpiration(TimeSpan.FromSeconds(50));
//or
TimeSpan ts2 = cacheExpiration.AbsoluteExpiration(TimeSpan.FromSeconds(50));
This doesn't line up with the lamda in your example so I'm guessing from that you really want cacheExpiration to be a Func that takes a Timespan and returns a TimeSpan. But this wouldn't work for the RefreshCache method as it takes a MetaObject and returns a boolean.

Related

WebFlux returning http.okay vice http.notFound

New to WebFlux, reactive, and handlers. I've got things "working", but am not understanding why following code is returning "okay" with empty body, vice "not found".
Clarification: The issue-of-concern is in the final return statement of DemoPOJOHandler.getById(). The "short-circuit" code works as expected (i.e., returns "Bad Request" status), but the "switchIfEmpty" path of the final return statement does not appear to get exercised if a DemoPOJORepo.getById(int) returns Mono.empty().
(Note: I've hacked up a list-based "repo" to avoid dealing with database while figuring out handlers and http return types.)
Router implementation ("/v1" is a set of annotation based RESTful endpoints)...
#Configuration
public class DemoPOJORouter {
#Bean
public RouterFunction<ServerResponse> route(DemoPOJOHandler requestHandler) {
return nest(path("/v2"),
nest(accept(APPLICATION_JSON),
RouterFunctions.route(RequestPredicates.GET("/DemoPOJO"), requestHandler::getAll)
.andRoute(RequestPredicates.GET("/DemoPOJO/{id}"), requestHandler::getById)
.andRoute(RequestPredicates.POST("/DemoPOJO"), requestHandler::add)));
}
}
Handler implementation has been "stripped down" to only the code in question. I have a feeling that much of the style is "still imperative", but I've attempted to put the reactive stuff where it "makes the most sense".
If I supply a bad value on the URI (i.e., "foo"), then I get the http "bad request" returned. But, never seem to get the "not found" that should be generated by "switchIfEmpty" if a validly formatted int value is supplied, but it does not map to an entry in the repo.
#Component
public class DemoPOJOHandler {
public static final String PATH_VAR_ID = "id";
private DemoPOJORepo repo = null;
public Mono<ServerResponse> getById(ServerRequest request) {
Mono<DemoPOJO> monoDemoPOJO = null;
Map<String, String> pathVariables = request.pathVariables();
int id = -1;
checkRepoRef(); // part of the list hack
// short-circuit if request doesn't contain id (should never happen)
if ((pathVariables == null)
|| (!pathVariables.containsKey(PATH_VAR_ID))) {
return ServerResponse.badRequest().build();
}
// short-circuit if bad id value
try {
id = Integer.parseInt(pathVariables.get(PATH_VAR_ID));
} catch(NumberFormatException e) {
return ServerResponse.badRequest().build();
}
// get entity by keyValue
monoDemoPOJO = repo.getById(id);
return monoDemoPOJO
.flatMap(demoPOJO -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.syncBody(demoPOJO)
.switchIfEmpty(ServerResponse.notFound().build()));
}
}
Hack of a list-based repo to avoid dealing with data/APIs while working on handlers and http return types.
// local hack to avoid a database for testing
public class DemoPOJORepo {
private static DemoPOJORepo fpRepo = null;
private static int NUM_ROWS = 100;
private Map<Integer, DemoPOJO> fooPOJOMap;
private DemoPOJORepo() {
initMap();
}
public static DemoPOJORepo getInstance() {
if (fpRepo == null) {
fpRepo = new DemoPOJORepo();
}
return fpRepo;
}
public Mono<DemoPOJO> getById(int id) {
Mono<DemoPOJO> monoDP;
if (fooPOJOMap.containsKey(id)) {
monoDP = Mono.just(fooPOJOMap.get(id));
} else {
monoDP = Mono.empty();
}
return monoDP;
}
private Mono<Void> initMap() {
fooPOJOMap = new TreeMap<Integer, DemoPOJO>();
int offset = -1;
for(int ndx=0; ndx<NUM_ROWS; ndx++) {
offset = ndx + 1;
fooPOJOMap.put(offset, new DemoPOJO(offset, "foo_" + offset, offset+100));
}
return Mono.empty();
}
}
Your brackets are in the wrong place causing the swithIfEmpy to apply to the ServerResponse.ok() publisher not the monoDemoPOJO, replace the return with this and it should work:
return monoDemoPOJO
.flatMap(demoPOJO -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).syncBody(demoPOJO))
.switchIfEmpty(ServerResponse.notFound().build());
As I can see the code is right. The response code is Bad request because you are trying to convert "foo" to Integer, and when it throws an exception you are returning a Bad request response, so I think it works perfectly fine.
If you use an Integer id that is not present in your database then the answer must be a not found response

Constraints on parameters in api interface

I've declared an API call in an interface and was wondering if it is possible to put constraints on some of the parameters. The API I'm accessing has these constraints as well and would like to enforce them in my program.
#GET("/recipes/search")
Call<RecipeResponse> getRecipes(
#Query("cuisine") String cuisine,
#Query("diet") String diet,
#Query("excludeIngredients") String excludeIngredients,
#Query("intolerances") String intolerances,
#Query("number") Integer number,
#Query("offset") Integer offset,
#Query("query") String query,
#Query("type") String type
);
How can I do this?
I know that it is possible to do this with POST request, and passing along an object via the RequestBody through the #Body annotation. Can I do this with a GET request too, where information is passed via the query string?
Thanks!
I think I ended up finding a solution. I've made a class SearchRecipeRequest in which I declare all possible parameters as class variables. In the setters I do the data validation such as checking for null on parameters that are required, or min/max value constraints on integers as specified by the endpoint. I then made a SearchRecipeRequestBuilder class to build such an object like so to make it easier to deal with all those possible parameters:
public class SearchRecipeRequestBuilder {
private String _cuisine = null,
_diet = null,
_excludeIngredients = null,
_intolerances = null,
_query = null,
_type = null;
private Integer _number = null,
_offset = null;
public SearchRecipeRequestBuilder() {}
public SearchRecipeRequest buildRequest() {
return new SearchRecipeRequest(_cuisine, _diet, _excludeIngredients, _intolerances, _number, _offset, _query, _type);
}
public SearchRecipeRequestBuilder cuisine(String cuisine) {
_cuisine = cuisine;
return this;
}
public SearchRecipeRequestBuilder diet(String diet) {
_diet = diet;
return this;
}
public SearchRecipeRequestBuilder excludeIngredients(String excludeIngredients) {
_excludeIngredients = excludeIngredients;
return this;
}
public SearchRecipeRequestBuilder intolerances(String intolerances) {
_intolerances = intolerances;
return this;
}
public SearchRecipeRequestBuilder query(String query) {
_query = query;
return this;
}
public SearchRecipeRequestBuilder type(String type) {
_type = type;
return this;
}
public SearchRecipeRequestBuilder number(Integer number) {
_number = number;
return this;
}
public SearchRecipeRequestBuilder offset(Integer offset) {
_offset = offset;
return this;
}
}
Which allows me to build the request like so:
SearchRecipeRequest request = new SearchRecipeRequestBuilder()
.query("burger")
.buildRequest();
I then pass along that object to a different function that knows how to use the request object to pass it along to the API.
That's how I'm doing it right now, if someone has a better way I'd love to hear it. :)
I got the idea to use the Builder pattern from a different StackOverflow question: Managing constructors with many parameters in Java.

PureMVC / complicated asMock

Ok - I've got a bit of a complicated asMock setup here; I've got a PureMVC async command that is attempting to call another class that implements interfaces in order to set up some asmocks for development without the backend.
import test.mix.common.business.MockInterbahnServiceFactory;
public class InitMockInterbahnServiceFactory extends AsyncCommand{
public static var mockServiceFactory:MockInterbahnServiceFactory = new MockInterbahnServiceFactory();
override public function execute(notification:INotification):void{
var serviceResult:IEventDispatcher = mockServiceFactory.mockRepository.prepare([EchoBusinessObjects, SendBusinessObjects]);
//serviceResult.addEventListener(Event.COMPLETE, onComplete);
}
private function onComplete(event:Event):void{
mx.controls.Alert.show("COMPLETE!");
var logMessage:String = "4 MOCK SERVICE FACTORY MOCKED !!!!!";
sendNotification( MixConstants.LOG_OUTPUT, logMessage );
//sendNotification(MixConstants.INTERBAHN_CONNECTED, mockServiceFactory);
// commandComplete() ;
}
}
This is actually trying to set up a MockRepositoryFactory:
public class MockInterbahnServiceFactory implements ServiceFactory
{
[Mock] public static var withMocks : Array = [
SendBusinessObjects, EchoBusinessObjects
];
//public static var mockRepository:MockRepository ;//= new MockRepository();
public var mockSendBusinessObjects:SendBusinessObjects;
public var mockEchoBusinessObjects:EchoBusinessObjects ;
public var mockRepository:MockRepository;
public function MockInterbahnServiceFactory(){
mockRepository = new MockRepository();
prepareMocks();
}
public function prepareMocks():void{
var prepareDispatcher:IEventDispatcher = mockRepository.prepare([SendBusinessObjects, EchoBusinessObjects]);
prepareDispatcher.addEventListener(Event.COMPLETE, setupMocks);
}
public function setupMocks(event:Event):void{
mockSendBusinessObjects = SendBusinessObjects(mockRepository.create(SendBusinessObjects));
mockEchoBusinessObjects = EchoBusinessObjects(mockRepository.create(EchoBusinessObjects));
SetupResult.forCall(mockSendBusinessObjects.sendOrder(new Order())).returnValue('wee');
}
public function createSendBusinessObjectService():SendBusinessObjects{
return mockSendBusinessObjects;
}
public function createEchoBusinessObjectService():EchoBusinessObjects{
return mockEchoBusinessObjects;
}
}
}
And at some point this factory is going to get passed around and utilized for the send / receive endpoints for multiple communications (true backend being a scala one).
I'm getting this error:
ArgumentError: returnValue must be assignable from :void
at asmock.framework.expectations::AbstractExpectation/set returnValue()[C:\Users\Richard\SVN\asmock\trunk\source\ASMock\src\asmock\framework\expectations\AbstractExpectation.as:107]
at asmock.framework::MethodOptions/returnValue()[C:\Users\Richard\SVN\asmock\trunk\source\ASMock\src\asmock\framework\MethodOptions.as:134]
at test.mix.common.business::MockInterbahnServiceFactory/setupMocks()[/Users/grimm/Documents/__WORK/__INVESTLAB/MIX/trunk/src/test/mix/common/business/MockInterbahnServiceFactory.as:56]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at Function/org.floxy:ProxyRepository/org.floxy:IProxyRepository:prepare/org.floxy:swfLoadedHandler()[C:\transfer\IdeaProjects\as3-interbahn\floxy\main\as3\src\org\floxy\ProxyRepository.as:218]
I'm assuming this is because of the interface functions I'm stubbing?
public interface SendBusinessObjects {
function sendFirmExchangePermission(frp:FirmExchangePermission):void ;
function sendFirm(f:Firm):void ;
function sendExchange(ex:Exchange):void ;
function sendFXConversion(fx:FXConversion):void ;
function sendInstrument(ins:Instrument):void ;
function sendQuote(q:Quote):void ;
It looks to me like SendBusinessObjects returns void, but you are calling returnValue when you are mocking the call to it. Remove the returnValue('wee') call and it should work as expected.

Flex/AS3 - calling a function dynamically using a String?

Is it possible to call a function in AS3 using a string value as the function name e.g.
var functionName:String = "getDetails";
var instance1:MyObject = new MyObject();
instance1.functionName(); // I know this is so wrong, but it gets the point accross:)
UPDATE
The answer from #Taskinoor on accessing a function is correct:
instance1[functionName]();
And to access a property we would use:
instance1[propertyName]
instance1[functionName]();
Check this for some details.
You may use function.apply() or function.call() methods instead in the case when you dont know whether object has such method for instance.
var functionName:String = "getDetails";
var instance1:MyObject = new MyObject();
var function:Function = instance1[functionName]
if (function)
function.call(instance1, yourArguments)
I have created the following wrappers for calling a function. You can call it by its name or by the actual function. I tried to make these as error-prone as possible.
The following function converts a function name to the corresponding function given the scope.
public static function parseFunc(func:*, scope:Object):Function {
if (func is String && scope && scope.hasOwnProperty(funcName)) {
func = scope[func] as Function;
}
return func is Function ? func : null;
}
Call
Signature: call(func:*,scope:Object,...args):*
public static function call(func:*, scope:Object, ...args):* {
func = parseFunc(func, scope);
if (func) {
switch (args.length) {
case 0:
return func.call(scope);
case 1:
return func.call(scope, args[0]);
case 2:
return func.call(scope, args[0], args[1]);
case 3:
return func.call(scope, args[0], args[1], args[2]);
// Continue...
}
}
return null;
}
Apply
Signature: apply(func:*,scope:Object,argArray:*=null):*
public static function apply(func:*, scope:Object, argArray:*=null):* {
func = parseFunc(func, scope);
return func != null ? func.apply(scope, argArray) : null;
}
Notes
Call
The switch is needed, because both ...args and arguments.slice(2) are Arrays. You need to call Function.call() with variable arguments.
Apply
The built-in function (apply(thisArg:*, argArray:*):*) uses a non-typed argument for the argArray. I am just piggy-backing off of this.

Dynamically implement interface in Groovy using invokeMethod

Groovy offers some really neat language features for dealing with and implementing Java interfaces, but I seem kind of stuck.
I want to dynamically implement an Interface on a Groovy class and intercept all method calls on that interface using GroovyInterceptable.invokeMethod. Here what I tried so far:
public interface TestInterface
{
public void doBla();
public String hello(String world);
}
import groovy.lang.GroovyInterceptable;
class GormInterfaceDispatcher implements GroovyInterceptable
{
def invokeMethod(String name, args) {
System.out.println ("Beginning $name with $args")
def metaMethod = metaClass.getMetaMethod(name, args)
def result = null
if(!metaMethod)
{
// Do something cool here with the method call
}
else
result = metaMethod.invoke(this, args)
System.out.println ("Completed $name")
return result
}
TestInterface getFromClosure()
{
// This works, but how do I get the method name from here?
// I find that even more elegant than using invokeMethod
return { Object[] args -> System.out.println "An unknown method called with $args" }.asType(TestInterface.class)
}
TestInterface getThisAsInterface()
{
// I'm using asType because I won't know the interfaces
// This returns null
return this.asType(TestInterface.class)
}
public static void main(String[] args)
{
def gid = new GormInterfaceDispatcher()
TestInterface ti = gid.getFromClosure()
assert ti != null
ti.doBla() // Works
TestInterface ti2 = gid.getThisAsInterface()
assert ti2 != null // Assertion failed
ti2.doBla()
}
}
Returning the Closure works fine, but I couldn't figure a way to find out the name of the method being called there.
Trying to make a Proxy to the this reference itself (so that method calls will call invokeMethod) returns null.
You could use the Map coercion feature of Groovy to dynamically generate a Map that represents the given interface:
TestInterface getMapAsInterface() {
def map = [:]
TestInterface.class.methods.each() { method ->
map."$method.name" = { Object[] args->
println "Called method ${method.name} with ${args}"
}
}
return map.asType(TestInterface.class)
}
To complete the response of Christoph, as stated by this page, you can implement an interface with a closure. For example:
def map = [doBla: { println 'Bla!'}, hello: {world -> "Hello $world".toString()}] as TestInterface
map.hello 'Groovy' // returns 'Hello Groovy'

Resources