How to programatically evaluate expression(spel/variable reference) used in annotation? - spring

Say that I have use case for finding method annotated via say #Scheduled(cron = "${variable}"), and I'd like to know the value of "cron" parameter. If I check via reflection, no surprise, I will find there value "${variable}".
Can someone share link/snipet how to evaluate variables/spel expression present in annotation? I found some answers, but neither of them worked.

Just to extend #crizzis answer, maybe filling the missing part.
Fist you need to inject/autowire ConfigurableBeanFactory beanFactory;. Looking at implementation of ExpressionValueMethodArgumentResolver and it's parent AbstractNamedValueMethodArgumentResolver it seems to me, that full code which does variable substitution and spell needs one more line:
BeanExpressionResolver beanExpressionResolver = beanFactory.getBeanExpressionResolver();
String expressionWithSubstitutedVariables = beanFactory.resolveEmbeddedValue(expression);
Object resultWithResolvedSPEL = beanExpressionResolver.evaluate(expressionWithSubstitutedVariables, new BeanExpressionContext(beanFactory, null));
then string like #{!${some-boolean-variable} ? 'a' : 'b'} was correctly evaluated for me. Not sure if this is the way-to-go as I don't know spring well, but this worked for me.

I'm sure there are a couple of ways, but the easiest is probably:
beanFactory.getBeanExpressionResolver().evaluate(
"${variable}",
new BeanExpressionContext(beanFactory, null))

Related

BuildCoreAdmin solrnetfacility is returning nullpointer exception

Need to do swapping of my cores and hence need to set the SolrCoreAdmin in my solrFacility, so I can use it throughout my application using my Windsor container.
When I do the following :
var solrFacility = new SolrNetFacility(ConfigurationSettings.ContentSearch_Solr_ServiceBaseAddress);
solrFacility.AddCore(AgentsIndex.IndexName, typeof(AgentsIndexMapper), ConfigurationSettings.ContentSearch_Solr_ServiceBaseAddress +"/"+ AgentsIndex.IndexName);
solrFacility.AddCore(AgentsIndex.SwapIndexName, typeof(AgentsIndexMapper), ConfigurationSettings.ContentSearch_Solr_ServiceBaseAddress + "/" + AgentsIndex.SwapIndexName);
solrFacility.BuildCoreAdmin(ConfigurationSettings.ContentSearch_Solr_ServiceBaseAddress);
_WindsorContainer.AddFacility("solr", solrFacility);
I get following error:
[NullReferenceException: Object reference not set to an instance of an object.]
Castle.Facilities.SolrNetIntegration.SolrNetFacility.BuildCoreAdmin(ISolrConnection conn) +40
I looked up the code inside BuildCoreAdmin using reflector and I think its trying to access a base.Kernel...is that null? How do I set that kernel? The base file is AbstractFacility and that has a function setKernel. What should this kernel be?
How do I solve this? im new to solrnet and need your help. Thanking you.
Regards,
Kasturi Chavan
I got the solution for this. I was doing it wrong. Thought of posting the answer so it helps others.
When initilaizing the solrnetfacility , the solrcoreadmin are also initialised. I later added this solrnetfacility to my container (castle windsor in this case) so i can use it over entire application.
Later when i wanted to swap the indexes after rebuild, i just resolved it
ISolrCoreAdmin _ISolrCoreAdmin = c.GetContainer().Resolve<ISolrCoreAdmin>();
ResponseHeader response = _ISolrCoreAdmin.Swap(corename, othername);
And all set!
Hope it helps someone. Thanks a lot for all help provided.

How to read pair in freemarker

I'm having little trouble with reading pair.
So I'm creating my pair
private Pair<Integer, Integer> count(somethink) {
int c1 = 2;
int c2 = 4;
return new Pair<Integer, Integer>(c1, c2);
}
And 'sending' it to ftl via java
mv.addObject("counted", count(somethink));
I won't write everything how it sends because I don't think it really matters with my issue. So i'm recieving it in "ftl". Then I was trying to 'read' it.
<#list counted?keys as key>
<#spring.message "someMsg"/>(${key}/${counted[key]})
</#list>
After then I'm getting error
Expecting a string, date or number here, Expression x is instead a freemarker.ext.beans.SimpleMethodModel
As I suppose you don't iterate pairs (or I'm wrong?) I know its pair that contains only one key and one value but still I have to do send it that way and I thought its going be to similar to iterating through map, in Java I would use pair.first() and pair.second() but it doesn't work in ftl (yes I know it shouldn't work). I also tried to cast it to String by using ?string but it didnt work too
have you tried?
${counted.first()?xml}/${counted.second()?xml}
Assuming pair.first() and second() work in your Java code.
I'm not sure how the API of Pair looks, but with ?keys you probably unwillingly list its methods. Hence the error message; you try to print the method itself, not its return value. (As of the broken error message, because there's no x there, a FreeMarker update would help.) So as Caleryn says, just call the two methods. If you need to list this thing, you probably need to put it into a List or array, unless Pair implements List (or even just Collection) or Iterable. Or if this is a bigger issue in your project, FreeMarker has this pluggable configuration component, the ObjectWrapper, and with that you can tell FreeMarker to treat Pair-s as lists, and how. That needs some deeper understanding of FreeMarker though.

