I have a question with respect to Liferay Startup Events.
In Liferay documentation it is given:
Startup Events
Input a list of comma delimited class names that extend com.liferay.portal.struts.SimpleAction. These classes will run at the specified event.
Could anybody please tell me what is the difference between global.startup.events and application.startup.events and could any body tell me in what case do we need to override them?
And should both these start up events extend com.liferay.portal.struts.SimpleAction?? and I couldn't find anything inside the SimpleAction except this:
public abstract class SimpleAction {
public abstract void run(String[] ids) throws ActionException;
}
}
I also wanted to know this class contains nothing, how does Liferay knows what XML files to read and process?
Thanks
global.startup.events - run once for global server
application.startup.events - run for every portal instance at startup. If you have one portal instance at your server (normal case) - here is no difference between this properties. I use application.startup.events.
Extend the com.liferay.portal.kernel.events.SimpleAction class and impliment run-methode, that will call by liferay startup. For this purpose create a hook plugin and register in liferay-hook.xml the property file, e.g.:
<hook>
<portal-properties>portal-myext.properties</portal-properties>
</hook>
Create portal-myext.properties in classpath and set your startup action:
application.startup.events=com.my.actions.MyStartupAction
The action MyStartupAction must be in the same classpath, hence same hook-plugin.
Related
I would like to set bootstrap.yaml property aws.paramstore.prefix programmatically.
According to the documentation the only way to configure it is via bootstrap.yaml file. And it works fine if I define aws.paramstore.prefix in the bootstrap.yaml file. However, I would like to do that programmatically.
There is also a possibility to customize bootstrap property sources, however this does not solve the problem. Custom Bootstrap seem to be loaded later than aws.paramstore properties.
As far as I can see the aws.paramstore properties are loaded very early on using spring.factories that are defined in spring-cloud-starter-aws-parameter-store-config dependency:
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.aws.autoconfigure.paramstore.AwsParamStoreBootstrapConfiguration
And in AwsParamStoreBootstrapConfiguration constructor AwsParamStoreProperties is passed as an argument, which is instantiated via #ConfigurationProperties. That is aws.paramstore are loaded very early on.
You can try to look into PostProcessors that executed on the very first stages of Spring Context initialization. For example, EnvironmentPostProcessor. It executes quite early and probably can help you to manage some properties/modify files before they will be loaded to context.
Note: if you want to use this code in some library that will be a part of another project, you should add such PostProcessor to spring.factories file. In other case it won't be added to configuration stage of another Spring.
A hacky workaround is to set the aws.paramstore.prefix property before calling SpringApplication#run method.
Say we want to set aws.paramstore.prefix to the value of a Spring profile that is being passed to the application. Then one can do something like:
public static void main(String[] args) {
// or System.getenv("SPRING_PROFILES_ACTIVE")
// or some additional logic that filters a profile that is being passed to the application
// note that application can also have multiple profiles
String activeProfile = System.getProperty("spring.profiles.active");
System.setProperty("aws.paramstore.prefix", activeProfile);
SpringApplication.run(MyApplication.class, args);
}
In this way we "guarantee" that aws.paramstore.prefix is available before ane bootstraps from spring.factories kicks in.
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.
I am currently deploying my custom controls as OSGi plugins and I wanted to do the same thing with my beans. I have tried putting them into the OSGi plugin and it works fine but the only problem I have is the faces-config.
It seems it has to be called faces-config in the OSGi plugin to work but that means i can't use beans in the NSF anymore because it seems to ignore the local faces-config.
Is there a way to change the name of the faces-config in the OSGi plugin?
Something like FEATURE-faces-config.xml?
In the class in your plugin that extends AbstractXspLibrary, you can override "getFacesConfigFiles", which should return an array of strings representing paths within the plugin to additional files of any name to load as faces-config additions. For example:
#Override
public String[] getFacesConfigFiles() {
return new String[] {
"com/example/config/beans.xml"
};
}
Then you can put the config file in that path within your Java source folder (or another folder that is included in build.properties) and it will be loaded in addition to your app's normal faces-config, beans and all.
The NSFs are running as separate, distinct Java applications. The OSGi plugin is running in the OSGi layer, above all those distinct Java applications, as a single code base. Consequently, the faces-config is only at that level.
It's possible to load them dynamically, by using an ImplicitObjectFactory, loaded from an XspContributor. That's what is done in OpenNTF Domino API for e.g. userScope (which is a bean stored in applicationScope of an NSF). See org.openntf.domino.xsp.helpers.OpenntfDominoImplicitObjectFactory, which is referenced in OpenntfDominoXspContributor, loaded via the extension point of type "com.ibm.xsp.library.Contributor".
A few caveats:
You have no control over what happens if you try to register your bean with a name the developer also uses for a different variable in that scope.
Unless you add code to check if the library is enabled, as we do, you'll be adding the bean to every database on the server.
You still need to add the library to the NSF. Unless you also provide a component that those databases will all use, there's no way you can programmatically add it, as far as I know.
It might be easier to skip the bean approach and just add an instance of the Java class in beforePageLoad, page controller class, or however you're managing the backing to the relevant XPage (if viewScope) or application (if sessionScope / applicationScope).
My application is trying to externalize all project properties, some ones will be inside my app and another ones will be in a folder somewhere in Windows.
I set up Spring to execute this way: --spring.config.location=file:///C:\Temp\config\application.properties,classpath:application.properties
As you can see, if the same property exists in both sides, application property will be kept (priority order). I noticed for example some properties such as "server.port" can be found if exists outside folder (file://) but if I create one such "common.acronym-name" my project can not find its value.
Why "server.port" has a different behaviour that one create by me? Is there any configuration I need to tell Spring Boot to see this external property in my project?
#Value("${common.acronym-name:}") //Just find it in application classpath
private String acronymEnv;
Thanks!
To simulate this error, just create a class to handle the banner, for example:
#Component
public class ShowBanner {
#Value("${spring.main.show-banner:}")
private String showBanner;
#PostConstruct
public void init() {
System.out.println(showBanner);
}
}
In this code if you set at external property file the property "spring.main.show-banner=false" the banner still shows in console if it is set before server section. When the banner should not appear. Because the property returns empty.
If I move the property after server section the banner disappears, because return false value as expected.
Keep in mind my application.properties project is empty.
By the way, Even running via Eclipse or java console it happens:
java -jar sample-1.2.3.RELEASE.jar --spring.config.location=file:///C:\Temp\config\application.properties,application.properties
Why?
Believe or not, the order of properties makes difference for external properties be found.
If I set this below order where "spring.main.show_banner" is the first one at the top, my properties can not be found. For example:
spring.main.show-banner=false
server.port=9043
server.session-timeout=1800
server.ssl.key-store=file:///C:/Temp/config/localhost.jks
server.ssl.key-store-password=localhost
server.ssl.key-password=localhost
So, If change to below order, everything works fine:
server.port=9043
server.session-timeout=1800
server.ssl.key-store=file:///C:/Temp/config/localhost.jks
server.ssl.key-store-password=localhost
server.ssl.key-password=localhost
spring.main.show-banner=false
Is there any reason for it? Spring Boot needs to have the properties in right order? Seems the "server" section must the first one in the properties.
thanks.
I'm trying to get myself familiar with MVC3 and autofac but I've encountered small problem that I'm having trouble resolving.
I am using autofac integrated with MVC3 and all works well, pages are loading correctly, dependencies are being injected and that's cool. What's bugging me is how to use autofac's Container or MVC's DependencyResover in class library project.
I'm trying to create static class that will help me handle domain events. I simply want to be able to call the method with event parameter and everything should be handeled by this class. Here is code:
public static IContainer Container { get; set; }
public static void Raise<T>(T e) where T : IDomainEvent
{
foreach (var eventHandler in DomainEventManager.Container.Resolve<IEnumerable<EventHandlers.Handles<T>>>())
{
eventHandler.Handle(e);
}
}
As you can see it's pretty straightforward and everything would work great if it wasn't MVC approach. Some of my dependencies are registeres as InstancePerHttpRequest (NHibernate' session), while other are registered as InstancePerDependency or SingleInstance. Thus when I try to use container created in my UI project, I get exception that there is no httpRequest tag available.
How can i reuse the Container created in web project to get access to all of it's features, including InstancePerHttpRequest and httpRequest tag?
Or maybe there is other solution to my problem? I was thinking about using delegate function to obtain event handlers, but I cannot (can I?) create generic delegate that I would not need to initialize with concrete type at time of assignment.
Why I want to do this using static class is basically every entity and aggregate or service needs to be able to raise domain event. Injecting EventManager into every one of these would be troublesome and static class is exactly what would resolve all my problems.
If anyone could help me get my head around it I would be grateful.
Cheers, Pako
You shouldn't be referencing your container directly from your app code. This looks like the Service Locator anti-pattern. The correct action is to pass your objects the services they need to do their jobs, usually done through constructor parameters. BUT... if you are going to insist on depending on a global static, then at least model EventManager as a singleton, such that usage would look like:
EventManager.Current.Raise<SomeEvent>(someObject);
and then you can set EventManager.Current equal to a properly constructed instance when your app is initialized.