i have some hard task, i need to change some part of my project using jboss portal 2.7.2 into liferay. Ofc less change better but all jboss portal must disappear. I need 2 replace classes below. So my question is how using liferay portal implements(or not(if already exist)) listener which will know when someone is trying 2 log in. Make login possible without reloading etc. Ofc it was nice if there was some pro eventlistener in liferay which can recognise other events not only logging but i will be glad for all help. 4 the rest of this class will be nice if someone know replacment 4 them in liferay.
import org.jboss.portal.api.event.PortalEvent;
import org.jboss.portal.api.event.PortalEventContext;
import org.jboss.portal.api.event.PortalEventListener;
import org.jboss.portal.api.session.PortalSession;
import org.jboss.portal.api.user.event.UserAuthenticationEvent;
import org.jboss.portal.identity.IdentityException;
import org.jboss.portal.identity.NoSuchUserException;
import org.jboss.portal.identity.User;
import org.jboss.portal.identity.UserModule;
import org.jboss.portal.identity.UserProfileModule;
Liferay has similar approache. Create a Hook and add properties like http://www.liferay.com/documentation/liferay-portal/6.1/development/-/ai/extending-and-overriding-%3Cem%3Eportal-properties%3C-e-1
With the properties you can specificy wich class schould be call by the portal events:
login.events.post=my.package.AfterLoginHandler
with the same approche you can listen to creating/changes/removes of entities:
value.object.listener.com.liferay.portal.model.User=my.package.UserListener
value.object.listener.com.liferay.portal.model.Layout=my.package.LayoutListener
...
Liferay does allow adding handlers to login events. More information can be found # http://www.learnercorner.in/topics?showTopic=16001
Related
We have a spring boot application with REST interface and a web client. We are using spring-security with OAuth 2.0 JWT tokens for authentication. We are using slf4j and sleuth for logging. We want to log the currently logged-in user id in our logs. Technically, we want to add the user id to the Mapped Diagnostic Context (MDC) of our server application.
The goal is to link server side errors resulting from frontend operations to the user who has triggerend the backend operation.
At the moment, we extract the user id on the client side and send the id as HTTP header field to the server where it is extraced from the HTTP header as baggage by sleuth and added to the logs, see following spring.sleuth.baggage configuration. This is working.
spring.sleuth.baggage.remote-fields=user_id
spring.sleuth.baggage.tag-fields=user_id
spring.sleuth.baggage.correlation-fields=user_id
The user is logged by user=%X{user_id:-}, see the full log pattern:
logging:
level:
ROOT: WARN
pattern:
console: "[%d] [%t] %highlight(%-5p) %c{10} - %cyan([trace=%X{X-B3-TraceId:-} span=%X{X-B3-SpanId:-} user=%X{user_id:-}]) %m%n"
However, instead of extracting the user id on the client side and sending it to the backend, we want to directly extract the user id from the JWT token on the server side. Since all the information are also directly available on the server side.
I have checked spring-cloud-sleuth documentation how to set baggage fields in Java, but I couldn't figure out how to do it.
https://cloud.spring.io/spring-cloud-sleuth/reference/html/#java-configuration
https://docs.spring.io/spring-cloud-sleuth/docs/current-SNAPSHOT/reference/html/project-features.html#features-brave-baggage
https://docs.spring.io/spring-cloud-sleuth/docs/current-SNAPSHOT/reference/html/appendix.html#appendix
I did not know which classes to use and how to use them. I've tried the following code. The code is not executed at Spring startup. So, it seems some config is missing or the code is completely wrong.
package net.company.common.service;
import brave.baggage.BaggageField;
import brave.baggage.BaggagePropagation;
import brave.baggage.BaggagePropagationConfig;
import brave.baggage.BaggagePropagationCustomizer;
import brave.internal.baggage.BaggageContext;
import net.company.common.service.CommonServiceConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
#Configuration
#ComponentScan
#Import({CommonServiceConfig.class})
public class ServiceConfig {
#Bean
BaggagePropagationConfig.SingleBaggageField singleBaggageField() {
BaggagePropagationConfig.SingleBaggageField field = BaggagePropagationConfig.SingleBaggageField.newBuilder(BaggageField.create("user_id")).build();
field.field().updateValue("user_12345"); // set only dummy value for debug
return field;
}
}
It would be possible to implement such an MDC manually, see https://www.baeldung.com/mdc-in-log4j-2-logback. But as this is error prone we want to avoid it, e.g. context cleaning must be done right.
How can the user id from JWT be added to MDC using sleuth/brave for server side logging?
I was using
spring boot version: 2.1.2.RELEASE
spring cloud version: Greenwich.RELEASE
and you can configure with following properties
spring.sleuth.propagation-keys=user_id
spring.sleuth.log.slf4j.whitelisted-mdc-keys=user_id
Since you are using
spring.sleuth.baggage.remote-fields=user_id
and it's working for you, this is how to create and update the value of Baggage Fields.
BaggageField baggageField = BaggageField.create(baggageKey);
baggageField.updateValue(baggageValue);
Do note that updating baggage value this way will show up in the logs from the next span. In case you want to update the value in the same span have a look at this answer https://stackoverflow.com/a/67373784/2224254
You can get the principal (username in your case) from Spring Security like this (assuming you are using the JWT as it should be):
SecurityContextHolder.getContext().getAuthentication().getPrincipal()
After this, you can add it to the MDC or set as a baggage field/tag/etc:
// assuming username is setup in sleuth.baggage.remote-keys
BaggageField USERNAME = BaggageField.create("username");
USERNAME.updateValue(span.context(), String.valueOf(SecurityContextHolder.getContext().getAuthentication().getPrincipal()));
Tags.BAGGAGE_FIELD.tag(USERNAME, span);
Context: I need to provide a way to change parameter values during production on lower performance cost as possible.
Goal: I want change annotation values on fly and apply it at once on all microservices instances.
Personal background and limitations: I know I can use Spring Cloud Config to change parameters on the fly like explained in this article and I Know there is some challenges and pitfalls involved on changing annotations on the fly also like discussed in stackoveflow question.
I know that Spring Cloud Config can be used for setting up a centralized configuration applied to all microservice instances during boot/start. I have used it a bit. I am wondering if I can use it for centralizing parameters that can affect customized annotations on fly.
An imagined solution is:
... whenever I need somepRopertyValue
#Value("${config.somePropertyValue}")
private String somePropertyValue;
#Bean
public String somePropertyValue(){
return somePropertyValue;
}
A config client in all microservices endpoint that must be call not only when the application start but whenever somePropertyValue managed in Spring Cloud Config Server bootstrap.properties is updated:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#SpringBootApplication
public class SpringConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(SpringConfigClientApplication.class, args);
}
}
#RefreshScope
#RestController
class MessageRestController {
#Value("${server.somePropertyValue:Unable to connect to config server}")
private String somePropertyValue;
#RequestMapping("/server/somePropertyValue")
String getSomePropertyValue() {
return this.somePropertyValue;
}
}
And somehow somePropertyValue is maintened in Spring Cloud Config and if change during production time it affects on demand everywhere somePropertyValue is annoted in all microservice instances.
I am currently reaching this behaviour by adding a kafka consumer in all SpringBoot microservices that listen/observe a topic and when it receives a new messagge it changes on the fly the parameter value. It seems so odd that I created a Kafka dependency in all company microservices. Since I have used Spring Config for a bit similar scenario I am wondering if there is a better alternative using some out-of-box Spring approach. Also performance is highly important in my case and a bit delay on syncronize all parameters isn't an issue. By delay I mean that two or three seconds to update parameters in all microservices isn't an issue.
There are two ways to do that:
i- There's a refresh endpoint, and you can actually call that for a service, and it'll actually refresh its configurations without restarting itself, which is pretty neat. e.g. MS-A is listing on 8080 then do a POST request at this endpoint:
localhost:8080/refresh.
NOTE: Spring Actuator actually adds a RefreshEndpoint to the app automatically when we annotate a controller in MS-A with #RefreshScope.
ii- What you can also do is use Spring Cloud Bus, and broadcast an event, and then every service listens on that and refreshes itself. That's handy if you have dozens of services all using the Config Server, and you don't want to go one by one and hit a /refresh endpoint as we have did in 1st approach. You just want to broadcast a message to a bus and have all these things automatically pick it up.
Reference: Both concepts I've learnt while taking course at Pluralsight
I'm using Spring Boot 2.2.4 with embedded Undertow.
I've enabled the access log using server.underdow.accesslog.enabled=true and everything works as expected.
I'm utilizing the actuator endpoints on a different port which sets up a child context. I do not want requests to the actuator to be logged. Currently they automatically go to management_access.log where access. is the prefix of my main access log.
Any ideas on how to disable that access log? I know Spring is creating a separate WebServer via Factory for the actuator context, but I haven't found a way to customize the factory.
I found my own answer (spent way too much time doing it).
It's a little bit of a hack, but it works:
New configuration class: foo.ManagementConfig
package foo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
#ManagementContextConfiguration
public class ManagementConfig {
#Bean
WebServerFactoryCustomizer<UndertowServletWebServerFactory> actuatorCustomizer(#Value("${management.server.port}") int managementPort) {
return factory -> {
if (managementPort == factory.getPort()) {
factory.setAccessLogEnabled(false);
}
};
}
}
Created resources/META-INF/spring.factories so that it gets picked up by the ManagementContext:
org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration=foo.ManagementConfig
The part that's a bit of a hack is the if statement. It would have been great if it applied only to the management context, but for some reason it's trying to apply to both. With the if statement, it just doesn't do anything for the primary context.
This would have unintended consequences if management.server.port was undefined or if it was the same as the primary context.
Does MaterialModule in Angular Material 2 include Http providers by default?
I have created a service that injects Http from #angular/http. If I omit to import HttpModule in the main AppModule, there is no error and everything works as expected. If on the contrary, I remove the import of MaterialModule, then I get the error that there is no provider for Http.
Since I import the whole MaterialModule, I can see that this is due to the automatic import of MdIconModule. It uses HttpModule internally in order to fetch Material Design icons.
Could everyone show me a tutorial on how to make Spring 3.1.1 running on Google App Engine, please?
I've followed severals tutorial and managed to get the dead simple HelloWorld example to work on App Engine. However, when I go futher, I stuck at the persistent process between Spring and Datastore. I looked at this thread Configuring JDO in Spring 3.1?, too, but it works on localhost but it doesn't work when I deploy to app engine due to the javax.naming.NamingException.
Therefore, I'm looking for a not-too-simple tutorial that covers basic aspects of a real life application such as the view, the model and the database.
Jappstart is a good place to see a working example of GAE that uses Spring and the Datastore (via JPA) and is also a good starting point for building a basic GAE/J app.
Having spent about a day trying to make this work, I thought I'd add some additional useful information here. First take a look at this project https://github.com/hleinone/spring-gae-jdo and this issue: http://code.google.com/p/googleappengine/issues/detail?id=1240 -- comment 24 is the useful one.
In case anyone wants to get this working with annotation-driven configuration, here's how I did it:
package com.domain.yourcode.configuration;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jdo.GAETransactionAwarePersistenceManagerFactoryProxy;
import org.springframework.orm.jdo.JdoTransactionManager;
//import org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy;
#Configuration
public class JDOConfiguration {
private static final PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory("transactions-optional");
#Bean
public GAETransactionAwarePersistenceManagerFactoryProxy proxyPmf() {
GAETransactionAwarePersistenceManagerFactoryProxy proxy =
new GAETransactionAwarePersistenceManagerFactoryProxy();
proxy.setTargetPersistenceManagerFactory(pmf);
proxy.setAllowCreate(false);
return proxy;
}
#Bean
public JdoTransactionManager transactionManager() {
JdoTransactionManager mgr = new JdoTransactionManager();
mgr.setPersistenceManagerFactory(pmf);
return mgr;
}
}
You'll still want <tx:annotation-driven/> in your applicationContext.xml