How to set the the main theme at build or deploy time? - java

I look for way in Vaadin Flow & Spring Boot to set the main theme at build time or via properties, but it is not working. Any ideas how it can be achieved?
Background: I have an application which I like to have the same code but deployed on different domains with different theme.
I tried to use a property from Spring Boot "application.properties" like "theme=my-vaadin-app", but this seems not to be supported. So any other way to set the theme at build or deploy time?
#SpringBootApplication
#Theme(value = "my-vaadin-app") // the usual way
#Theme(vaule = "${thene}") // NOT Working
public class MyVaadinApplication implements AppShellConfigurator {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
SpringApplication.run(MyVaadinApplication .class, args);
}

The theme is included in the optimized client-side bundle that is created as part of the production build.
If there are only small differences between your different theme variants, then you can include support for all of those variants in the same theme with CSS selectors for different classnames. You can then only change the classname at runtime while always using the same CSS content.
The other alternative is that you create separate builds for separate cases.

Related

Eclipse autocompletion for jdk.* packages does not work

I write here because I noticed a strange behaviour of Eclipse IDE (2022-12).
Basically, the autocompletition does not work properly when I use a class from a jdk.* package.
For example:
import jdk.jshell.*;
public class Test {
private static final JShell JSHELL = JShell.create();
...
...
public static void main(String[] args) {}
}
Now when I write JSHELL. (e.g., inside the main method), I get only proposal for the methods of the Object class. No specific proposal is available.
What am I doing wrong?
Thanks.
Tried updating & reinstalling Eclipse.
jdk.* is filtered by default.
When you want to use something of jdk.* in a project, go to the preferences Java > Appearance > Type Filters and uncheck the item jdk.*.

Changing FavIcon in Vaadin using pure Java alongside Springboot

