How to create objects (beens) manually? - quarkus

I am new to quarkus. And I am trying to write my first quarkus application (RAX-RS service). I started with "quarkus create app" and got the initial maven project with GreetingResource.java (a JAX-RS resource).
#Path("/hello")
public class GreetingResource {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello from RESTEasy Reactive";
}
}
Now I want to add a constructor and a field into GreetingResource.java.
#Path("/hello")
public class GreetingResource {
private final Greeting greeting;
public GreetingResource(Greeting greeting) {
this.greeting = greeting;
}
#GET
#Produces(MediaType.TEXT_PLAIN)
public String hello() {
return greeting.say();
}
}
After that, I want to create objects manually:
public class App {
public static void main(String[] args) {
Greeting greeting = new GreetingSomeImpl();
GreetingResource greetingResource = new GreetingResource(greeting);
Server.publicResource(greetingResource); // something like this
}
}
But I do not know how to do this manually (through "new" without annotations, injections, etc.).

Related

Injecting spring bean (service layer class) into ResourceBundle

I created a class using ResourceBundle interface as shown below. This class is dependent on another class. The implementation class for ResourceBundle (QuestionnaireSource as shown below) always has null as dependencies. No matter if I use setter or constructor injection.
Could someone please help me with this issue. I am I missing some configuration here.
#Component
public class QuestionnaireSource extends ResourceBundle {
private final QuestionnaireCache questionnaireCache;
private static final Object lockObject = new Object();
#Override
protected Object handleGetObject(String key) {
// Gets an object for the given key from this resource bundle.
// Returns null if this resource bundle does not contain an object for the given key 0
Object value = null;
try {
value = getString(key, LocaleContextHolder.getLocale());
} catch (Exception ignored) {
}
return value;
}
public Questionnaire getString(String key, Locale locale) {
Locale l = safeLocale(locale);
return getResources(l).get(key);
}
private Locale safeLocale(Locale l) {
if (l.getLanguage().equalsIgnoreCase("DE")) {
return Locale.GERMAN;
} else {
return Locale.ENGLISH;
}
}
protected Map<String, Questionnaire> getResources(Locale locale) {
synchronized (lockObject) {
return questionnaireCache.getQuestionnaireCache().get(locale.getLanguage().toUpperCase());
}
}
#Override
public Enumeration<String> getKeys() {
return null;
}
public QuestionnaireSource(QuestionnaireCache questionnaireCache) {
super();
this.questionnaireCache = questionnaireCache;
}
}
Update:
I found that even simple dependency injection in resourceBundle is failing.
UPdate2:
The way I am using in the main class is as follows:
// ResourceBundle test here
System.out.println("Test here for resource bundle");
Locale locale = new Locale("de", "DE");
ResourceBundle bundle = ResourceBundle.getBundle("com.app.util.QuestionnaireSource", locale);
System.out.println(bundle.getString("some.test.string"));
Update3
I am writing a simple example to convey the scenario:
Some service class
#Service
public class SomeServiceTest {
public String testMethod(){
return "test here and complete";
}
}
Some example implementation of resource bundle
#Component
public class MyResourceBundle extends ResourceBundle {
private final SomeServiceTest someServiceTest;
#Autowired
public MyResourceBundle(SomeServiceTest someServiceTest) {
this.someServiceTest = someServiceTest;
}
#Override
protected Object handleGetObject(String key) {
if(key.equals("test"))
return "test";
return null;
}
#Override
public Enumeration<String> getKeys() {
return null;
}
}
Main.java
main(){
// ResourceBundle test here
System.out.println("Test here for resource bundle");
Locale locale = new Locale("de", "DE");
ResourceBundle bundle = ResourceBundle.getBundle("com.app.util.MyResourceBundle", locale);
System.out.println(bundle.getString("test"));
}
Update4:
I changed the annotation on classes as mentioned by on this post https://www.baeldung.com/spring-inject-bean-into-unmanaged-objects
but still I have the null dependency injection for SomeServiceTest class. The changes are as shown below.
SomeServiceTest.java
#Service
public class SomeServiceTest {
public String testMethod(){
return "test here and complete";
}
}
MyResourceBundle.java
#Configurable
public class MyResourceBundle extends ResourceBundle {
#Autowired
private SomeServiceTest someServiceTest;
public MyResourceBundle() {
}
#Override
protected Object handleGetObject(String key) {
if(key.equals("test"))
return someServiceTest.testMethod();
return null;
}
#Override
public Enumeration<String> getKeys() {
return null;
}
}
still SomeServiceTest class is null.
Can you please post an example on how you are using this class? Is it you (your code) or spring who instanciate it (on startup)?
#Component only works for beans which Spring instanciate. If you want to inject stuff in classes you instanciate in you code you can annotate the class with #Configurable.
Please see https://www.baeldung.com/spring-inject-bean-into-unmanaged-objects for some examples.
Make sure you have initialized the spring context
If you are using spring boot
You can get the application context after it starts and use it to get the bean you want
For example
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(YouApplication.class, args);
MyResourceBundle resConfig = run.getBean("myResourceBundle", MyResourceBundle .class);
resConfig.handleGetObject("test");
}
Unfortunately ResourceBundle.getBundle does not initialize the spring application context

