Can I access the current user in session statically in Quarkus? - security

I need to do access to the current user (previously set up by a ContainerRequestFilter) in a static way, to avoid the passage of the #Context SecurityContext in every method of every controller.
I want to achieve something that, in Spring, I would do with
SecurityContextHolder.getContext().getAuthentication();
Is there any way to do it, besides using Spring Security in Quarkus?

The solution is to use this dependency
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
Then you can manipulate the instance of SecurityIdentity to "make it static"
#Startup
#ApplicationScoped
public class UserUtilsService {
#Inject
private SecurityIdentity securityIdentity;
private static SecurityIdentity instance;
/**
* Gets the custom user.
*
* #return the custom user
*/
public static CustomUser getCustomUser() {
return (CustomUser) instance.getPrincipal();
}
#PostConstruct
private void setUp() {
instance = this.securityIdentity;
}
}
#StartUp does instantiate the bean on application start (instead of lazily).
You can then access to the Principal statically using UserUtilsService.getCustomUser();

Related

Inject different implementations based on application property in Quarkus

I have a Repository interface that has two implementations. One reads data from a locally stored CSV file while the other reads from an Amazon Dynamo DB. I would like to be able to switch between which implementation I'm using based on an application property or custom build profile. I would normally use a Factory to retrieve the correct class at runtime, but I would like to do this with injection if possible.
I found a similar question using Spring boot but couldn't find an equivalent that would work in Quarkus Spring choose bean implementation at runtime
I also tried implementing a Configuration class similar to what is found in the docs here but again didn't have much luck. https://quarkus.io/guides/cdi-reference#default_beans
It feels like I'm missing something obvious so any pointers would be much appreciated.
Here is a simple example of my classes:
#ApplicationScoped
public class ExampleService {
#Inject
ExampleRepository repository;
public List<Data> retrieveData() {
return repository.retrieveData();
}
}
public interface ExampleRepository {
List<Data> retrieveData();
}
#ApplicationScoped
public class DynamoRepository implements ExampleRepository {
#Override
public List<Data> retrieveData() {
//Get Data from DynamoDb
}
}
#ApplicationScoped
public class CsvRepository implements ExampleRepository {
#Inject
CsvBeanHandler csvBeanHandler;
#Inject
LocalFileReader fileReader;
#Override
public List<Data> retrieveData() {
// Get data from CSV
}
}
I currently also have the following in my application.yml:
com:
example:
application:
storage-type: 'CSV' # OR AMAZON_DYNAMO_DB
It looks like they've added this directly to the documentation:
https://quarkus.io/guides/cdi-reference#declaratively-choose-beans-that-can-be-obtained-by-programmatic-lookup
I feel a bit guilty pasting this much, but it's the SO way.
I can add that it is NOT like a Guice 'binding'; BOTH classes will be instantiated, but only one will be injected. Also unlike Guice, you cannot inject the interface (or I did it wrong) - you have to do what's shown below, with Instance.
Personally I just use constructor injection and then drop the value of the Instance wrapper into a final field, so I'm not crying about the extra step. I do miss the power and explicit bindings possible with Modules ala Guice, but the simplicity here has its own value.
5.16. Declaratively Choose Beans That Can Be Obtained by Programmatic Lookup
It is sometimes useful to narrow down the set of beans that can be
obtained by programmatic lookup via javax.enterprise.inject.Instance.
Typically, a user needs to choose the appropriate implementation of an
interface based on a runtime configuration property.
Imagine that we have two beans implementing the interface
org.acme.Service. You can’t inject the org.acme.Service directly
unless your implementations declare a CDI qualifier. However, you can
inject the Instance instead, then iterate over all
implementations and choose the correct one manually. Alternatively,
you can use the #LookupIfProperty and #LookupUnlessProperty
annotations. #LookupIfProperty indicates that a bean should only be
obtained if a runtime configuration property matches the provided
value. #LookupUnlessProperty, on the other hand, indicates that a bean
should only be obtained if a runtime configuration property does not
match the provided value.
#LookupIfProperty Example
interface Service {
String name();
}
#LookupIfProperty(name = "service.foo.enabled", stringValue = "true")
#ApplicationScoped
class ServiceFoo implements Service {
public String name() {
return "foo";
}
}
#ApplicationScoped
class ServiceBar implements Service {
public String name() {
return "bar";
}
}
#ApplicationScoped
class Client {
#Inject
Instance<Service> service;
void printServiceName() {
// This will print "bar" if the property "service.foo.enabled" is NOT set to "true"
// If "service.foo.enabled" is set to "true" then service.get() would result in an AmbiguousResolutionException
System.out.println(service.get().name());
}
}
If your request is to bind at startup time the right implementation based on a configuration property, I suppose your problem may be resolved used #Produces annotation:
public class ExampleRepositoryFactory {
#Config("storage-type")
String storageType;
#Produces
public ExampleRepository dynamoInstance() {
return storageType == "CSV" ? new CsvRepository() : new DynamoRepository();
}
}

