I try to use dependency injection in DropWizard with Google Guice but I have a lot of problems. So I programmed a simple code like below to find the main problem. The errors are in the class Test, line :testservice.Result (10,10,10).
- Syntax error on token "(", { expected after this token
- Syntax error on tokens, ConstructorHeaderName expected
instead
- Syntax error on token "Result", invalid AnnotationName
why I can't use the object testservice ?
Thanks for your help.
package dropwizard.GoogleGuiiice;
import io.dropwizard.Application;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
public class GoogleGuiiiceApplication extends Application<GoogleGuiiiceConfiguration> {
public static void main(final String[] args) throws Exception {
new GoogleGuiiiceApplication().run(args);
}
#Override
public String getName() {
return "GoogleGuiiice";
}
#Override
public void initialize(final Bootstrap<GoogleGuiiiceConfiguration> bootstrap) {
// TODO: application initialization
}
#Override
public void run(final GoogleGuiiiceConfiguration configuration,
final Environment environment) {
// TODO: implement application
environment.jersey().register(new Test ());
}
}
import com.google.inject.Guice;
import com.google.inject.Injector;
public class Test {
Injector guice=Guice.createInjector(new OperationModule());
TestService testservice=guice.getInstance(TestService.class);
testservice.Result (10,10,10);
}
public interface Operation {
int getResult(int a, int b);
}
public class Somme implements Operation{
#Override
public int getResult(int a, int b){
return a+b;
}
}
public class OperationModule extends com.google.inject.AbstractModule{
#Override
protected void configure(){
bind(Operation.class).to(Somme.class);
}
}
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import com.google.inject.Inject;
public class TestService {
#Inject
Operation Op;
#GET
#Path("{a}/{b}")
public int Result (int c, #PathParam(value="a")int a, #PathParam(value="b")int b){
int SommeFinale=c + Op.getResult(a,b);
return SommeFinale;
}
}
It is not clear to me what you are actually attempting to do here but to answer your question from a purely Java perspective the syntax error is simply because you are not allowed to execute arbitrary statements at that point in your code.
If you really do wish to execute that statement at that point then you either need to wrap it in curly braces so that it is in an initializer block but this would likely be pointless given the implementation as the result is thrown away
{
testService.Result(10,10,10);
}
or you need to assign the result to a field
int useMe = testService.Result(10,10,10);
Other options are that you could execute the statement in a constructor or method of the Test class.
I hope this tutorial can help.
Dropwizard and Guice Integration
Related
I need a static mechanism to verify my sender knows a static token. That token is hard coded into the sending system.
My API has an endpoint /webhook where I need to have that be verified.
This guides/security-customization gives an example on how to implement a custom mechanism, so I implemented this:
#Singleton
public class FixedTokenAuthenticationMechanism implements HttpAuthenticationMechanism {
#Override
public Uni<SecurityIdentity> authenticate(RoutingContext context, IdentityProviderManager identityProviderManager) {
String authHeader = context.request().headers().get("magic_header");
if (authHeader == "magic_value")
{
return Uni.createFrom().optional(Optional.empty());
}
else
{
return Uni.createFrom().optional(Optional.empty());
}
}
#Override
public Uni<ChallengeData> getChallenge(RoutingContext context) {
return null;
}
#Override
public Set<Class<? extends AuthenticationRequest>> getCredentialTypes() {
return Collections.singleton(AuthenticationRequest.class);
}
#Override
public Uni<Boolean> sendChallenge(RoutingContext context) {
return HttpAuthenticationMechanism.super.sendChallenge(context);
}
#Override
public HttpCredentialTransport getCredentialTransport() {
return HttpAuthenticationMechanism.super.getCredentialTransport();
}
#Override
public Uni<HttpCredentialTransport> getCredentialTransport(RoutingContext context) {
return HttpAuthenticationMechanism.super.getCredentialTransport(context);
}
#Override
public int getPriority() {
return HttpAuthenticationMechanism.super.getPriority();
}
}
I do not know how to configure this to be used in the application properties.
There seems to be a configuration for path-specific-authentication-mechanisms which I can not seem to make work.
what would I need to configure in aplication.properties to use my not so secure security mechanism for the /webhook endpoint?
Right now this implementation is incomplete, but as far as path-based authentication is concerned, you need to have an alias like webhook that you can refer to from the configuration, see https://github.com/quarkusio/quarkus/blob/main/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/BasicAuthenticationMechanism.java#L198 (note, basic is a qualifier) as well the rest of the class on how to implement the custom mechanism. Delegating to the default interface implementation will likely not work
User: Sergey Beryozkin got me on the right Track.
package org.eon.webhookingestor.receiver;
import io.quarkus.arc.Priority;
import io.quarkus.oidc.IdTokenCredential;
import io.quarkus.security.AuthenticationFailedException;
import io.quarkus.security.identity.IdentityProviderManager;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.identity.request.AuthenticationRequest;
import io.quarkus.security.identity.request.TokenAuthenticationRequest;
import io.quarkus.security.runtime.QuarkusPrincipal;
import io.quarkus.security.runtime.QuarkusSecurityIdentity;
import io.quarkus.vertx.http.runtime.security.ChallengeData;
import io.quarkus.vertx.http.runtime.security.HttpAuthenticationMechanism;
import io.quarkus.vertx.http.runtime.security.HttpCredentialTransport;
import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;
import javax.enterprise.inject.Alternative;
import javax.inject.Singleton;
import java.util.Collections;
import java.util.Set;
#Alternative
#Singleton
#Priority(900)
public class MagicAuthenticationMechanism implements HttpAuthenticationMechanism {
//related docs:
// https://quarkus.io/guides/security#security-architecture
// https://quarkus.io/guides/security-customization
//related so: https://stackoverflow.com/questions/73120309/quarkus-returning-empty-body-response-for-unauthorize
// related on so:
// https://stackoverflow.com/questions/74384603/how-to-configure-a-quarkus-custom-httpauthenticationmechanism
// https://stackoverflow.com/questions/73120309/quarkus-returning-empty-body-response-for-unauthorize
#Override
public Uni<SecurityIdentity> authenticate(RoutingContext context, IdentityProviderManager identityProviderManager) {
String magic_key = "magic_header";
String header_value = context.request().headers().get(magic_key);
String magic_value = "magic_value";
if ( !magic_value.equals(header_value))
{
return Uni.createFrom().failure(new AuthenticationFailedException());
}
return Uni.createFrom().item(
QuarkusSecurityIdentity.builder()
.setPrincipal(new QuarkusPrincipal(magic_key))
.addCredential(new IdTokenCredential(header_value))
.build());
}
#Override
public Uni<ChallengeData> getChallenge(RoutingContext context) {
//https://quarkus.io/guides/security-customization#dealing-with-more-than-one-httpauthenticationmechanism
//If no credentials are provided then the mechanism specific challenge is created
throw new RuntimeException ("no credentials were provided");
}
#Override
public Set<Class<? extends AuthenticationRequest>> getCredentialTypes() {
//needs to inherit from io.quarkus.security.identity.request.AuthenticationRequest
return Collections.singleton(TokenAuthenticationRequest.class);
}
#Override
public Uni<Boolean> sendChallenge(RoutingContext context) {
// a failed authentication will check if a challenge should be sent
return Uni.createFrom().item(Boolean.FALSE);
}
#Override
public Uni<HttpCredentialTransport> getCredentialTransport(RoutingContext context) {
return Uni.createFrom().item(new HttpCredentialTransport(HttpCredentialTransport.Type.OTHER_HEADER, "magic"));
}
#Override
public int getPriority() {
return 900;
}
}
with the configuration:
quarkus.http.auth.permission.magic.paths=/webhook
quarkus.http.auth.permission.magic.policy=authenticated
quarkus.http.auth.permission.magic.auth-mechanism=magic
Results in a magic authentication that works on my machine.
At this point I would advice against implementing and using it since the quarkus authentication is entirely unpredictable to me and maybe you if you read this post.
Excessive Testing of all endpoints is advised.
I'm trying to make an pointcut of type #Around to intercept all methods of beans annotated with #Repository.
I've tried
#Around("execution(* (#org.springframework.stereotype.Repository *).*(..))")
public void aspect() {
}
Also(should be same)
#Around("#within(org.springframework.stereotype.Repository)")
public void aspect() {
}
From my testing, these poincut expressions match just the methods from the type directly annotated(not the ones inherited like the ones autogenerated DAO (findAll, findById). I want to intercept all methods (from child type annotated and also inherited methods from other types like CrudRepository.
One of usages is this
#org.springframework.stereotype.Repository
public interface SubRepository extends CrudRepository {
}
How could i implement this or it is not possible?. Thank you.
Here is an MCVE. Next time, please provide one by yourself. It should not be my job to do that for you.
Interface + sub-interface:
package de.scrum_master.spring.q70824392;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface SubRepository extends CrudRepository {
String greet(String who);
}
package de.scrum_master.spring.q70824392;
public interface SubSubRepository extends SubRepository {
int add(int a, int b);
}
Abstract class extending sub-interface + concrete class extending it:
package de.scrum_master.spring.q70824392;
import java.util.Optional;
public abstract class MyAbstractRepository implements SubSubRepository {
#Override public Object save(Object entity) { return null; }
#Override public Iterable saveAll(Iterable entities) { return null; }
#Override public Optional findById(Object o) { return Optional.empty(); }
#Override public boolean existsById(Object o) { return false; }
#Override public Iterable findAll() { return null; }
#Override public Iterable findAllById(Iterable iterable) { return null; }
#Override public long count() { return 0; }
#Override public void deleteById(Object o) {}
#Override public void delete(Object entity) {}
#Override public void deleteAllById(Iterable iterable) {}
#Override public void deleteAll(Iterable entities) {}
#Override public void deleteAll() {}
}
package de.scrum_master.spring.q70824392;
import org.springframework.stereotype.Component;
#Component
public class MyRepository extends MyAbstractRepository {
#Override
public String greet(String who) {
return "Hello " + who;
}
#Override
public int add(int a, int b) {
return a + b;
}
}
Class directly annotated with #Repository as a counter-example:
package de.scrum_master.spring.q70824392;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import java.util.Optional;
#Component
#Repository
public class DirectlyAnnotatedRepository implements CrudRepository {
public void doSomething() {}
#Override public Object save(Object entity) { return null; }
#Override public Iterable saveAll(Iterable entities) { return null; }
#Override public Optional findById(Object o) { return Optional.empty(); }
#Override public boolean existsById(Object o) { return false; }
#Override public Iterable findAll() { return null; }
#Override public Iterable findAllById(Iterable iterable) { return null; }
#Override public long count() { return 0; }
#Override public void deleteById(Object o) {}
#Override public void delete(Object entity) {}
#Override public void deleteAllById(Iterable iterable) {}
#Override public void deleteAll(Iterable entities) {}
#Override public void deleteAll() {}
}
Demo application:
package de.scrum_master.spring.q70824392;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
#SpringBootApplication
#Configuration
public class DemoApplication {
public static void main(String[] args) throws Throwable {
try (ConfigurableApplicationContext appContext = SpringApplication.run(DemoApplication.class, args)) {
doStuff(appContext);
}
}
private static void doStuff(ConfigurableApplicationContext appContext) {
DirectlyAnnotatedRepository directlyAnnotatedRepository = appContext.getBean(DirectlyAnnotatedRepository.class);
directlyAnnotatedRepository.doSomething();
directlyAnnotatedRepository.deleteAll();
System.out.println("----------");
SubSubRepository repo = appContext.getBean(SubSubRepository.class);
repo.add(3, 4);
repo.greet("world");
repo.deleteAll();
}
}
Aspect:
package de.scrum_master.spring.q70824392;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class MyAspect {
#Before("#within(org.springframework.stereotype.Repository)")
public void directlyAnnotated(JoinPoint joinPoint) {
System.out.println("Directly annotated: " + joinPoint);
}
#Before(
"within((#org.springframework.stereotype.Repository *)+) && " +
"within(de.scrum_master.spring.q70824392..*)"
)
public void subClassesSubInterfaces(JoinPoint joinPoint) {
System.out.println("Sub-interfaces, sub-classes: " + joinPoint);
}
}
Like you said, the first advice should only kick in for classes directly annotated with #Repository, i.e. in this example for the DirectlyAnnotatedRepository bean.
The second advice however targets all types annotated with #Repository and their subtypes - please note the +. Depending on what we want, we could add one more execution pointcut to limit the intercepted methods, but I simply chose all. Please also note that without the second within pointcut, we would target many Spring-internal components, too, which would work for some, but throw exceptions for others. So we are limiting the scope to only repository beans in our own application. Instead, we could also exclude the Spring ones we do not want.
Console log:
Directly annotated: execution(void de.scrum_master.spring.q70824392.DirectlyAnnotatedRepository.doSomething())
Sub-interfaces, sub-classes: execution(void de.scrum_master.spring.q70824392.DirectlyAnnotatedRepository.doSomething())
Directly annotated: execution(void de.scrum_master.spring.q70824392.DirectlyAnnotatedRepository.deleteAll())
Sub-interfaces, sub-classes: execution(void de.scrum_master.spring.q70824392.DirectlyAnnotatedRepository.deleteAll())
----------
Sub-interfaces, sub-classes: execution(int de.scrum_master.spring.q70824392.MyRepository.add(int,int))
Sub-interfaces, sub-classes: execution(String de.scrum_master.spring.q70824392.MyRepository.greet(String))
Sub-interfaces, sub-classes: execution(void de.scrum_master.spring.q70824392.MyAbstractRepository.deleteAll())
If you have your repository classes/interfaces all named with *Repository suffix, what you need can be archived with the following:
#Around("execution(public * *..*Repository.*(..))")
public Object aroundAnyRepositoryMethod(
ProceedingJoinPoint joinPoint) throws Throwable {
...
}
or if you usually put your repositories in the separate sub-packages, then something like this to further filter:
#Around("execution(public * com.pkg1.pkg2..repository..*Repository.*(..))")
public Object aroundAnyRepositoryMethod(
ProceedingJoinPoint joinPoint) throws Throwable {
...
}
This will pick out all methods in your repository and all methods that it inherits or overrides.
I'm learing Spring Boot and I have probably very simple question, but it's not clear enough for me. I'm facing some problem with #Value annotation - I would like to know why apprication property cannot be injected to class parameter.
I prepared some very basic project using Spring Initializr and I added one property to my "application.properties" resource. Moreover, I created two additional classes: "YellowCar" (which works fine) and "RedCar" (which does not work - the parameter cannot be properly injected).
"application.properties" file:
car.age=15
The main class of my application:
package com.example.helper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
#SpringBootApplication
public class HelperApplication implements CommandLineRunner {
#Autowired
private Environment env;
public static void main(String[] args) {
SpringApplication.run(HelperApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
System.out.println (new RedCar(env));
System.out.println (new YellowCar());
}
}
RedCar is build by passing the Environment variable to constructor:
package com.example.helper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
#Component
public class RedCar {
private int age;
#Autowired
public RedCar (Environment env) {
this.age = new Integer(env.getRequiredProperty("car.age")).intValue();
}
#Override
public String toString() {
return "Car [age=" + age + "]";
}
}
YellowCar is build without passing the Environment variable to the constructor, but using the #Value annotation:
package com.example.helper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class YellowCar {
#Value("${car.age}")
private int age;
#Override
public String toString() {
return "YellowCar [age=" + age + "]";
}
}
This is the program output:
Car [age=15]
YellowCar [age=0]
As you can see, age of YellowCar was not properly injected (it equals 0).
My goal: I'd like not to pass everywhere Environment object to the constructor of other classes... I'd like to use #Value annotatnio instead. Could somebody explain me:
1) why my code is not working?
2) how this code should be updated in order to get the following output?
Car [age=15]
YellowCar [age=15]
Thanks!
This happens, because you instantiate YellowCar directly. In order to make thing work, #Autowire YellowCar inside HelperApplication and use this injected instance like this(not tested):
#Autowired
private YellowCar yellowCar;
public static void main(String[] args) {
SpringApplication.run(HelperApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
System.out.println (new RedCar(env));
System.out.println (yellowCar);
}
Explanation:
When you creating class using new, Spring knows nothing about this new instance, hence, it cannot inject anything. But when instance is created through Spring infrastructure (I'm trying not use a lot of slang words here), it will have all fields injected: when you mark class with #Component annotation or create method with #Bean annotation, you tell Spring, that you want it to be a Bean. On application startup, spring creates instances of this beans - by default only one instance per context - and inject this instance into all other beans, where requested. In this case, this instance is being processed by spring infrastructure (exact class which do it - AutowiredAnnotationBeanPostProcessor), and instances of other beans will be injected into our bean.
UPD: You can do the same thing with RedCar:
#Autowired
private YellowCar yellowCar;
#Autowired
private RedCar redCar;
public static void main(String[] args) {
SpringApplication.run(HelperApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
System.out.println (redCar);
System.out.println (yellowCar);
}
I have following classes
interface 1
package test;
public interface TODO {
boolean test();
}
interface 2
package test;
#FunctionalInterface
public interface FuncN {
State zip(State ...states);
}
class 1
package test;
public class Test {
public static Test define(FuncN zipperFunc,TODO... tasks) {
return null;
}
public static Test define(TODO... tasks) {
return null;
}
}
class 2
package test;
public class State {
public static State mergeStates(State ...states) {
return null;
}
}
main class
package test;
public class Main {
public static void main(String[] args) {
Test.define(State::mergeStates,()->true);
}
}
The class main doesn't compile, throws error
reference to define is ambiguous
Test.define(State::mergeStates,()->true);
^
both method define(FuncN,TODO...) in Test and method define(TODO...) in Test match
Class below does compile:
package test;
public class Main {
public static void main(String[] args) {
Test.define(states->State.mergeStates(states),()->true);
}
}
However i don't see any ambiguity. The signatures of FuncN and TODO are completely different, i don't think compiler should mistake them for one another.
Correct me if i am wrong.
P.S. Error is not reproducible using eclipse, so i would recommend creating a folder test creating all java files in that and run javac test/Main.java
It will compile if you cast the method reference call to FincN. there are two overload methods in Test class call 'define' so compiler confuse to select which one. so try to use as following.
public static void main(String[] args){
Test.define((FuncN) State::mergeStates,()->true);
}
My requirement is as given below :
"we have a load a big properties file using Spring and then loop through it .
While looping we have to check the very first column of properties file for some particular values.
As soon as we find those values we have to print that value and continue this printing process till the very end."
For this i finally able to build a code like below :
import java.util.Map;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringPropertiesUtil extends PropertyPlaceholderConfigurer {
private static Map<String, String> propertiesMap;
private static String keyToFind = "myProperty";
// Default as in PropertyPlaceholderConfigurer
private int springSystemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;
#Override
public void setSystemPropertiesMode(int systemPropertiesMode) {
super.setSystemPropertiesMode(systemPropertiesMode);
springSystemPropertiesMode = systemPropertiesMode;
}
#Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException {
super.processProperties(beanFactory, props);
for (Object key : props.keySet()) {
String keyStr = key.toString();
if(keyStr.equals(keyToFind)) {
String valueStr = resolvePlaceholder(keyStr, props, springSystemPropertiesMode);
System.out.println(valueStr);
}
}
}
public String getProperty(String name) {
return propertiesMap.get(name).toString();
}
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
((ConfigurableApplicationContext)context).close();
}
}
It is working fine but i am finding a nicer way of doing this if i can overload processProperties() and can pass String keyTofind to this method rather than defining it globally.
Any suggestion is welcome.
Thanks.
Alternatively to your solution, you could implement a custom property source. I believe this is the mechanism Spring has intended for proprietary "source parsing logic".
The subject is not terribly well documented on the web, but this article gives some insight: http://scottfrederick.cfapps.io/blog/2012/05/22/Custom-PropertySource-in-Spring-3.1---Part-1/