Using multiple res folders with Robolectric - gradle

My current Gradle configuration has multiple (Merged) res folders:
sourceSets {
androidTest {
setRoot('src/test')
}
main {
res.srcDirs =
[
'src/main/res/features/registration',
'src/main/res/features/login',
'src/main/res'
]
}
}
But Robolectric allows me to configure a single directory using AndroidManifest:
public class RobolectricGradleTestRunner extends RobolectricTestRunner {
private static final int MAX_SDK_SUPPORTED_BY_ROBOLECTRIC = 18;
public RobolectricGradleTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
}
#Override
protected AndroidManifest getAppManifest(Config config) {
String manifestProperty = "../app/src/main/AndroidManifest.xml";
String resProperty = "../app/src/main/res";
return new AndroidManifest(Fs.fileFromPath(manifestProperty), Fs.fileFromPath(resProperty)) {
#Override
public int getTargetSdkVersion() {
return MAX_SDK_SUPPORTED_BY_ROBOLECTRIC;
}
};
}
}
This way tests are failing. Is it possible to configure robolectric to reflect my gradle file?

Another solution similar to Luca's:
public class MyTestRunner extends RobolectricTestRunner {
...
#Override
protected AndroidManifest getAppManifest(Config config) {
String appRoot = "./src/main/";
String manifestPath = appRoot + "AndroidManifest.xml";
String resDir = appRoot + "res";
String assetsDir = appRoot + "assets";
return new AndroidManifest(Fs.fileFromPath(manifestPath), Fs.fileFromPath(resDir), Fs.fileFromPath(assetsDir)) {
#Override
public List<ResourcePath> getIncludedResourcePaths() {
List<ResourcePath> paths = super.getIncludedResourcePaths();
paths.add(new ResourcePath(getRClass(), getPackageName(), Fs.fileFromPath("../app/src/main/res/features/registration"), getAssetsDirectory()));
paths.add(new ResourcePath(getRClass(), getPackageName(), Fs.fileFromPath("../app/src/main/res/features/login"), getAssetsDirectory()));
return paths;
}
};
}
}
Don't forget to annotate your tests with #RunWith(MyTestRunner.class)

Ok, this is the easiest way to do it, You will have to extend RobolectricTestRunner getAppManifest and createAppResourceLoader.
In getAppManifest you will simply have to store the manifest in a field, let's say mDefaultManifest.
In createAppResourceLoader you will have to add the right resources injected.
/**
* TODO: Watch OUT this is copied from RobolectricTestRunner in Robolectric-2.4 keep it up to date!
*/
#Override
protected ResourceLoader createAppResourceLoader(ResourceLoader systemResourceLoader, AndroidManifest appManifest) {
List<PackageResourceLoader> appAndLibraryResourceLoaders = new ArrayList<PackageResourceLoader>();
for (ResourcePath resourcePath : appManifest.getIncludedResourcePaths()) {
appAndLibraryResourceLoaders.add(createResourceLoader(resourcePath));
}
/* BEGIN EDIT */
if(mDefaultManifest != null) {
ResourcePath rpInjected = new ResourcePath(mDefaultManifest.getRClass(), mDefaultManifest.getPackageName(), Fs.fileFromPath("../app/src/main/res/features/registration"), mDefaultManifest.getAssetsDirectory());
appAndLibraryResourceLoaders.add(createResourceLoader(rpInjected));
rpInjected = new ResourcePath(mDefaultManifest.getRClass(), mDefaultManifest.getPackageName(), Fs.fileFromPath("../app/src/main/res/features/login"), mDefaultManifest.getAssetsDirectory());
appAndLibraryResourceLoaders.add(createResourceLoader(rpInjected));
}
/* END EDIT */
OverlayResourceLoader overlayResourceLoader = new OverlayResourceLoader(appManifest.getPackageName(), appAndLibraryResourceLoaders);
Map<String, ResourceLoader> resourceLoaders = new HashMap<String, ResourceLoader>();
resourceLoaders.put("android", systemResourceLoader);
resourceLoaders.put(appManifest.getPackageName(), overlayResourceLoader);
return new RoutingResourceLoader(resourceLoaders);
}
Do not forget to add #RunWith(YourTestRunner.class) in your test classes.