Spring boot application that run service in sequential order by passing the sequence at the run time

I want to implement a spring boot application that have 3 services . Now I want to run 3 services from my controller sequentially . I want to pass the the name of service and method as well as input parameters and sequence through controller and want to get the result of each of service . Please let me know how I can achieve these with a simple spring boot application.
Very very high level example. General idea that you need to use "reflection" for create class instance by name and/or call methods dynamically without "if". Pay attention that code can be different if your "service" is spring bean.
interface Service {
void method();
}
class Service1 implements Service {
#Override
public void method() {
// do magic
}
}
class Service2 implements Service {
#Override
public void method() {
// do magic
}
}
class Test {
public void executeMe(String className, String methodName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
// you may need to have full class name with package
Service service = (Service) Class.forName(className).newInstance();
if ("method".equalsIgnoreCase(methodName)) {
service.method();
}
}
}
Update
class Service1 {
public void method1() {
// do magic
}
public void method2() {
// do magic
}
}
class Service2 {
public void method3() {
// do magic
}
}
class Test {
public void executeMe(String className, String methodName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
// you may need to have full class name with package
Service1 service = (Service1) Class.forName(className).newInstance();
if ("method1".equalsIgnoreCase(methodName)) {
service.method1();
}
}
}
with Spring
class Test {
#Autowired
private Service1 service1;
#Autowired
private Service2 service2;
public void executeMe(String className, String methodName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Map<String, Object> map = new HashMap<>();
map.put("service1", service1);
map.put("service2", service2);
// you may need to have full class name with package
if ("service1".equalsIgnoreCase(className)) {
Service1 service1 = (Service1) map.get(className);
if ("method1".equalsIgnoreCase(methodName)) {
service1.method1();
}
}
}
}
Again, this is very very high level meta code.

Retrieving the value of a property pom.xml

I would like to retrieve the value of a property in file application.properties in my service layer of my application, the value of setVersion is null
version=5.4.3
and the function for recovery the version
#Override
public ProductDto getVersionApp() {
ProductDto dto = new ProductDto();
Properties prop = new Properties();
try {
prop.load(new FileInputStream("/concerto-rest-api/src/main/resources/application.properties"));
dto.setVersion(prop.getProperty("version"));
LOG.info("version ",prop.getProperty("version"));
} catch (IOException ex) {}
return dto;
}
You can use #Value("${version}") in you service, provided you service is a spring bean.
If you are using the spring-boot framework, there are several ways you can get that property.
First:
#SpringBootApplication
public class SpringBoot01Application {
public static void main(String[] args) {
ConfigurableApplicationContext context=SpringApplication.run(SpringBoot01Application.class, args);
String str1=context.getEnvironment().getProperty("version");
System.out.println(str1);
}
}
Second:
#Component
public class Student {
#Autowired
private Environment env;
public void speak() {
System.out.println("=========>" + env.getProperty("version"));
}
}
Third:
#Component
#PropertySource("classpath:jdbc.properties")//if is application.properties,then you don't need to write #PropertyScource("application.properties")
public class Jdbc {
#Value("${jdbc.user}")
private String user;
#Value("${jdbc.password}")
private String password;
public void speack(){
System.out.println("username:"+user+"------"+"password:"+password);
}
}

factory pattern using spring