Using blank? or present? in model-scopes in Ruby on Rails

In my model, I have several scopes defined such as:
scope :myScope1, where('myField IS NULL')
This works, but I don't need to check for 'Null' - I need to check for '.blank?' - because there are cases of non-nulls which are 'blank' in the DB, which I need to include. I can use '.blank?' in my class-defs (and do - and they work there), but I cannot use this in this current context.
I have not been able to find a syntax (of the non-depreciated variety) which will work for this. Thanks.
Try
scope :myScope1, where("myField IS NULL or CAST(myField as text) = ''")
It's not that simple as blank?, but I can't see a simple enough solution.

Using element "unless" for #Cacheable [spring 3.2.3] not working

I did use unless following for Cacheable, but it seems it did not work.
For the function below, it still will cache the result if result = -1.
Not sure what is the reason for its not working. Anyone gets any ideas? Any lib missing?
#Cacheable(value="queueIds", key="#servicePhoneNumber", unless="#result == -1")
public int getQueueIdByPhoneNumber(String servicePhoneNumber) { ... }
I had the same issue. The problem is that I used two different spring versions in a project.

Is it possible to use Jasmine's toHaveBeenCalledWith matcher with a regular expression?

I have reviewed Jasmine's documentation of the toHaveBeenCalledWith matcher in order to understand whether it's possible to pass in a regular expression for an argument, if that argument is expected to be a string. Unfortunately, this is unsupported functionality. There's also an issue open on github requesting this functionality.
I've dug a bit into the codebase, and I see how it might be possible to implement this inside the existing matcher. I think it would be more appropriate to implement it as a separate matcher though, so that the abstraction is captured individually.
In the meantime, what might be a good workaround?
After doing some digging, I've discovered that Jasmine spy objects have a calls property, which in turn has a mostRecent() function. This function also has a child property args, which returns an array of call arguments.
Thus, one may use the following sequence to perform a regexp match on call arguments, when one wants to check that the string arguments match a specific regular expression:
var mySpy = jasmine.createSpy('foo');
mySpy("bar", "baz");
expect(mySpy.calls.mostRecent().args[0]).toMatch(/bar/);
expect(mySpy.calls.mostRecent().args[1]).toMatch(/baz/);
Pretty straightforward.
As of Jasmine 2.2, you can use jasmine.stringMatching:
var mySpy = jasmine.createSpy('foo');
mySpy('bar', 'baz');
expect(mySpy).toHaveBeenCalledWith(
jasmine.stringMatching(/bar/),
jasmine.stringMatching(/baz/)
);
In Jasmine 2.0 the signature changed a bit. Here it would be:
var mySpy = jasmine.createSpy('foo');
mySpy("bar", "baz");
expect(mySpy.calls.mostRecent().args[0]).toMatch(/bar/);
expect(mySpy.calls.mostRecent().args[1]).toMatch(/baz/);
And the Documentation for Jasmine 1.3 has moved.
Alternatively, if you are spying on a method on an object:
spyOn(obj, 'method');
obj.method('bar', 'baz');
expect(obj.method.argsForCall[0][0]).toMatch(/bar/);
expect(obj.method.argsForCall[0][1]).toMatch(/baz/);
Sometimes it is more readable to write it this way:
spyOn(obj, 'method').and.callFake(function(arg1, arg2) {
expect(arg1).toMatch(/bar/);
expect(arg2).toMatch(/baz/);
});
obj.method('bar', 'baz');
expect(obj.method).toHaveBeenCalled();
It give more clear visibility of method arguments (instead of using array)
As jammon mentioned, the Jasmine 2.0 signature has changed. If you are spying on the method of an object in Jasmine 2.0, Nick's solution should be changed to use something like -
spyOn(obj, 'method');
obj.method('bar', 'baz');
expect(obj.method.calls.mostRecent().args[0]).toMatch(/bar/);
expect(obj.method.calls.mostRecent().args[1]).toMatch(/baz/);

Resources