Related

Freemarker Debugger framework usage example

I have started working on a Freemarker Debugger using breakpoints etc. The supplied framework is based on java RMI. So far I get it to suspend at one breakpoint but then ... nothing.
Is there a very basic example setup for the serverpart and the client part other then the debug/imp classes supplied with the sources. That would be of great help.
this is my server class:
class DebuggerServer {
private final int port;
private final String templateName1;
private final Environment templateEnv;
private boolean stop = false;
public DebuggerServer(String templateName) throws IOException {
System.setProperty("freemarker.debug.password", "hello");
port = SecurityUtilities.getSystemProperty("freemarker.debug.port", Debugger.DEFAULT_PORT).intValue();
System.setProperty("freemarker.debug.password", "hello");
Configuration cfg = new Configuration();
// Some other recommended settings:
cfg.setIncompatibleImprovements(new Version(2, 3, 20));
cfg.setDefaultEncoding("UTF-8");
cfg.setLocale(Locale.US);
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
Template template = cfg.getTemplate(templateName);
templateName1 = template.getName();
System.out.println("Debugging " + templateName1);
Map<String, Object> root = new HashMap();
Writer consoleWriter = new OutputStreamWriter(System.out);
templateEnv = new Environment(template, null, consoleWriter);
DebuggerService.registerTemplate(template);
}
public void start() {
new Thread(new Runnable() {
#Override
public void run() {
startInternal();
}
}, "FreeMarker Debugger Server Acceptor").start();
}
private void startInternal() {
boolean handled = false;
while (!stop) {
List breakPoints = DebuggerService.getBreakpoints(templateName1);
for (int i = 0; i < breakPoints.size(); i++) {
try {
Breakpoint bp = (Breakpoint) breakPoints.get(i);
handled = DebuggerService.suspendEnvironment(templateEnv, templateName1, bp.getLine());
} catch (RemoteException e) {
System.err.println(e.getMessage());
}
}
}
}
public void stop() {
this.stop = true;
}
}
This is the client class:
class DebuggerClientHandler {
private final Debugger client;
private boolean stop = false;
public DebuggerClientHandler(String templateName) throws IOException {
// System.setProperty("freemarker.debug.password", "hello");
// System.setProperty("java.rmi.server.hostname", "192.168.2.160");
client = DebuggerClient.getDebugger(InetAddress.getByName("localhost"), Debugger.DEFAULT_PORT, "hello");
client.addDebuggerListener(environmentSuspendedEvent -> {
System.out.println("Break " + environmentSuspendedEvent.getName() + " at line " + environmentSuspendedEvent.getLine());
// environmentSuspendedEvent.getEnvironment().resume();
});
}
public void start() {
new Thread(new Runnable() {
#Override
public void run() {
startInternal();
}
}, "FreeMarker Debugger Server").start();
}
private void startInternal() {
while (!stop) {
}
}
public void stop() {
this.stop = true;
}
public void addBreakPoint(String s, int i) throws RemoteException {
Breakpoint bp = new Breakpoint(s, i);
List breakpoints = client.getBreakpoints();
client.addBreakpoint(bp);
}
}
Liferay IDE (https://github.com/liferay/liferay-ide) has FreeMarker template debug support (https://issues.liferay.com/browse/IDE-976), so somehow they managed to use it. I have never seen it in action though. Other than that, I'm not aware of anything that uses the debug API.

dynamic values in tags object of swagger

I want to provide values from properties file in tags section of the swagger for ex: tags = "${metric.tags}" but not able to pickup from properties file. for values it is working fine value = "${metric.value}".
I have made plugin configuration in swagger configuration file and it started working as per my requirement.
#Bean
public TranslationOperationBuilderPlugin translationPlugin() {
return new TranslationOperationBuilderPlugin();
}
#Order(Ordered.LOWEST_PRECEDENCE)
public static class TranslationOperationBuilderPlugin implements OperationBuilderPlugin {
#Autowired
Environment environment;
#Override
public boolean supports(DocumentationType delimiter) {
return true;
}
#Override
public void apply(OperationContext context) {
String summary = context.operationBuilder().build().getSummary();
String notes = context.operationBuilder().build().getNotes();
Set<String>tags = context.operationBuilder().build().getTags();
Set<String>translatedTags= new HashSet<>();
for(String tag:tags) {
if(environment.getProperty(tag)!=null) {
translatedTags.add(environment.getProperty(tag));
}else {
translatedTags.add(tag);
}
}
ModelReference modelReference= context.operationBuilder().build().getResponseModel();
AllowableListValues allowableValues=(AllowableListValues) modelReference.getAllowableValues();
if(allowableValues!=null && allowableValues.getValues()!=null) {
List<String> translatedAllowables=new ArrayList<>();
for(String value:allowableValues.getValues()) {
if(environment.getProperty(value)!=null) {
translatedAllowables.add(environment.getProperty(value));
}else {
translatedAllowables.add(value);
}
}
allowableValues.getValues().removeAll(allowableValues.getValues());
allowableValues.getValues().addAll(translatedAllowables);
}
//String summaryTranslated = apiDescriptionPropertiesReader.getProperty(summary);
//String notesTranslated = apiDescriptionPropertiesReader.getProperty(notes);
//context.operationBuilder().summary(summaryTranslated);
//context.operationBuilder().notes(notesTranslated);
context.operationBuilder().tags(translatedTags);
}

How to start multiple boot apps for end-to-end tests?

I'd like to write end-to-end tests to validate two boot apps work well together with various profiles.
What already works:
create a third maven module (e2e) for end-to-end tests, in addition to the two tested apps (authorization-server and resource-server)
write tests using TestResTemplate
Test work fine if I start authorization-server and resource-server manually.
What I now want to do is automate the tested boot apps startup and shutdown with the right profiles for each test.
I tried:
adding maven dependencies to tested apps in e2e module
using SpringApplication in new threads for each app to start
But I face miss-configuration issues as all resources and dependencies end in the same shared classpath...
Is there a way to sort this out?
I'm also considering starting two separate java -jar ... processes, but then, how to ensure tested apps fat-jars are built before 2e2 unit-tests run?
Current app start/shutdown code sample which fails as soon as I had maven dependency to second app to start:
private Service startAuthorizationServer(boolean isJwtActive) throws InterruptedException {
return new Service(
AuthorizationServer.class,
isJwtActive ? new String[]{ "jwt" } : new String[]{} );
}
private static final class Service {
private ConfigurableApplicationContext context;
private final Thread thread;
public Service(Class<?> appClass, String... profiles) throws InterruptedException {
thread = new Thread(() -> {
SpringApplication app = new SpringApplicationBuilder(appClass).profiles(profiles).build();
context = app.run();
});
thread.setDaemon(false);
thread.start();
while (context == null || !context.isRunning()) {
Thread.sleep(1000);
};
}
#PreDestroy
public void stop() {
if (context != null) {
SpringApplication.exit(context);
}
if (thread != null) {
thread.interrupt();
}
}
}
I think your case, running the two applications via a docker compose can be a good idea.
This article shows how you can set up some integration tests using a docker compose image: https://blog.codecentric.de/en/2017/03/writing-integration-tests-docker-compose-junit/
Also, take a look at this post from Martin Fowler: https://martinfowler.com/articles/microservice-testing/
I got things working with second solution:
end-to-end tests projects has no other maven dependency than what is required to run spring-tests with TestRestClient
test config initialises environment, running mvn packageon required modules in separate processes
test cases run (re)start apps with chosen profiles in separate java -jar ... processes
Here is the helper class I wrote for this (taken from there):
class ActuatorApp {
private final int port;
private final String actuatorEndpoint;
private final File jarFile;
private final TestRestTemplate actuatorClient;
private Process process;
private ActuatorApp(File jarFile, int port, TestRestTemplate actuatorClient) {
this.port = port;
this.actuatorEndpoint = getBaseUri() + "actuator/";
this.actuatorClient = actuatorClient;
this.jarFile = jarFile;
Assert.isTrue(jarFile.exists(), jarFile.getAbsolutePath() + " does not exist");
}
public void start(List<String> profiles, List<String> additionalArgs) throws InterruptedException, IOException {
if (isUp()) {
stop();
}
this.process = Runtime.getRuntime().exec(appStartCmd(jarFile, profiles, additionalArgs));
Executors.newSingleThreadExecutor().submit(new ProcessStdOutPrinter(process));
for (int i = 0; i < 10 && !isUp(); ++i) {
Thread.sleep(5000);
}
}
public void start(String... profiles) throws InterruptedException, IOException {
this.start(Arrays.asList(profiles), List.of());
}
public void stop() throws InterruptedException {
if (isUp()) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.setAccept(List.of(MediaType.APPLICATION_JSON_UTF8));
actuatorClient.postForEntity(actuatorEndpoint + "shutdown", new HttpEntity<>(headers), Object.class);
Thread.sleep(5000);
}
if (process != null) {
process.destroy();
}
}
private String[] appStartCmd(File jarFile, List<String> profiles, List<String> additionalArgs) {
final List<String> cmd = new ArrayList<>(
List.of(
"java",
"-jar",
jarFile.getAbsolutePath(),
"--server.port=" + port,
"--management.endpoint.heath.enabled=true",
"--management.endpoint.shutdown.enabled=true",
"--management.endpoints.web.exposure.include=*",
"--management.endpoints.web.base-path=/actuator"));
if (profiles.size() > 0) {
cmd.add("--spring.profiles.active=" + profiles.stream().collect(Collectors.joining(",")));
}
if (additionalArgs != null) {
cmd.addAll(additionalArgs);
}
return cmd.toArray(new String[0]);
}
private boolean isUp() {
try {
final ResponseEntity<HealthResponse> response =
actuatorClient.getForEntity(actuatorEndpoint + "health", HealthResponse.class);
return response.getStatusCode().is2xxSuccessful() && response.getBody().getStatus().equals("UP");
} catch (ResourceAccessException e) {
return false;
}
}
public static Builder builder(String moduleName, String moduleVersion) {
return new Builder(moduleName, moduleVersion);
}
/**
* Configure and build a spring-boot app
*
* #author Ch4mp
*
*/
public static class Builder {
private String moduleParentDirectory = "..";
private final String moduleName;
private final String moduleVersion;
private int port = SocketUtils.findAvailableTcpPort(8080);
private String actuatorClientId = "actuator";
private String actuatorClientSecret = "secret";
public Builder(String moduleName, String moduleVersion) {
this.moduleName = moduleName;
this.moduleVersion = moduleVersion;
}
public Builder moduleParentDirectory(String moduleParentDirectory) {
this.moduleParentDirectory = moduleParentDirectory;
return this;
}
public Builder port(int port) {
this.port = port;
return this;
}
public Builder actuatorClientId(String actuatorClientId) {
this.actuatorClientId = actuatorClientId;
return this;
}
public Builder actuatorClientSecret(String actuatorClientSecret) {
this.actuatorClientSecret = actuatorClientSecret;
return this;
}
/**
* Ensures the app module is found and packaged
* #return app ready to be started
* #throws IOException if module packaging throws one
* #throws InterruptedException if module packaging throws one
*/
public ActuatorApp build() throws IOException, InterruptedException {
final File moduleDir = new File(moduleParentDirectory, moduleName);
packageModule(moduleDir);
final File jarFile = new File(new File(moduleDir, "target"), moduleName + "-" + moduleVersion + ".jar");
return new ActuatorApp(jarFile, port, new TestRestTemplate(actuatorClientId, actuatorClientSecret));
}
private void packageModule(File moduleDir) throws IOException, InterruptedException {
Assert.isTrue(moduleDir.exists(), "could not find module. " + moduleDir + " does not exist.");
String[] cmd = new File(moduleDir, "pom.xml").exists() ?
new String[] { "mvn", "-DskipTests=true", "package" } :
new String[] { "./gradlew", "bootJar" };
Process mvnProcess = new ProcessBuilder().directory(moduleDir).command(cmd).start();
Executors.newSingleThreadExecutor().submit(new ProcessStdOutPrinter(mvnProcess));
Assert.isTrue(mvnProcess.waitFor() == 0, "module packaging exited with error status.");
}
}
private static class ProcessStdOutPrinter implements Runnable {
private InputStream inputStream;
public ProcessStdOutPrinter(Process process) {
this.inputStream = process.getInputStream();
}
#Override
public void run() {
new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(System.out::println);
}
}
public String getBaseUri() {
return "https://localhost:" + port;
}
}

How to implement custom SftpSimplePatternFileListFilter?

I am newbee to Spring integration. i am trying to implement customer sftp filter to list the files in SFTP server. I am getting "The blank final field seen may not have been initialized" at the constructor.Can you please suggest me to get list of file names from sftp server.
I dont have any idea what went wrong in my code.
Thanks in Advance
java code
public class SFTPFileFilter extends SftpSimplePatternFileListFilter {
public SFTPFileFilter(String pattern) {
super(pattern);
// TODO Auto-generated constructor stub
}
final static Logger logger = LoggerFactory.getLogger(SFTPFileFilter.class);
private final Queue<File> seen;
private final Set<File> seenSet = new HashSet<File>();
private final Object monitor = new Object();
public static int fileCount = 0;
#Autowired
private SourcePollingChannelAdapter sftpInbondAdapter;
public List<File> filterFiles(File[] files)
{
List<File> accepted = new ArrayList<File>();
for (File file : files) {
System.out.println(file.getName());
accepted.add(file);
}
return accepted;
}
public boolean accept(File file) {
synchronized (this.monitor) {
if (this.seenSet.contains(file)) {
logger.info(file.getName()+" is already copied earlier");
return false;
}
if (this.seen != null) {
if (!this.seen.offer(file)) {
File removed = this.seen.poll();
this.seenSet.remove(removed);
this.seen.add(file);
}
}
this.seenSet.add(file);
return true;
}
}
}
private final Queue<File> seen;
You are not initializing that field in a constructor.
You can't extend it like that; simply override the method like this...
public List<File> filterFiles(File[] files) {
for (File file : files) {
System.out.println("received:" + file.getName());
}
List<File> filtered = super.filterFiles(files);
for (File file : flteredFiles) {
System.out.println("after filter:" + file.getName());
}
return filteredFiles;
}

I can't make a basic project run with javaexe

I created a basic program in order to see how to make javaexe run;
The program has to be a windows service and should display a icon on the taskbar, when one click in the menu item, a messageBox is displayed.
But it does not run, especially the icon is not displayed.
Do you know why?
here are my files:
the service:
package service;
/**
* Created by User on 26/10/2014.
*/
public class Exemple_ServiceManagement {
static Corps app=null;
public static boolean serviceInit (){
app=new Corps();
return true;
}
public static void serviceFinish (){
app.setEnd(true);
}
public static String[] serviceGetInfo (){
return new String[]{"mon exemple","test","pas auto",
"1"};
}
}
the core part:
public class Corps extends Thread{
public boolean isEnd() {
return isEnd;
}
public void setEnd(boolean isEnd) {
this.isEnd = isEnd;
}
public boolean isEnd=false;
/*******************************************/
public Corps()
{
start();
}
/*******************************************/
public void run(){
while (!isEnd){
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
and the taskbar part:
public class Exemple_TaskbarManagement {
public static void taskInit() {
}
public static String[][] taskGetMenu(boolean isRightClick, int menuID) {
return new String[][]
{
{"1", "test" , "", ""},
};
}
public static void taskDoAction (boolean isRightClick, int menuID){
if (!isRightClick && menuID==1){
javax.swing.JOptionPane.showMessageDialog(null,"Menu cliqué");
}
}
public static String[] taskGetInfo (){
return new String[]
{
"JavaExe : mon exemple",
"",
"",
"",
""
};
}
}
finally, the output directory contains:
- the file "Exemple.exe" (the javaexe exe)
- the file "Exemple.jar", generated from the above sources, without manifest
- the file "Exemple.properties", here is it:
JREversion =
PersonalClasspath =
MainArgs =
MainClass =
PersonalOptions =
RunAsService =
RunType =1
ClassDirectory =
ResourceDirectory =
URL_InstallJRE =
Display_BoxInstall =
PathBrowser =
PathJRE =
my question is very simple : do you know what's going wrong?
thanks
olivier
ps : I had a look at the example files but I want to make a basic project, not take an other from somebody else, in order to understand what I do.

Resources