Let's say I have a configuration class like so
#Configuration
public class NeverUsedConfig {
#Bean
public UselessObject getUselessObject() {
// execute some crucial state-changing code
}
}
If getUselessObject() is never called and UselessObject is never #Injected anywhere, is the getUselessObject() method ever called?
I have a similar situation, where it seems like it's being called in one environment and not in another. When it's called, I can see the logging inside the method as well as setting up some important AWS SDK Metrics. In another account/region, it doesn't seem to be called. My AWS SDK Metrics are not set up and there is no logging
Related
I have develop a new Connector. This connector requires to be configured with two parameters, lets say:
default_trip_timeout_milis
default_trip_threshold
Challenge is, I want read ${myValue_a} and ${myValue_a} from an API, using an HTTP call, not from a file or inline values.
Since this is a connector, I need to make this API call somewhere before connectors are initialized.
FlowVars aren't an option, since they are initialized with the Flows, and this is happening before in the Mule app life Cycle.
My idea is to create an Spring Bean implementing Initialisable, so it will be called before Connectors are init, and here, using any java based libs (Spring RestTemplate?) , call API, get values, and store them somewhere (context? objectStore?) , so the connector can access them.
Make sense? Any other ideas?
Thanks!
mmm you could make a class that will create the properties in the startup and in this class obtain the API properties via http request. Example below:
public class PropertyInit implements InitializingBean,FactoryBean {
private Properties props = new Properties();
#Override
public Object getObject() throws Exception {
return props;
}
#Override
public Class getObjectType() {
return Properties.class;
}
}
Now you should be able to load this property class with:
<context:property-placeholder properties-ref="propertyInit"/>
Hope you like this idea. I used this approach in a previous project.
I want to give you first a strong warning on doing this. If you go down this path then you risk breaking your application in very strange ways because if any other components depend on this component you are having dynamic components on startup, you will break them, and you should think if there are other ways to achieve this behaviour instead of using properties.
That said the way to do this would be to use a proxy pattern, which is a proxy for the component you recreate whenever its properties are changed. So you will need to create a class which extends Circuit Breaker, which encapsulates and instance of Circuit Breaker which is recreated whenever its properties change. These properties must not be used outside of the proxy class as other components may read these properties at startup and then not refresh, you must keep this in mind that anything which might directly or indirectly access these properties cannot do so in their initialisation phase or your application will break.
It's worth taking a look at SpringCloudConfig which allows for you to have a properties server and then all your applications can hot-reload those properties at runtime when they change. Not sure if you can take that path in Mule if SpringCloud is supported yet but it's a nice thing to know exists.
Looking at Grails 3 documentation, the following is written about scopes:
prototype (default) - A new controller will be created for each request (recommended for actions as Closure properties)
The odd part here is that I get significantly different results in Grails 3.1.4 if I explicitly state:
static scope = "prototype"
Take for example the following UserController
class UserController {
def userService
List<String> users
def loadUsers() {
if (!users) {
println("########## have to load users");
try {
user = userService.getAllUsersInAd()
} catch (Exception e) {
// do something
}
} else {
println("########## dont have to do it " + users.size());
}
}
}
And the following UserService
class UserService {
def getAllUsersInAd() {
println("######### querying")
return new ArrayList<String>();
}
}
If static scope is omitted:
When I close a Firefox browser and re-open it, "dont have to do it is executed", regardless of how many times I close/reopen it. What is even more weird about this is that I can open a completely different browser (like chrome) when I close Firefox, and the same message executes. It is almost as if the scope of this controller is a similar one to #ApplicationScope of JSF.
After a good 5-10 mins of idle time, the query is executed again, but the scenario remains.
If static scope is stated:
After each browser closing, the "have to load users" is executed as expected.
My question is, is the documentation wrong for the default scope? If it is not, what is the difference between explicitly stating scope="prototype" and omitting it(aside from the obvious above) ?
In the default generated application.yml file for a Grails 3.1.4 app you should see a setting like this:
grails:
controllers:
defaultScope: singleton
That tells the framework to make controllers singleton. The default scope is prototype if that setting is not set.
Yes, I believe controllers were changed to singleton (application) scope by default a while ago (version 1.4.x as it happens). I'm trying to find documentation of that. It seems it was a JIRA issue fix, originally here, but Grails has moved away from JIRA, and didn't migrate all the bugs to GitHub.
You shouldn't have state in controllers anyway according to the Grails team:
Why does Grails recommend singleton scope for controllers with actions as methods?
See Burt's answer, and Jeff even speaks up in the comments.
EDIT: As Jeff says, the default is still prototype, but the default generated config changes them all to singleton, which is recommended.
I want to handle multiple events in one class, here's my example:
#Lazy(false)
#Component
public class EventListenerImpl {
#EventListener
public void handleContextRefreshedEvent(ContextRefreshedEvent event) {
LOGGER.log(event.getSource());
...
}
}
However this method is not being executed when my application starts.
In my applicationContext.xml I have:
<context:annotation-config/>
<context:component-scan base-package="..."/>
which should be enough for #EventListener to work, according to the documentation.
The old way of implementing ApplicationListener<ContextRefreshedEvent> works just fine.
I'm using Spring 4.2.4.RELEASE.
Alright, this remains a total mystery for me. I bet it's some kind of wierd maven/ide caching issue, but anyway this worked for me after several restarts :
#Lazy(false)
#Component
public class EventListenerImpl {
#EventListener
public void whatever(final ContextRefreshedEvent event) {
event.getSource();
}
}
What I found might explain what #moonlightcheese observed:
If the event is published early in the application's lifecycle, it is not sent to the annotated #EventListener method. If it is published later, it is sent to the method.
My work around was to ensure that the event is not published prior to the ContextRefreshedEvent. I had my publisher class implement ApplicationListener<ContextRefreshedEvent>, and published my event from the onApplicationEvent(ContextRefreshedEvent event) override. Similar strategies could be used where the onApplicationEvent(ContextRefreshedEvent event) override is used to gate publication.
It's possible that anything which changes the timing dynamics of the application startup could affect the behavior one way or the other.
I know this is an old question, and the answer is accepted, but I don't think it solves the problem. I had this exact same issue and was able to solve it by moving the event listener #EventListener containing class from the root of the base-scan package to a sub package of that package. For example:
<context:component-scan base-package="com.example"/>
Simply create a sub package (folder) under com.example and place the class in there:
com -> example -> foo (place class here)
This is what worked for me. No idea why it couldn't find the #EventListener in the base-package root, but anyway, it's fixed. This seems to be an undocumented issue in the docs.
I am trying out the ResourceProcessor interface in Spring Data REST. I don't think my Processor ever gets called. No error message either.
Here is my processor (in Groovy):
#Autowired
PersonService personService
#Override
public Resource<Person> process(Resource<Person> resource) {
resource.content.isAdult = personService.isAdult(resource.content)
// sanity check: does this link get added?? (NOPE!!)
resource.add(new Link("http://localhost:8080/people", "added-link"))
log.info "## resource.content.isAdult ==> ${resource.content}"
return resource
}
Any help would be most appreciated!! You can see the entire project here in GitHub: https://github.com/txiasummer/spring-data-rest-examples
Finally got it to work! It turns out to be something completely trivial and I can't believe I missed it. I have a PersonProcessor classes which implements Spring's native ResourceProcessor interface. But PersonProcessor is still just a basic class that must be injected by Spring!! I think I was getting it confused with #Projection, which will be recognized automatically and does not need to be injected explicitly.
I addd #ComponentScan to my Application.groovy and now everything is working swimmingly. Alternatively, you an also manually define the PersonProcessor class and its service PersonService class as #Bean in Application.groovy. Again, you can see the whole project here: https://github.com/txiasummer/spring-data-rest-examples
I have a JIRA plugin that I'm developing that has a REST service. That service should be able to accept POSTed requests, unmarshall some data and store it. The seemingly suggested way to do this in JIRA is to make use of the Bandana persistence framework. According to this page, I should be able to simply define a setter that Spring should call to give me my Bandana manager.
#Path("/path")
public class SCMService {
private BandanaManager bandanaManager;
// setter called by Spring
public void setBandanaManager(BandanaManager bandanaManager) {
this.bandanaManager = bandanaManager;
}
//...More methods...
}
However, when I test this, the setter is never being called and my manager is null. I'm guessing this should be as simple as registering this service with Spring for injection somehow but I can't seem to find anything like that.
How would I get my setter called? Is there a better way to do this?
Er, I'm not sure that JIRA uses Bandana in that way, though Confluence does. You can certainly post data to a JIRA rest resource and then store it using properties tables
Something like this:
#POST
#Consumes (MediaType.APPLICATION_XML)
public Response createComponentAndIssues(#Context HttpServletRequest request, ...