How to use JAXB with PropertyChangeSupport?

I am trying to use JAXB in an Eclipse project. View widgets are bound to model attributes with java.beans.PropertyChangeSupport. This works fine. I want to also bind model attributes to a persistent XML representation on disk with JAXB. I can marshal important state to XML and can unmarshal that back into a pojo/bean thing at runtime but am not sure how best to proceed.
The bean setters bound to my view widgets need to firePropertyChange() but XJC generates only simple setters, this.value = value.
XJC properties are protected, so it looks like I could override its setters to firePropertyChange(), but I don't know how my overriding subclass could have its unmarshaled superclass magically change state at runtime (like when user requests report for different year which is when I would unmarshal a different XML file).
Is there an example or pattern for doing this? Surely it is not new. Many thanks. -d
#Adam Thanks! I grokked a workable solution with this:
public class MyBean extends JaxBean {
public JaxBean getJaxBean() {
return this;
}
public void setJaxBean(JaxBean jaxBean) {
super.setThis(jaxBean.getThis());
super.setThat(jaxBean.getThat());
// etc...
}
public MyBean() {
// etc...
}
}
I think my confusion was thinking the unmarshalled bean would somehow magically replace my working instance. The solution above requires additional text but it works and the use of JaxBean's dumb setters avoids firing events unnecessarily when loading a new XML.
Your solution, annotating MyBean with JAXB and using schemagen, sounds even better. I will try that next go around. These are very nice technologies. -d
I mentioned another approach to your application in my comment.
It's what we use in our RCP application. Except that we marshall/unmarshall through network thus we use JAXWS and not just JAXB.
I'm somewhat experienced with this kind of stack, so here's a kick-starter for you:
/**
* Your UI POJO-s should extend this class.
*/
public abstract class UIModel<T extends UIModel> {
protected final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
/**
* This comes handy at times
*/
public void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
//....
}
/**
* And this too, trust me.
*/
public void deepCopy(final T of) {
removePropertyChangeListener(propertyChangeListener);
//It's from Spring Framework but you can write your own. Spring is a fat-ass payload for a Java-SE application.
BeanUtils.copyProperties(of, this, IGNORED_ON_CLIENT);
addPropertyChangeListener(propertyChangeListener);
}
}
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
}
/**
* Example of a UI POJO.
*/
public class Car extends UIModel<Car> {
private String make;
private int numberOfWheels;
//... etc.
/**
* Example of a setter
*/
public void setMake(String make) {
propertyChangeSupport.firePropertyChange("make", this.make, this.make = make);
}
public String getMake() {
return make;
}
//... etc.
}
I don't know how often your Schema-definition changes but there's a pattern supporting this;
/**
* New application (compiled with the class below) can open a file saved by the old application.
*/
public class Car2 extends Car {
private String fuelType; // Example of a new field
public void setFuelType(String fuelType) {
propertyChangeSupport.firePropertyChange("fuelType", this.fuelType, this.fuelType = fuelType);
}
//... etc.
}
This way the old application can open XML-outputs of the new. Dropping a field from such a class's source code will result in a RuntimeException as JAXB is still looking for it.
If you're clients are always up-to-date then you should not care about this at all.
When tackling with Java collections and subclassing excessively you will run into JAXB problems which you can solve by Googling #XmlRootElement and #XmlSeeAlso annotations.
Comments don't format, trying "answer". Need to do the stackoverflow tour. Continuing,
Thanks, Adam, I will bookmark these for future reference. They look similar to my example, the pattern is (unmarshal New, be quiet, copy New to Old, be noisy). I like the mind-bending recursion,
class UIModel<T extends UIModel>
class Car extends UIModel<Car>
and assume you've tested it compiles. ;)
Regards, -d.

spring: share value between annotated beans like jsf applicationscope