How can I choose a service implementation depending on a request parameter on SpringBoot? I can do this by manually instantiating the service, but that's not making use of the Spring Injection feature.
I can also Autowire the two services separately but I'm thinking that if I have more implementations that would pollute the class.
Here's a crude example:
#RestController
class RestControllerTest {
#Autowired
PizzaService pizzaService;
public void bakePizza(#RequestParam("type") String type,#RequestParam("extra") String extra) {
if (type.equals("cheese")) {
//set pizzaService Cheese Implementation
pizzaService = new CheezePizza();
} else {
//set PizzaService vegetable Impleentation;
pizzaService = new VegetablePizza();
}
pizzaService.prepareIngredients(extra);
pizzaService.bakePizza();
}
}
public abstract class PizzaService {
String ingredients;
public abstract void prepareIngredients(String exraIngredient);
public void bakePizza() {
System.out.println("baking pizza with " + ingredients);
}
}
class CheezePizza extends PizzaService {
#Override
public void prepareIngredients(String exraIngredient) {
ingredients = "Cheese " + exraIngredient;
}
}
class VegetablePizza extends PizzaService {
#Override
public void prepareIngredients(String exraIngredient) {
ingredients = "Vegetable " + exraIngredient;
}
}
You could autowire list of beans of same type. So let's say you add getType() to your PizzaService and register every type as spring bean.
public abstract class PizzaService {
abstract String getType();
}
#Component
class CheezePizza extends PizzaService {
#Override
public String getType() {
return "cheese";
}
}
#Component
class VegetablePizza extends PizzaService {
#Override
public String getType() {
return "vegetable";
}
}
#RestController
class RestControllerTest {
private final Map<String, PizzaService> pizzaServices;
public RestControllerTest(List<PizzaService> services) {
pizzaServices = services.stream().collect(Collectors.toMap(PizzaService::getType, Function.identity()));
}
public void bakePizza(#RequestParam("type") String type, #RequestParam("extra") String extra) {
PizzaService pizzaService = pizzaServices.get(type); // remember of handling missing type
pizzaService.prepareIngredients(extra);
pizzaService.bakePizza();
}
}
Another way is to use name your beans by convention i.e. cheesePizza, vegetablePizza and then use ApplicationContext#getBean(type + "Pizza") but I like first approach better, because it's less magical.

Arquillian and ejb mocking - legacy application

i'm working on legacy project (jee 5, jboss 4.2.3) and i need to write integration tests for this app. I was able to integrate arquillian remote module and run simple tests. But now i would like to mock some services in my ejb using mockito.
Example :
some ejb
#Local
public interface DummyService {
String welcomMessage();
}
#Stateless
#LocalBinding(jndiBinding = "ejb/DummyServiceBean/local")
public class DummyServiceBean implements DummyService {
#EJB(mappedName = "ejb/DummyServiceBean2/local")
private DummyService2 service;
#Override
public String welcomMessage() {
return "world!!!!" + " " + service.getSomething();
}
}
#Local
public interface DummyService2 {
String getSomething();
}
#Stateless
#LocalBinding(jndiBinding = "ejb/DummyServiceBean2/local")
public class DummyServiceBean2 implements DummyService2 {
#Override
public String getSomething() {
return "sth";
}
}
test class
#RunWith(Arquillian.class)
public class DummyServiceTest {
#EJB(mappedName = "ejb/DummyServiceBean/local")
private DummyService service;
#Mock
private DummyService2 service2;
#Deployment
public static Archive<?> createDeployment() {
final JavaArchive javaArchive = ShrinkWrap.create(JavaArchive.class, "test.jar")
.addClasses(DummyService.class, DummyServiceBean.class,
DummyService2.class, DummyServiceBean2.class,
DummyServiceTest.class, InjectMocks.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
return ShrinkWrap.create(EnterpriseArchive.class, "test.ear")
.setApplicationXML(new File("application.xml"))
.addAsLibraries( // add maven resolve artifacts to the deployment
DependencyResolvers.use(MavenDependencyResolver.class)
.loadMetadataFromPom("pom.xml")
.artifact("org.mockito:mockito-all:1.9.5")
.resolveAs(GenericArchive.class))
.addAsModule(javaArchive);
}
#Before
public void setupMock() {
when(service2.getSomething()).thenReturn("qwerty");
}
#Test
public void should_assert_a_behaviour() {
System.out.println("Hello " + service.welcomMessage());
}
}
I can do this by not adding DummyServiceBean2.class into archive and by creating in test directory something like :
#Stateless
#LocalBinding(jndiBinding = "ejb/DummyServiceBean2/local")
public class MockDummyServiceBean2 implements DummyService2 {
#Override
public String getSomething() {
return "mock sth";
}
}
but this is bad practice. I got the idea to swap during runtime DummyServiceBean2 proxy reference using reflection in DummyServiceBean class for a new one with InvocationHandler which use mock inside his invoke method but it ended up on an exception
IllegalArgumentException: Can not set com.example.DummyService2 field com.example.DummyServiceBean.service to com.sun.proxy.$Proxy71
Any ideas how can i swap/replace DummyServiceBean2 proxy for new one or how can i replace invocation handler in existing one ?

Resources