I want to change the favicon of the website in Vaadin that is combined with Springboot. I have also opted to go the pure Java route within Vaadin (no html page).
I followed this guide, which explains that the icon I wish to use should be added in the src/main/webapp/icons folder where it will be automatically picked up, resized, etc.
I tried that to no avail, after which I found this thread and subsequently this one. The latter link especially explains that Spring-boot has its own directories and that the webapp folder should be avoided. I tried using the spring directories, but again to no avail.
My resources folder currently looks as such:
My MainView as such:
#Route
#PageTitle("My new title")
public class MainView extends VerticalLayout {
And my SpringBootApplication class as such:
#SpringBootApplication
public class MyVaadinApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(MyVaadinApplication.class, args);
}
}
The icon still remains the default spring leaf:
Where am I going wrong in trying to set the favicon?
Add icon.png to resources/META-INF/resources/icons/icon.png
Then:
If you are use progressive web app (#PWA annotation) it should already work
If you are use simple vaadin application you should to implements PageConfiguration and add link to your favicon.
#Route("favicon")
public class FaviconTest extends Div implements PageConfigurator {
#Override
public void configurePage(InitialPageSettings settings) {
HashMap<String, String> attributes = new HashMap<>();
attributes.put("rel", "shortcut icon");
attributes.put("type", "image/png");
settings.addLink("icons/icon.png", attributes);
}
}

Is there a way to update modular library without updating main application?

Before modular application organization, I had one main JavaFX application that load custom created multiple libraries for different options and possibilities in main app.
In old way of implementation, I just send new library to update, main application reads all libraries from folder and it works like a charm. But in a modular system, if my application wants to use new modular library that I send, it needs to update its module-info file, apropos I need to send updates for modular library and for main application.
Just imagine, it would be like, chrome need to send browser update for every new plugin that is created. As I can see, with Java modularity system you can't create modular applications.
Is there a way import new module without updating main application or some other way around?
Java has a class for that: ServiceLoader.
If we assume you have a “service provider” interface named PluginProvider, other modules can declare themselves to provide that service by putting this in their respective module-info.java descriptors:
provides com.john.myapp.PluginProvider with com.library.MyProvider;
Your application would then state that it uses that service in its own module-info:
uses com.john.myapp.PluginProvider;
And your application’s code would create a ModuleFinder that looks in the directory (or directories) where you expect those plugin modules to reside, then pass that ModuleFinder to a Configuration which can be used to create a ModuleLayer for the ServiceLoader:
public class PluginLoader {
private final ServiceLoader<PluginProvider> loader;
public PluginLoader() {
Path pluginDir = Paths.get(System.getProperty("user.home"),
".local", "share", "MyApplication", "plugins");
ModuleLayer layer = PluginProvider.class.getModule().getLayer();
layer = layer.defineModulesWithOneLoader(
layer.configuration().resolveAndBind(
ModuleFinder.of(),
ModuleFinder.of(pluginDir),
Collections.emptySet()),
PluginProvider.class.getClassLoader());
loader = ServiceLoader.load(layer, PluginProvider.class);
}
public Stream<PluginProvider> getAll() {
return loader.stream();
}
public void reload() {
loader.reload();
}
}
You might even want to watch the plugin directory for new or removed files:
try (WatchService watch = pluginDir.getFileSystem().newWatchService()) {
pluginDir.register(watch,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.OVERFLOW);
WatchKey key;
while ((key = watch.take()).isValid()) {
loader.reload();
key.reset();
}
}

Using SystemLoader / SpringFactoryLoader to load external Jar in Spring-Project

first: I'm really new to spring-boot and maven. So I still don't get how everything plugs together.
What I'm trying to achieve is some kind of plugin-feature for my application. From my research it seems the best way to do this is using ServiceLoader or the spring-boot implmentation of the SpringFactoriesLoader.
According to several instructions from the web I put two projects together
James (the main application) GitHub
TemperatureSensor (the plugin) GitHub
The JamesApplication provides an interfaces which is supposed to be implemented (de.maxrakete.james.device.domain.DeviceInterface).
The TemperatureSensor implements said class and exposes this in several ways.
For the ServiceLoader in in the file META-INF\services\de.maxrakete.james.device.domain.DeviceInterface with this content
de.maxrakete.james.plugin.TemperatureSensor.TemperatureSensor
For the SpringFactoriesLoader in the file META-INF\spring.factories with this content
de.maxrakete.james.device.domain.DeviceInterface=de.maxrakete.james.plugin.TemperatureSensor.TemperatureSensor
According to this page I tried two different implementations (see in the onApplicationEvent-function) in the MainApplication:
#SpringBootApplication
public class JamesApplication implements ApplicationListener<ApplicationReadyEvent> {
public static void main(String[] args) {
SpringApplication.run(JamesApplication.class, args);
ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader)cl).getURLs();
for(URL url: urls){
System.out.println("Classpath file: " + url.getFile());
}
}
#Override
public void onApplicationEvent(ApplicationReadyEvent event) {
ServiceLoader<DeviceInterface> loader = ServiceLoader.load(DeviceInterface.class);
loader.iterator();
List<DeviceInterface> foos = SpringFactoriesLoader.loadFactories(DeviceInterface.class, null);
}
}
I'm trying both ways to load the jar, but nothing is happening (I'm supposed to get some log-messages from the plugin) but this is not happening.
The way I'm running the application is like this:
java -cp "./plugins/TemperatureSensor-0.0.1-SNAPSHOT.jar" -jar james.war
As you see I'm trying to add the jar in the subfolder to the classpath, but in the ouput of the main-function (where I try to print all the files in the classpath) I only get Classpath file: /home/max/folder/james.war
Conclusion
So, there are three possible error-sources
Wrong cli command to add classpath files
Wrong declaration of interfaces in the META-INF folder
Wrong implementation of the Loader
Maybe I'm compiling the sources the wrong way?
Wrong configuration of the pom.xml
I really have no idea what the problem might be. I tried to provide you with as much information as possible and all the steps of my research. I hope someone finds some helpful clues, which I might have overlooked.
Thanks veryone!

How to manage required, conflicting Java dependencies

Say I need (its required) to use fizz-1.0.jar and buzz-2.3.2.jar in my Java project. Now, fizz-1.0.jar depends on foo-0.1.35.jar, and buzz-2.3.2.jar depends on foo-4.2.17.jar.
foo-0.1.35.jar contains a Widget class like so:
public class Widget {
public int doSomething(int x) {
return x++;
}
}
foo-4.2.17.jar contains a heavily modifed version of Widget:
public class Widget {
public Meh makeStuff() {
return new Meh();
}
}
Unfortunately, both fizz-1.0.jar and buzz-2.3.2.jar make heavy use of both versions of Widget.
I can't just blindly add both versions of foo-x.y.z.jar to the classpath, because whichever Widget gets loaded first will only work for either fizz-1.0.jar or buzz-2.3.2.jar.
What are my options here? Remember I must have both fizz-1.0.jar and buzz-2.3.2.jar, and must satisfy all of their transitive dependencies.
I would recommend that you use a framework which distinguishes class loads.
E.g. OSGi framework. Then you can create 2 bundles - one with the fizz implementation and one with the buzz implementation. They both can contain their dependent libraries which do not conflict anymore because they are loaded from 2 different classs loaders.
Example osgi containers or "Eclipse Equinox" and "Apache Felix" but there are more.
Hope that helps.

Categories

Resources