How to load Groovy object from text file by Spring? - java

I have:
Some interface:
public interface ISomeObject {
void someAction();
}
Some groovy file (someObject.groovy):
public class SomeObject implements ISomeObject {
#Autowired
SomeOtherClass someField;
#Override
void someAction(){};
}
I need to Spring automatically load autowired fields. How should I load this class?
Some code (for start) that load class without Spring:
GroovyClassLoader gcl = new GroovyClassLoader();
Class clazz = null;
try {
clazz = gcl.parseClass(new File("someObject.groovy"));
ISomeObject groovyObject = (ISomeObject ) clazz.newInstance();
return Optional.of(groovyObject);
} catch (IOException |InstantiationException|IllegalAccessException e) {
return Optional.empty();
}

Personally I would use a plain old factory in this case and wire all the properties "manually".
Although I made a small research and it looks like you have other options to do it. I believe this question is what you are looking for:
Registering beans(prototype) at runtime in Spring

Related

JAVA Spring Boot : How to access application.properties values in normal class

I know how I can access the application.properties values in #Service classes in Java Spring boot like below
#Service
public class AmazonClient {
#Value("${cloud.aws.endpointUrl}")
private String endpointUrl;
}
But I am looking for an option to access this value directly in any class (a class without #Service annotation)
e.g.
public class AppUtils {
#Value("${cloud.aws.endpointUrl}")
private String endpointUrl;
}
But this returns null. Any help would be appreciated.
I have already read here but didn't help.
There's no "magic" way to inject values from a property file into a class that isn't a bean. You can define a static java.util.Properties field in the class, load values from the file manually when the class is loading and then work with this field:
public final class AppUtils {
private static final Properties properties;
static {
properties = new Properties();
try {
ClassLoader classLoader = AppUtils.class.getClassLoader();
InputStream applicationPropertiesStream = classLoader.getResourceAsStream("application.properties");
applicationProperties.load(applicationPropertiesStream);
} catch (Exception e) {
// process the exception
}
}
}
You can easily achievw this by annotating ur app utils class with #component annotation . spring will take care of loading properties.
But if you don't want to do that approach , then look at the link below .
https://www.baeldung.com/inject-properties-value-non-spring-class

How to obtain a field from my test in a Junit 5 jupiter extension

I have a Custom tag for my tests for a driver ive created. Im looking for a way to initialize and quit this driver during the BeforeEach and the AfterEach, using the new Junit5 jupiter extensions.
#Target({TYPE, FIELD, ANNOTATION_TYPE })
#Retention(RUNTIME)
#ExtendWith(MyExtension.class)
public #interface MyDriver
{
}
I've seen there is a AnnotationSupport.class that should help you to obtain the fields annotated with certain annotation but havent found any example.
What I want is just to be able to work with the field annotated with my annotation from the extension.
You could go about it like this:
public class MyExtension implements BeforeEachCallback {
#Override
public void beforeEach(ExtensionContext context) {
context.getTestInstance().ifPresent(testInstance -> {
List<Field> driverFields = AnnotationSupport.findAnnotatedFields(testInstance.getClass(), MyDriver.class);
for (Field driverField : driverFields) {
try {
Object fieldValue = driverField.get(testInstance);
// Do whatever you want with the field or its value
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
});
}
}
Which would then be called before each test in a test class like this:
#MyDriver
class SomeTestThatUsesDriver {
#MyDriver
Object fieldWithAnnotation = "whatever";
#Test
void aTest() {
...
}
}
What I wouldn't do, though, is to use the annotation #MyDriver for both adding the extension and marking a field. I'd rather got with an additional annotation like #MyDriverField or add the extension directly at the test class.

Nested annotations method interception in Guice

I searched a lot but couldn't find anything much useful.
Problem:
I have created custom annotation like:
#MapExceptions(value = {
#MapException(sources = {IllegalArgumentException.class, RuntimeException.class}, destination = BadRequestException.class),
#MapException(sources = {RuntimeException.class}, destination = BadRequestException.class)
})
I am using Guice for DI.
Do I have to write two method interceptors? Actual work is getting done in #MapException
If yes, then how can I call #MapException interceptors invoke method from #MapExceptions interceptors invoke method? I dont want to duplicate code.
My #MapException interceptor looks like following
public class MapExceptionInterceptor implements MethodInterceptor {
#Override
public Object invoke(MethodInvocation invocation) throws Throwable {
try {
return invocation.proceed();
} catch (Exception actualException) {
Method method = invocation.getMethod();
Annotation[] annotations = method.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof MapException) {
MapException mapException = (MapException) annotation;
Class<? extends Throwable> destinationClass = mapException.destination();
Class<? extends Throwable>[] sourceClasses = mapException.sources();
for (Class sourceExceptionClass : sourceClasses) {
if (actualException.getClass().isInstance(sourceExceptionClass)) {
Constructor ctr = destinationClass.getConstructor(String.class);
throw (Throwable) ctr.newInstance(actualException.getMessage());
}
}
}
}
throw actualException;
}
}
}
I am using following Binding currently
bindInterceptor(Matchers.any(), Matchers.annotatedWith(MapException.class), new MapExceptionInterceptor());
Is this okay? Or I can improve?
Thank You !
So, the inner annotation is just a data bag.
To solve this I wrote interceptor for outer annotation (MapExceptions) which does all the work.

NoUniqueBeanDefinitionException for Named classes