I am working on a project with jsf 2.2 on the web side and spring 4 on the business side. I have a web filter which receives a parameter from the request url. From this parameter I have to connect to a database. There are cases where there are different databases possible, so depending on the parameter I have to initiate a different database connection. The web filter looks like this:
#Component
public final class SecurityFilter implements Filter
{
#Autowired
private CommonEao commonEao;
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest)request;
String instance = req.getParameter("instance");
//I would like to have something here like:
// springContext.addParameter("instance", instance);
String company = req.getParameter("company");
commonEao.getConfiguration(company);
... Do stuff
}
}
How does it works? The commonEao contains methods to make queries to the database (JPA/Eclipselink...). At initialization, no entityManager is present in commonEao since it is injected in SecurityFilter before the doFilter is executed when an url is requested. After the url is requested, the instance of the database to use is known through the 'instance' request parameter.
When the method commonEao.getConfiguration(company) is invoked, the first thing that should happen is to create an entity Manager:
#Repository
public final class CommonEao extends AbstractEao
{
public final void getConfiguration(final String company)
{
if (entityManager == null)
{
//I would like to have something here like:
// String instance = springContext.getParameter("instance");
createEntityManager(instance);
}
else ...
}
}
As you can see, when the first time the url is requested, no entityManager exists and it needs to be created based on the instance name provided by the request. Based on the instance name the properties files containing database connection parameters will be used the call the Persistence.createEntityManagerFactory functionality... etc etc... :)
What is the idea? The idea that I had, as you can see in my comments, is to put a parameter in some global context/container that is available for all Spring beans. This idea comes from the JSF world, where you can create a managed bean, annotate it with applicationscope, define a variable in it, and access this variable from any jsf managed bean through injecting the application scoped bean with the managedproperty annotation:
#ManagedBean
public final class SomeJsfBean
{
#ManagedProperty(value = "#{applicationBean}")
private ApplicationBean applicationBean;
private void method()
{
applicationBean.setInstanceName("instance");
}
}
#ManagedBean
public final class AnotherJsfBean
{
#ManagedProperty(value = "#{applicationBean}")
private ApplicationBean applicationBean;
private void method()
{
String instance = applicationBean.getInstanceName();
}
}
I have some restrictions though. I want to use a global object of Spring. I don't have any XML config in my project. Spring is configured like this and nothing more:
#Configuration
#ComponentScan(value = { "megan.fox.is.hot", "as.is.lindsay.lohan" })
public class SpringConfiguration
{
}
I have looked in many places, something I found was fetching a property from PropertyPlaceholderConfigurer and stuff like that, but I didn't understand how it works and mainly it looks way too complex for what i need: just sharing one variable.
There must be an easy solution like in the JSF world, but i suspect i am looking for the wrong name in the Spring world! :)
Any help is greatly appreciated, this is the last thing I need to fix in my project!

i want to launch a class method periodically using spring

i have the following code.
#Configuration
#EnableAsync
#EnableScheduling
public class AsyncConfiguration implements AsyncConfigurer {
#Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(10000);
executor.setThreadNamePrefix("Executor-");
executor.initialize();
return executor;
}
}
and if i want to run the recommend method after every certain interval of time. What can be the java spring bean configuration way to do that.?
public class UserBrandsRecommender {
public List<RecommendedItem> recommend(Long userId, int number) throws TasteException{
}
}
You should look into the #Scheduled annotation. For example:
#Scheduled(fixedDelay=5000)
public void doSomething() {
// something that should execute periodically
}
You'll probably need to create a new Spring bean with a method similar to above. The bean could have the UserBrandsRecommender injected into it. The new bean will need to implement some logic to pass proper values for the "userId" and "number" parameters to the "recommend" method.
More information here:
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/htmlsingle/#scheduling-annotation-support

How to use MyBatis with CDI

I am writing a web application and I am using MyBatis framework for persistence. I want to use CDI to inject the mappers easily and to manage the transaction declaratively.
MyBatis has official CDI support:
Mapper declaration:
#Mapper
public interface UserMapper {
#Select("SELECT * FROM users WHERE id = #{userId}")
User getUser(#Param("userId") String userId);
}
Mapper Usage:
public class MyService {
#Inject UserMapper userMapper;
public User doSomeStuff(String userId) {
return this.userMapper.getUser(userId);
}
}
More information in docs: http://mybatis.org/cdi/

Resources