I have following template extension:
package com.company;
import io.quarkus.qute.RawString;
import io.quarkus.qute.TemplateExtension;
#TemplateExtension
public class TemplateExtensions {
static RawString myMethod(Input input, String someEnumName) {
SomeEnum value = SomeEnum.valueOf(someEnumName);
//...
return new RawString("...");
}
}
With this enum:
package com.company;
public enum SomeEnum {
LOREM,
IPSUM;
}
In my template I do following:
{input.myMethod('LOREM')}
This works great, but I am wondering how and if I can use the enum value directly:
package com.company;
import io.quarkus.qute.RawString;
import io.quarkus.qute.TemplateExtension;
#TemplateExtension
public class TemplateExtensions {
static RawString myMethod(Input input, SomeEnum value) {
//...
return new RawString("...");
}
}
I have tried:
{input.myMethod(com.company.SomeEnum.LOREM)}
But this creates:
NOT_FOUND
Hello resource:
package com.company;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateInstance;
#Path("/hello")
public class ExampleResource {
#Inject
Template helloTemplate;
#GET
#Path("/index.html")
public TemplateInstance index() {
return helloTemplate.data("input", new Input());
}
}
And Input Class:
package com.company;
public class Input {
String foo = "bar";
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
I needed to do this too, and I found an answer by searching through the Github issues for Quarkus. You can do it with Template Extensions
Add a method like this to your Enum:
#TemplateExtension(namespace = "SomeEnum", matchName = ANY)
static SomeEnum getVal(String val) {
return SomeEnum .valueOf(val.toUpperCase());
}
and then in your template, you can access it using {SomeEnum:LOREM}
Related
public class ServiceLoaderDemo {
public CPService demo() {
ServiceLoader<CPService> serviceLoader = ServiceLoader.load(CPService.class);
return iterate(serviceLoader);
}
public CPService iterate(ServiceLoader<CPService> serviceLoader) {
CPService nonDefault = null;
for (CPService cpService : serviceLoader) {
cpService.show();
if(!cpService.isDefault())
{
nonDefault = cpService;
}
}
return nonDefault;
}
}
I need to write unit tests for iterate method with following cases:
a default service and a non-default service
a default service only
a non-default service only
more than one non-default service
I tried to mock ServiceLoader class as follows:
import static org.fest.reflect.core.Reflection.method;
import static org.powermock.api.mockito.PowerMockito.mock;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import junit.framework.TestCase;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ServiceLoader.class)
public class ServiceLoaderDemoTest extends TestCase {
private ServiceLoaderDemo serviceLoaderDemo = new ServiceLoaderDemo();
public void testIterate() {
final ServiceLoader mockServiceLoader = mock(ServiceLoader.class);
IteratorDummy iterator = new IteratorDummy();
iterator.cpServices.add(new CPServiceImplTwo());
iterator.cpServices.add(new CPServiceImplOne());
PowerMockito.when(mockServiceLoader.iterator()).thenReturn(iterator);
CPService methodToTest = null;
try {
methodToTest = method("iterate").withReturnType(CPService.class).withParameterTypes(ServiceLoader.class).in(serviceLoaderDemo).invoke(mockServiceLoader);
} catch (SecurityException e) {
e.printStackTrace();
}
assertEquals(methodToTest.getClass(), ServiceLoaderDemoTest.class);
}
}
class IteratorDummy implements Iterator<CPService> {
public List<CPService> cpServices = new ArrayList<>();
#Override
public boolean hasNext() {
return cpServices.iterator().hasNext();
}
#Override
public CPService next() {
CPService service = cpServices.iterator().next();
return service;
}
}
This is throwing NullPointerException. I am unable to write unit tests for this. please help me.
This is my object class:
package com.example;
public class Car {
private String name;
private String model;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
This is operation class:
package com.example;
public class Call1 {
public static String callMethod1(){
return "Hello from callMethod1";
}
public static Car callingCall2(){
Call2 call = new Call2();
Car args= call.callMethod2();
return args;
}
}
This is another class:
package com.example;
public class Call2 {
public Car callMethod2(){
Car car = new Car();
car.setModel("2009");
car.setName("mustang");
return car;
}
}
This is my test class:
package com.example;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.agent.builder.AgentBuilder.RedefinitionStrategy;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.asm.Advice.OnMethodEnter;
import net.bytebuddy.asm.AsmVisitorWrapper;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.DynamicType.Builder;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.utility.JavaModule;
import org.junit.Test;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import static net.bytebuddy.matcher.ElementMatchers.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
public class CallingTest {
#Test
public void givenCall1_whenRedefined_thenReturnFooRedefined() throws
Exception {
premain(null, ByteBuddyAgent.install());
/* Car carTest = new Car();
carTest.setModel("2011");
carTest.setName("Maruti");
ByteBuddyAgent.install();
new ByteBuddy()
.redefine(Call1.class)
.method(named("callingCall2"))
.intercept(FixedValue.value(carTest))
.make()
.load(Car.class.getClassLoader(),
ClassReloadingStrategy.fromInstalledAgent());*/
Call1 f = new Call1();
assertEquals(f.callingCall2().getModel(), "2011");
assertEquals(f.callingCall2().getName(), "Maruti");
}
public static void premain(String arguments, Instrumentation instrumentation) {
new AgentBuilder.Default()
.disableClassFormatChanges()
.with(RedefinitionStrategy.RETRANSFORMATION)
.type(is(Call1.class))
.transform(new AgentBuilder.Transformer() {
/* #Override
public DynamicType.Builder transform(DynamicType.Builder builder,
TypeDescription typeDescription,
ClassLoader classloader) {
return builder.method(named("toString"))
.intercept(FixedValue.value("transformed"));
}*/
#Override
public Builder<?> transform(Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule arg3) {
Car carTest = new Car();
carTest.setModel("2011");
carTest.setName("Maruti");
return builder.method(named("callingCall2")).intercept(MethodDelegation.to(MyAdvice.class));
// return builder.visit((AsmVisitorWrapper) Advice.to(Advice.class).on(ElementMatchers.named("callingCall2")));
}
}).installOn(instrumentation);
}
class MyAdvice {
#OnMethodEnter
Car foo() {
Car carTest = new Car();
carTest.setModel("2011");
carTest.setName("Maruti");
return carTest;
}
}
}
The requirement is to override the value of object Car in this scenario such that test class should pass. I tried using byte buddy and AgentBuilder for doing so. When I tried using redefine, it threw error which is
'java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)'
When I tried using AgentBuilder, it is not affecting assertion resulting it to fail.
I am newly introduced to byte-buddy so please help achieving requirement.
FixedValue can only be used with Strings, Class object, primitive types and their wrappers. To cover Your case You can introduce an interceptor like this:
#Test
public void givenCall1_whenRedefined_thenReturnFooRedefined() throws Exception {
ByteBuddyAgent.install();
new ByteBuddy()
.redefine(Call1.class)
.method(named("callingCall2"))
.intercept(to(Interceptor.class))
.make()
.load(ByteBuddyTest2.class.getClassLoader(),
ClassReloadingStrategy.fromInstalledAgent());
Call1 f = new Call1();
assertEquals(f.callingCall2().getModel(), "2011");
assertEquals(f.callingCall2().getName(), "Maruti");
}
public static class Interceptor {
public static Car callingCall2() {
Car carTest = new Car();
carTest.setModel("2011");
carTest.setName("Maruti");
return carTest;
}
}
I am coding in spring-boot. I tried to get the value of properties.properties in other packages without success. For example in the classe ClassUtils.java, the value of testValue is always null
This is my project
This is my code:
package com.plugins.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.plugins.domain.ClassUtils;
#RestController
public class SearchContactController {
#Value("${environnement.test}")
String testValue;
#Value("${environnement.url}")
String urlValue;
#RequestMapping(value = "/test")
public String pingRequest() {
System.out.println("value ===> " + testValue + " /// " + urlValue);
return "test !" + ClassUtils.getTestValue();
}
}
This is my second class, where I can't get the value of testValue variable:
package com.plugins.domain;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class ClassUtils {
#Value("${environnement.test}")
static String testValue;
public static String getTestValue(){
return "The return "+testValue;
}
}
This is my springApp.java
package com.plugins;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringBootVideApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootVideApplication.class, args);
}
}
Enable #ComponentScan({"com.plugins"}) , in Application
To access the properties defined in application.properties
myapp.url="xxxxxx"
in your class
#Value("${myapp.url}")
private String testValue;
but this cannot be a static variable, if it is a static variable you do some hack like this, by defining setter method
private static String testValue;
#Value("${myapp.url}")
public void testValue(String value) {
testValue = value;
}
I resolve this issue by addin #Autowired in the class which use the method of the other class this is a snippet
// Class: SearchContactController.java
#Autowired
ClassUtils cd;
#RequestMapping(value = "/ping")
public String pingRequest() {
return "Ping OK !" + cd.getTestValue();
}
Currently I'm rendering a command object in a MessageBodyReader but I'd like to be able to do this in a #BeanParam:
Inject a field derived from the SecurityContext (Is there somewhere to hook in the conversion?).
have a field inject that has been materialised by a MessageBodyReader.
Is this possible ?
Note: Go Down to UPDATE. I guess it is possible to use #BeanParam. Though you need to inject the SecurityContext into the bean and extract the name info.
There's no way to achieve this with #BeanParam corrected. You could use a MessageBodyReader the way you are doing, but IMO that's more of a hack than anything. Instead, the way I would achieve it is to use the framework components the way they are supposed to be used, which involves custom parameter injection.
To achieve this, you need two things, a ValueFactoryProvider to provide parameter values, and a InjectionResolver with your own custom annotation. I won't do much explaining for the example below, but you can find a good explanation in
Jersey 2.x Custom Injection Annotation With Attributes
You can run the below example like any JUnit test. Everything is included into the one class. These are the dependencies I used.
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.19</version>
<scope>test</scope>
</dependency>
And here is the test
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.security.Principal;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Entity;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.api.InjectionResolver;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.api.TypeLiteral;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.internal.inject.AbstractContainerRequestValueFactory;
import org.glassfish.jersey.server.internal.inject.AbstractValueFactoryProvider;
import org.glassfish.jersey.server.internal.inject.MultivaluedParameterExtractorProvider;
import org.glassfish.jersey.server.internal.inject.ParamInjectionResolver;
import org.glassfish.jersey.server.model.Parameter;
import org.glassfish.jersey.server.spi.internal.ValueFactoryProvider;
import org.glassfish.jersey.test.JerseyTest;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class CustomInjectionTest extends JerseyTest {
#Target(ElementType.PARAMETER)
#Retention(RetentionPolicy.RUNTIME)
public static #interface CustomParam {
}
public static class CustomModel {
public String name;
public RequestBody body;
}
public static class RequestBody {
public String message;
}
public static class CustomParamValueFactory
extends AbstractContainerRequestValueFactory<CustomModel> {
#Override
public CustomModel provide() {
ContainerRequest request = getContainerRequest();
String name = request.getSecurityContext().getUserPrincipal().getName();
RequestBody body = request.readEntity(RequestBody.class);
CustomModel model = new CustomModel();
model.body = body;
model.name = name;
return model;
}
}
public static class CustomValueFactoryProvider extends AbstractValueFactoryProvider {
#Inject
public CustomValueFactoryProvider(MultivaluedParameterExtractorProvider multiProvider,
ServiceLocator locator) {
super(multiProvider, locator, Parameter.Source.UNKNOWN);
}
#Override
protected Factory<?> createValueFactory(Parameter parameter) {
if (CustomModel.class == parameter.getType()
&& parameter.isAnnotationPresent(CustomParam.class)) {
return new CustomParamValueFactory();
}
return null;
}
}
public static class CustomParamInjectionResolver extends ParamInjectionResolver<CustomParam> {
public CustomParamInjectionResolver() {
super(CustomValueFactoryProvider.class);
}
}
private static class CustomInjectBinder extends AbstractBinder {
#Override
protected void configure() {
bind(CustomValueFactoryProvider.class)
.to(ValueFactoryProvider.class)
.in(Singleton.class);
bind(CustomParamInjectionResolver.class)
.to(new TypeLiteral<InjectionResolver<CustomParam>>(){})
.in(Singleton.class);
}
}
private static final String PRINCIPAL_NAME = "peeskillet";
#PreMatching
public static class SecurityContextFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
requestContext.setSecurityContext(new SecurityContext(){
public Principal getUserPrincipal() {
return new Principal() {
public String getName() { return PRINCIPAL_NAME; }
};
}
public boolean isUserInRole(String role) { return false; }
public boolean isSecure() { return true;}
public String getAuthenticationScheme() { return null; }
});
}
}
#Path("test")
public static class TestResource {
#POST
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.APPLICATION_JSON)
public String post(#CustomParam CustomModel model) {
return model.name + ":" + model.body.message;
}
}
#Override
public ResourceConfig configure() {
return new ResourceConfig(TestResource.class)
.register(SecurityContextFilter.class)
.register(new CustomInjectBinder());
}
#Test
public void should_return_name_with_body() {
RequestBody body = new RequestBody();
body.message = "Hello World";
Response response = target("test").request()
.post(Entity.json(body));
assertEquals(200, response.getStatus());
String responseBody = response.readEntity(String.class);
assertEquals(PRINCIPAL_NAME + ":" + body.message, responseBody);
System.out.println(responseBody);
}
}
Note that I read the request body from the ContainerRequest inside the CustomParamValueFactory. It is the same RequestBody that I sent in JSON from the request in the #Test.
UPDATE
So to my surprise, it is possible to use #BeanParam. Here is the following bean I used to test
public static class CustomModel {
#Context
public SecurityContext securityContext;
public RequestBody body;
}
public static class RequestBody {
public String message;
}
The difference from the previous test is that instead of the name from the SecurityContext.Principal, we need to inject the entire SecurityContext. There's just no way for the inject to get the name from the Principal, So we will just do it manually.
The thing that surprised me the most though, is that we are able to inject the RequestBody entity. I didn't know this was possible.
Here is the complete test
import java.io.IOException;
import java.security.Principal;
import javax.ws.rs.BeanParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Entity;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class CustomInjectTestTake2 extends JerseyTest {
private static final String PRINCIPAL_NAME = "peeskillet";
private static final String MESSAGE = "Hello World";
private static final String RESPONSE = PRINCIPAL_NAME + ":" + MESSAGE;
public static class CustomModel {
#Context
public SecurityContext securityContext;
public RequestBody body;
}
public static class RequestBody {
public String message;
}
#PreMatching
public static class SecurityContextFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
requestContext.setSecurityContext(new SecurityContext(){
public Principal getUserPrincipal() {
return new Principal() {
public String getName() { return PRINCIPAL_NAME; }
};
}
public boolean isUserInRole(String role) { return false; }
public boolean isSecure() { return true;}
public String getAuthenticationScheme() { return null; }
});
}
}
#Path("test")
public static class TestResource {
#POST
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.APPLICATION_JSON)
public String post(#BeanParam CustomModel model) {
return model.securityContext.getUserPrincipal().getName()
+ ":" + model.body.message;
}
}
#Override
public ResourceConfig configure() {
return new ResourceConfig(TestResource.class)
.register(SecurityContextFilter.class);
}
#Test
public void should_return_name_with_body() {
RequestBody body = new RequestBody();
body.message = "Hello World";
Response response = target("test").request()
.post(Entity.json(body));
assertEquals(200, response.getStatus());
String responseBody = response.readEntity(String.class);
assertEquals(RESPONSE, responseBody);
System.out.println(responseBody);
}
}
See Also:
Custom Injection and Lifecycle Management
I am going through the Play Framework tutorial. I am getting this error:
error: cannot find symbol
In /Users/hseritt/devel/todolist/app/controllers/Application.java at line 12.
import views.html.*;
public class Application extends Controller {
static Form<Task> taskForm = Form.form(Task.class); // ERROR IS HIGHLIGHTED AS Form.form
public static Result index() {
return redirect(routes.Application.tasks());
}
My full code for Application.java:
package controllers;
import play.*;
import play.data.*;
import play.mvc.*;
import models.*;
import views.html.*;
public class Application extends Controller {
static Form<Task> taskForm = Form.form(Task.class);
public static Result index() {
return redirect(routes.Application.tasks());
}
public static Result tasks() {
return ok(
views.html.index.render(Task.all(), taskForm)
);
}
public static Result newTask() {
return TODO;
}
public static Result deleteTask(Long id) {
return TODO;
}
}
I am wondering if I missed something in the tutorial or put something in the wrong place.
Thanks!
I think you should import the following:
import static play.data.Form.*;
As per jnoob, just change import to import play.data.Form, then do static Form<Task> taskForm = form(Task.class);, worked for me.