I am Using Spring 3.2.2 and was wondering if there was a way to inject beans by class type without explicitly giving them a string name. Ex:
#Named
public MyClass{
}
#Named
public MyOtherClass extends MyClass{
}
#Named
public class Foo{
public void blah(){
MyClass myClass = context.getBean(MyClass.class);
}
}
This will generate:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [MyClass] is defined: expected single matching bean but found 2: myClass,myOtherClass
Is there a way to say "Use the one that matches the class name exactly" without using String names?
In other words I don't want to do:
#Named("MyClass")...
#Named("MyOtherClass")...
MyClass myClass = context.getBean("MyClass");
Thanks!
This is what § 5.4.5 of Spring manual suggest whenever you encounter non-unique dependency bean definition:
Abandon autowiring in favor of explicit wiring.
Avoid autowiring for a bean definition by setting its autowire-candidate attributes to false as described in the next section.
Designate a single bean definition as the primary candidate by setting the primary attribute of its element to true.
If you are using Java 5 or later, implement the more fine-grained control available with annotation-based configuration, as described in Section 5.9, “Annotation-based container configuration”.
For the example, you could do something like:
#Named
public class Foo{
public void blah(){
MyClass myClass = getBean(MyClass.class);
}
private <T> T getBean(Class<T> type) {
return context.getBean(Introspector.decapitalize(type.getSimpleName()), type);
}
}
But this will not work when using #Inject or #Autowire.
To force strict class matching when autowiring, you could replace the default AutowireCandidateResolver on the BeanFactory with a BeanFactoryPostprocessor, but don't seem a good idea as #Resource or #Qualify can solve the NUBDE problem.
For example: (Not tested)
public class StrictClassAutowireCandidateResolver implements AutowireCandidateResolver {
#Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
if (!bdHolder.getBeanDefinition().isAutowireCandidate()) {
return false;
}
if (descriptor == null) {
return true;
}
String className = null;
if (descriptor.getField() != null) {
className = descriptor.getField().getType().getName();
}
else if (descriptor.getMethodParameter() != null) {
className = descriptor.getMethodParameter().getParameterType().getName();
}
Class<?> clazz = null;
try {
clazz = Class.forName(className);
}
catch (Exception e) {
return false;
}
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) {
// have no chances to be strict, let BeanFactory to find implementations.
return true;
}
return bdHolder.getBeanDefinition().getBeanClassName().equals(className);
}
#Override
public Object getSuggestedValue(DependencyDescriptor descriptor) {
return null;
}
}
Try using #Component (Service, Repository, Controller) on your classes, and #Autowired when you're injecting a bean.
EDIT: my bad, I didn't read the question too well. The problem is that you're actually having 2 instances of MyClass (since MyOtherClass extends from MyClass). Hence there's no other way than giving the classes names, or you'll always end up with NoUniqueBeanDefinitionExceptions.

Making a "TransactionAction" inner class

I've got a Spring + Hibernate + MySQL web application, which is just a hello-world-test-area for now.
One of my Service classes implements this method:
public List<Offerta> tutte() {
List<Offerta> tutte = null;
TransactionStatus status = txm.getTransaction( new DefaultTransactionDefinition() );
try {
tutte = dao.getAll(Offerta.class);
txm.commit(status);
} catch (Exception e) {
e.printStackTrace();
txm.rollback(status);
}
return tutte;
}
'txm' is an injected PlatformTransactionManager.
What I want now, is to avoid duplicating the "wrapping" transaction code in all my service's methods!
I would like something like this:
someHelperTransactionClass.doThisInTransaction(new TransactionAction() {
List l = dao.queryForSomething();
});
But that's a inner class: how can I pass in and out data from it? I mean, how can I get the resulting "l" list from that TransactionAction? You could answer in a number of ways to this specific case, but what I need is a generic TransactionAction or a different solution which let me write the actual database code, without having to write each time the same boring code.
Please do not answer "Why don't you use #Transactional annotations or AOP tx:advice configuration?" because I CAN'T!
Why? I am on Google AppEngine, and that cool guys are not so cool: the disabled access to the javax.naming package, and something in those great ways to declarative transactions touches it. :-\
You can imitate basic AOP mechanism using Proxy objects. Such as http://www.devx.com/Java/Article/21463/1954
This is a mock. But I really doubt it plays well with Spring or GAE. PLease note that you need to use interfaces for Proxies.
interface Dao {
List<Foo> getAllFoo();
}
public class MyDao implements Dao {
public MyDao() {
}
public List<Foo> getAllFoo() {
//.. get list of foo from database. No need to use transactions
}
public static void main(String[] args) {
Dao dao = new MyDao();
InvocationHandler handler = new TransactionProxyHandler(dao);
Dao proxy = (Dao) Proxy.newProxyInstance(MyDao.class.getClassLoader(), MyDao.class.getInterfaces(), handler);
List<Foo> all = proxy.getAllFoo();
}
}
class TransactionProxyHandler implements InvocationHandler {
protected Object delegate;
PlatformTransactionManager txm = new PlatformTransactionManager();
public TransactionProxyHandler(Object delegate) {
this.delegate = delegate;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
TransactionStatus status = txm.getTransaction();
Object res = null;
try {
res = method.invoke(delegate, args);
txm.commit(status);
} catch (Exception e) {
e.printStackTrace();
txm.rollback(status);
}
return res;
}
}

Categories