I split my java web application in a few modules. I have five modules: model, services, util, rest and web-app. Now each of these modules use resources, for example in the web-app module there are a few images, in the service module there are a jasper files ....
I want to ask you what is the best place to put these resources? I saw a few plugin like maven-shared-resources
maven-shared-resources
Is this a used strategy to manage different kind of resources in a maven modular project?
I ask you this why I'm not able not get a few resources from a model
I use a few resource contained in the util module for the login . My trouble is that when i call the class contained also it in the util module from the web-app module i get a FileNotFoundException why it try to get a resource from the util-module.jar.
I use the following line code to try to get a resource
InputStream inStr = getClass().getResourceAsStream( "/myFile.jks");
Related
I have been working on a software with a plugin based system, where users can write their own plugins. I am very new to JMPS, but I would like to make this using JMPS and not OSGi. Made a separate API module and even created a Test Plugin.
The plugins are stored with the filename "someplugin.jar" in a directory.
How do I load all these jars (none of them are automodules but well-defined modules with module-info.class) during runtime? The reason I want to load them dynamically during runtime is that the user will be having an option to change the directory to search for plugins, and change it without having to restart the application.
To load modules dynamically, you need to define a new ModuleLayer. The new module layer will inherit the boot layer:
This means that in your boot layer (where your main module is), you cannot directly refer to classes in the plugins layer. However, you can use your plugins layer through services.
Here is the code that you can use as a starting point:
Path pluginsDir = Paths.get("plugins"); // Directory with plugins JARs
// Search for plugins in the plugins directory
ModuleFinder pluginsFinder = ModuleFinder.of(pluginsDir);
// Find all names of all found plugin modules
List<String> plugins = pluginsFinder
.findAll()
.stream()
.map(ModuleReference::descriptor)
.map(ModuleDescriptor::name)
.collect(Collectors.toList());
// Create configuration that will resolve plugin modules
// (verify that the graph of modules is correct)
Configuration pluginsConfiguration = ModuleLayer
.boot()
.configuration()
.resolve(pluginsFinder, ModuleFinder.of(), plugins);
// Create a module layer for plugins
ModuleLayer layer = ModuleLayer
.boot()
.defineModulesWithOneLoader(pluginsConfiguration, ClassLoader.getSystemClassLoader());
// Now you can use the new module layer to find service implementations in it
List<Your Service Interface> services = ServiceLoader
.load(layer, <Your Service Interface>.class)
.stream()
.map(Provider::get)
.collect(Collectors.toList());
// Do something with `services`
...
Module layers are considered an advanced topic but I don't find it really difficult. The only key point you need to understand is that module layers are inherited. This means that from a child layer, you can only refer to classes of the parent layer but not vice versa. To do the opposite, you have to use the inversion of control which is implemented in the Java module system by ServiceLoader.
I'm working on a multi module spring-boot project to build a REST API. Here is my project structure:
Parent project (packaging is pom)
core module (#SpringBootApplication + handle path like / or /status)
restControllerA module (Handle path like /routeA/*)
restControllerB module (Handle path like /routeB/*)
Everything is working in this project :)
In another non Spring project I would like to reuse a service of restControllerB. This service return the result of the request body validation.
First I try to add the restControllerB.jar as a dependency to this new project... But this jar does not contain its depedencies (who are in the fatJAR "core.jar"). When I run the project, I get a lot of ClassNotFoundException.
How can I manage to reuse this service as a dependency ? I thought to create a validator module which implements the validatorService interface, but I'm not sure if it is the best solution.
After few hours googling, It seems that creating an external librairy is the right choice. I create an external module and add it as a dependecy to restControllerB.
I'm learning to make Java MVC project using Spring Tool Suite tool.
The path to make new project is:
File->New->SpringLegacyProject->Spring MVC Project.
My question is: which directory I have to use to add additional not-Spring files and where and what do I have to type for Spring files to see them?
For example:
css files - where to put and how to make jsp views see them, will 'link rel="" 'tag be enough?
properties files used to specify database connection or to specify messages for ReloadableResourceBundleMessageSource. In this case, do I have to create bean for this class in root-context.xml?
Thanks.
You should probably use Spring Boot (i.e. use File->New->Spring Starter Project and select Web as a starter. Place your web resources under src/main/resources/static folder. They are picked up automatically from that folder.
You should try an example project: File -> New -> Import Spring Getting Started Content and then pick "Serving Web Content" from the list.
Try some DB getting started content example to get the answer for the second part of your question.
I'm trying to find out if we can load a oracle commerce component from file system. Generally we assemble all the code into an ear file and deploy it, however, I got a requirement where in I have to store some components in file system rather than packaging them along with ear file.
I know that we can use URLClassloader to load a class as shown below,
File classDir = new File("A:\\LodeeModule\\classes");
URL[] url = { classDir.toURI().toURL() };
ClassLoader loader = new URLClassLoader(url);
for (File file : classDir.listFiles()) {
String filename = file.getName().replace(".class", "");
loader.loadClass("com.buddha.testers." + filename).getConstructor().newInstance();
}
but how can we use the same for an component which has to be resolved by Nucleus at later point of time? Is there any way to instruct Nucleus to resolve component from file system?
You should just be able to add the JAR that contains the components classes to the CLASSPATH system variable used by the application server instance.
Then in the component configuration just define the implementing class as you normally would
$class=some.class.path.class
If you are using Jboss EAP 6+ on a newer version of ATG (11.0+) you might have some more trouble, you have to jump through some more hoops due to its classloader
https://docs.jboss.org/author/display/AS7/Class+Loading+in+AS7
Essentially you would need to define a jboss module containing your jar files, and define a dependency between the ear's "module" and the module containing your classes.
Alternatively you can define a ClassLoaderService that will manage the classes for your JARs
To do this, you need to define a new ClassLoaderService, so create a new properties file as you would with any other component.
/my/custom/ClassLoaderService.properties
$class=atg.nucleus.ServicesManifestClassLoaderService
$description=Custom Class Loader Service.
# The files to go into the classpath of the classloader
classpathFiles=\
/path/to/my/jars/lib/someClasses.jar,\
/path/to/my/jars/lib/someOtherClasses.jar
loggingDebug=false
Then in the actual component that you need these classes for add this line;
$classloader=/my/custom/ClassLoaderService
I think you're looking for the atg.dynamo.data-dir property. If you specify that property dynamo will look at that location for the "server configs" or properties files. This allows you to separate the configs from the ear file.
Note: You can still include configs in the ear, I believe they will still have first precedence
It's usually specified when you start the server, something like:
run.sh -c <your server> -Datg.dynamo.data-dir=/data/something/serverconfigs
This feature is largely undocumented, but many people know about it.
See http://docs.oracle.com/cd/E24152_01/Platform.10-1/ATGPlatformProgGuide/html/s0302developmentmodeandstandalonemode01.html
EDIT:
I mistook what you were originally asking. You might want to take a look at the disposable class loader that ATG provides, but keep in mind this is only intended for development purposes.
We have the following scenario with our project:
A core web application packaged as a
war file (call it Core project).
The need to "customize" or "extend" the core app
per customer (call it Customer project). This mostly includes
new bean definitions (we're using
Spring), ie. replacing service
implementations in the core.war with
customer-specific implementations.
We want to develop the Core and Customer projects independently
When the Customer project is developed, we need to be able to run/debug it in Eclipse (on Tomcat) with the Core project as a dependency
When the Customer project is built, the resulting war file "includes" the core and customer projects. So this .war is the customer-specific version of the application
I'm looking for suggestions as to the best way to do this in terms of tooling and project configuration.
We're using Ant currently, but would like to avoid getting buried in more ant. Has anyone done this with Maven?
I've seen a lot of posts on how to build a web application that depends on a java application, but nothing on a web application depending on another web app.
Thanks!
Sounds like Maven WAR overlay does what you want.
In Eclipse there is a "native" WTP way to do this. It mainly using linked folders and a little hack in .settings/org.eclipse.wst.common.component file. You can read the article about it at http://www.informit.com/articles/article.aspx?p=759232&seqNum=3 the chapter called "Dividing a Web Module into Multiple Projects". The problem with this is that the linked folder must be relative to some path variable can be defined in Window/Preferences/General/Workspace/Linked Resources tab. Otherwise the linked folder definition (can be found in .project file in project root) will contain workstation specific path. The path variable practicly should be the workspace root. This solution works great with WTP, deploy and everything else works like it should.
The second solution is to use ant for it. Forget it. You will deeply regret it.
The third solution is to use maven for it. You can forget the comfort of WTP publishing if you dont do some tricks. Use war overlays like others suggested. Be sure to install both m2eclipse, m2eclipse extras. There is an extension plugin released recently, that can help you. Described at this blog. I did not try it, but looks ok. Anyway Maven have nothing to do with linked folders, so I think even the first solution and this maven overlay can live together if necessary.
As for headless builds you can use HeadlessEclipse for the first solution. It is dead (by me) now, but still works :). If you use the maven overlay + eclipse stuff, headless builds are covered by maven.
This is little bit more involved but at a high-level we do it as below. We have the core platform ui divided to multiple war modules based on the features (login-ui,catalog-mgmt-ui etc). Each of these core modules are customizable by the customer facing team.
We merge all of these modules during build time into 1 single war module. The merge rules are based on maven's assembly plugin.
You usually start from the Java source code. WARs don't include the Java source code, just the compiled classes under WEB-INF/classes or JARs under WEB-INF/libs.
What I would do is use Maven and start a brand new empty webapp project with it: http://maven.apache.org/guides/mini/guide-webapp.html
After you have the new empty project structure, copy the Java source code to it (src/main/java) and fill out the dependencies list in pom.xml.
Once you've done all this you can use mvn clean package to create a standard WAR file that you can deploy to Tomcat.
You might want to look into designing your core app with pluggable features based on interfaces.
For example say your core app has some concept of a User object and needs to provide support for common user based tasks. Create a UserStore interface;
public interface UserStore
{
public User validateUser(String username, String password) throws InvalidUserException;
public User getUser(String username);
public void addUser(User user);
public void deleteUser(User user);
public void updateUser(User user);
public List<User> listUsers();
}
You can then code your core app (logon logic, registration logic etc) against this interface. You might want to provide a default implementation of this interface in your core app, such as a DatabaseUserStore which would effectively be a DAO.
You then define the UserStore as a Spring bean and inject it where needed;
<bean id="userStore" class="com.mycorp.auth.DatabaseUserStore">
<constructor-arg ref="usersDataSource"/>
</bean>
This allows you to customise or extend the core app depending on specific customer's needs. If a customer wants to integrate the core app with their Active Directory server you write a LDAPUserStore class that implements your UserStore interface using LDAP. Configure it as a Spring bean and package the custom class as a dependant jar.
What you are left with is a core app which everyone uses, and a set of customer specific extensions that you can provide and sell seperately; heck, you can even have the customer write their own extensions.