The following document walks you through the steps required to set up for development on all Web of Needs components, which are Java Spring applications deployed to a Tomcat server via Eclipse. Maven is used for dependency managment and building.
- Outline
- Building
- 1. Java SDK version 8 or newer
- 2. Eclipse for Java Enterprise Developers (4.7 Oxygen or newer)
- 3. Install Maven (3.3 or newer)
- 4. Git Clone to Your Eclipse Workspace
- 5. Import the Maven-project in Eclipse
- 6. Recommended Eclipse Settings
- 7. Maven install
- 8. On Windows: build-tools for project-local npm
- 9. Copy and Adjust Configurations
- 10. Download/Install the latest Tomcat 9 server
- 11. Add Tomcat to Eclipse
- 12. Update Connector-Statement in Tomcat's server.xml
- 13. Edit the Server Configuration in Eclipse
- 14. Generate cryptographic keys
- 15. Install the bouncycastle security provider and the trust manager
- 16. Start server
- Troubleshooting
- Tomcat complains about Missing Keystore
- Tomcat start fails with ClassNotFoundException: java.lang.ClassNotFoundException
- Maven build fails with NoClassDefFoundException: java/sql/SQLException
- Out of memory error
- icu4j: Invalid byte tag in constant pool
- won.protocol.exception.RDFStorageException: Could not create File!
- Port Bind Problem - Failed to initialize end point associated with ProtocolHandler
- maven dies in won-owner-webapp during 'clean' task
- java.security.NoSuchProviderException: no such provider: BC
- Exception in Owner-Webapp log: PKIX path building failed
Sources:
- Your package manager
- Oracle Java: https://www.oracle.com/technetwork/java/javase/downloads/index.html
- Open JDK: https://openjdk.java.net/
Things to mind:
- Make sure your
$JAVA_HOME
environment variable points to the folder it's installed in. - Make sure the Java-Binaries are on the system-path/
$PATH
- On Linux-distributions using
alternatives
, checkalternatives --list | grep java
and make sure you have the right SDK selected. You can change the configuration viasudo alternatives --config <alternative-name>
- On Linux-distributions using
Sources:
- https://www.eclipse.org/downloads/packages/ >> "Eclipse for Java Enterprise Developers"
- Your package manager. Check if there's a Java EE version.
If you installed from your package manager, ensure the following addons are also installed:
- Eclipse Java EE Developer Tools
- Eclipse Web Developer Tools
- m2e Maven Integration
You can check in Help >> Install New Software >> "What's already installed". If anything isn't you can select "Work With: All Available Sites" and then search, select and install the missing addons.
Sources:
- https://maven.apache.org/
- your package manager
If it's installed you should be able to run mvn -version
on the command-line.
Make sure it's on the system $PATH
.
Using your terminal (we recommend Git SCM if you're on Windows) run:
git clone https://github.com/researchstudio-sat/webofneeds.git
File >> Import >> Existing Maven Project >> select the (folder with) the pom.xml webofneeds/pom.xml
Troubleshooting: If you don't have the "Existing Maven Project"-option, make sure you have the addons mentioned in the eclipse section above.
Window >> Preferences >> General >> Workspace >> Build >> uncheck "Build automatically"
This increases performance.
Window >> Preferences >> Java >> Code Style >> Formatter
- Click
Import
- Select the file
webofneeds/won-buildtools/src/main/resources/eclipse/formatter.xml
- Click
Apply and Close
If you want to commit to our repositories, this step we'd ask you to do this.
In Eclipse:
- Right-click the webofneeds project in the Project Explorer Tab on the left side >> Maven >> Select Maven Profiles. Check
skip-tests
. - right-click "webofneeds" in project explorer >> Run As >> Maven Install
Or in your terminal:
mvn install -P skip-tests
This is required e.g. so the project-local npm exists for the next step, the required WAR-archives and JAR-files exist, etc.
Further information on what you can do with the maven-configuration can be found in ./maven.md.
When you the maven-install reaches the owner-application, the maven-frontend plugin will install it's own version of npm
. Using that run the following with admin permissions:
<PROJECT_ROOT>/webofneeds/won-owner-webapp/src/main/webapp/node/npm install -g windows-build-tools
If your Windows User does not have admin permissions, installing windows-build-tools
will unfortunately install them only for that user. (Further info at researchstudio-sat/webofneeds#1743) The Visual Studio build tools are installed correctly however, so you only need to fix your Python installation:
- Go to https://www.python.org/downloads/ and download and install Python 2.7 (Python 3 will not work!)
- Locate your Python installation, e.g.,
c:\Python27\python.exe
- With the same user that will execute the maven build, run
npm config set python c:\\Python27\\python.exe
(replace with your actual location, of course, and note the double backslashes).
-
Copy the webofneeds conf-folder:
cp -r conf conf.local
if you haven't done that already. -
Change all instances of
localhost
in the configurations to your your IP (or computer name or domain) if you are not going to run node owner or matcher locally. -
In
conf.local
, editmatcher-service.properties
,node.properties
andowner.properties
and change all instances of keystore/truststore locations to point to a folder where you will store generated keys and certificates (in ), e.g. I used/home/username/WoNKeystore/
). Do not change the file name, just the path. -
Change the accompanying passwords to something at least 6-letter long.
sources:
- https://tomcat.apache.org/download-90.cgi
- your system's package manager
- On Linux: You might need to add your user to the "tomcat" group (e.g. via
sudo usermod -aG tomcat myusername
). Check the permissions on your tomcat-installation/config-directory (e.g./usr/share/tomcat/
). Otherwise the integration process might throw an error that it couldn't read the configs. - Add Server view: Window >> Show View >> Server. When the server appears there, double clicking it will allow to open the config-GUI.
- Create Server in Eclipse: File >> New >> Other >> Server
- Choose Tomcat 9, then press "next" (not "finish")
- Make sure you use a Java 8 JDK or JRE, not java 9, or tomcat will not start up and throw a JAXB-related exception.
- Add node and owner and click finish
- If you do not have the options to add the owner and node application to the tomcat (also accessible via Server >> [your tomcat server] >> Add and Remove), something went wrong.
- Make sure to run maven install at least once
- right-click "webofneeds" in the project explorer >> Run As >> Maven install
- or in the command-line:
mvn install -P skip-tests
- Make sure the following project facets are active for the won-owner-webapp and won-node-webapp-projects (right-click project >> Properties >> search: "facets" >> activate facets):
- Dynamic Web Module
- Java
- JavaScript
- Do an eclipse build (Project >> Build All)
- Maybe the import of the webofneeds maven project somehow did not work properly. Delete all imported projects (without deleting the sources), then import again (File >> Import... >> Maven >> Existing Maven Projects )
- Maybe you did not install eclipse for Java EE. Check Help >> About Eclipse. If it does not say 'Eclipse Java EE IDE for Web Developers.', the easiest is to download and install Eclipse for Java EE.
- Make sure to run maven install at least once
- If you do not have the options to add the owner and node application to the tomcat (also accessible via Server >> [your tomcat server] >> Add and Remove), something went wrong.
Copy the SSL connector statement given below to <TOMCAT_FOLDER>/conf/server.xml
as a child of the <Service name="Catalina">
-node and change the password and key-folders there to values used in previous steps as well (e.g. "changeit"
, /home/username/WoNKeystore/t-cert.pem
, /home/username/WoNKeystore/t-key.pem
). If you already have a Connector
-statement, modify it accordingly. You can also access the conf in Eclipse if you've already added Tomcat there via Project Explorer >> Server >> "Your Server" >> open server.xml
.
<Service name="Catalina">
...
<Connector
SSLEnabled="true"
compressibleMimeType="text/html, text/xml, text/plain, text/css, text/javascript, application/javascript, application/x-font-ttf, image/svg+xml, text/turtle, application/rdf+xml, application/x-turtle, text/rdf+n3, application/json, application/trig, application/ld+json, application/n-quads"
compression="on"
disableUploadTimeout="true"
enableLookups="true"
maxThreads="200"
minSpareThreads="5"
port="8443"
protocol="org.apache.coyote.http11.Http11Nio2Protocol"
scheme="https"
secure="true">
<SSLHostConfig
certificateVerification="optionalNoCA"
certificateVerificationDepth="2"
trustManagerClassName="won.utils.tls.AcceptAllCertsTrustManager"
protocols="all">
<Certificate
certificateKeystoreFile="/home/username/WoNKeystore/t-keystore.jks"
certificateKeystorePassword="changeit"/>
</SSLHostConfig>
</Connector>
DoubleClick the server in the "Server View" and select:
Open launch configuration >> (x)= Arguments >> VM arguments * append the following, replacing the placeholders <PROJECT_FOLDER>
to the webofneeds project location and the <TOMCAT_FOLDER>
to the installation directory of your tomcat:
-DWON_CONFIG_DIR="<PROJECT_FOLDER>\webofneeds\conf.local" -Dlogback.configurationFile="<PROJECT_FOLDER>\webofneeds\conf.local\logback.xml"
Add the JSTL jar to your tomcat's classpath libs (or tomcat cannot be run in Serve modules without publishing
mode, see Server Options
below):
- Open Launch Configuration >> Classpath >> User Entries >> Add External JARs ...
- Navigate to your maven repository (default location:
$HOME/.m2/repository
; if it's not there, look into$HOME/.m2/settings.xml
) - find javax\servlet\jstl\1.2\jstl-1.2.jar
- if you don't find it
- build the whole project again via
mvn install -Dmaven.test.skip=true
or eclipse's maven integration (right-click on "webofneeds" >> Run As >> Maven Install). - try again
Like above, add all jars in webofneeds/target/required-libs
. This should include won-utils-tls-x.y-jar
.
In the Server overview (reachable via double-clicking the server in the servers-tab at the bottom):
- select "Server Locations >> Use workspace metadata".
- Server Options
- Serve modules without publishing _(allows for instant effect of changes)*
- Publish module contexts to separate XML files
- Modules auto reload by default
- Enable security
- Enable tomcat logging
- Publishing: Never publish automatically
- Timeouts: i.e. 180 + 30
- Ports: The ports should be shown for HTTP + SSL
Suppress unnecessary tag library (TLD) scans to speed up startup:
- In the eclipse navigator view, open Servers >> Tomcat 9.0 _(your server config)*
- edit
catalina.properties
- replace the value of the multi-line(!) property
tomcat.util.scan.StandardJarScanFilter.jarsToSkip
such that the line reads,tomcat.util.scan.StandardJarScanFilter.jarsToSkip=*.jar
- replace the value of the multi-line(!) property
tomcat.util.scan.StandardJarScanFilter.jarsToScan
such that the line reads,tomcat.util.scan.StandardJarScanFilter.jarsToScan=jstl-1.2.jar
Allow both webapps (owner-webapp and node-webapp) to start simultaneously:
- In the eclipse navigator view, open Servers >> Tomcat 8.0 _(your server config)*
- edit
server.xml
- find the xml element
<Host appBase="webapps" ...
and add the xml attributestartStopThreads="2"
NOTE: The following guide assumes you want to run all services on the same machine. If you deploy these on different machines, use the respective IPs and Paths as suited/desired.
-
We use the Apache Portable Runtime (APR) in the security modules of the Web of Needs. Normally, APR is included in the Tomcat by default, but it could happen (e.g. when you use the Tomcat for Windows installer) that it's not included. To be sure that you have APR, check your
<TOMCAT_FOLDER>/bin
. A DLL file calledtcnative-1.dll
MUST be there (if you're on Windows). On Linux it exist occur globally e.g. in/usr/local/apr/lib/libtcnative-1.a
- At least on Ubuntu 18 you might need to compile it for yourself, see the Ubuntu-installation notes
- NOTE: After all the configurations below are done, if you have problems starting the tomcat (cannot be started, or started with the default keys, or complains about key format), most probably the APR library is not set up. Check Tomcat documenentation for OS specific setup, e.g. http://tomcat.apache.org/tomcat-9.0-doc/apr.html. For Mac OS users this is helpful: http://mrhaki.blogspot.co.at/2011/01/add-apr-based-native-library-for-tomcat.html (Mac Ports have to be installed)
-
In the console navigate to the folder for the keystore created in previous steps (e.g.
/home/username/WoNKeystore/
), adapt(!) and run the following lines:openssl req -x509 -newkey rsa:2048 -keyout t-key.pem -out t-cert.pem -passout pass:changeit -days 365 -subj "/CN=myhost.mydomain.com" openssl pkcs12 -export -out sometmpfile_deletme -passout pass:changeit -inkey t-key.pem -passin pass:changeit -in t-cert.pem "$JAVA_HOME/bin/keytool(.exe)" -importkeystore -srckeystore sometmpfile_deletme -srcstoretype pkcs12 -destkeystore t-keystore.jks -deststoretype JKS -srcstorepass changeit -deststorepass changeit rm sometmpfile_deletme
NOTE: the openssl commands can be executed in windows using cygwin or the git bash
NOTE: If you're getting the error messageSubject does not start with '/'.
, change last parameter to-subj "//CN=myhost.mydomain.com"
-
The other key stores, and the trust stores are created and filled in automatically when the application is run (in the locations defined in step 4 with the passwords defined in step 5).
-
For Oracle Java 8: Depending on your java-setup it might not be able to generate keys of a relevant length. In that case, you need to download and install the Java Cryptography Extension. There's a readme in the zip detailing its setup. At the time of this writing, this consists of copying the two jars into
$JAVA_HOME/(jre/)lib/security
. If you don't do this or the jars are in the wrong folder, you'll get an exception likejava.security.InvalidKeyException: Illegal key size
when trying to run the app. Check out step 3 here for a more detailed guide. In OpenJDK the unlimted cryptography policy should be enabled by default.
NOTE: If you're re-deploying the project and want to use different digital certificates than previously used (e.g. by generate new ones according to step 8, or use your server certificates certified by a CA): in addition to replacing corresponding server certificate files and the broker's key store, you have to also delete (or empty) all the trust-store files used by the applications. Also, if you have deleted or replaced the owner keystore, and your deployment uses something other than the in-memory database, you have to empty this database as well -- the stored data related to owner registration at node has to be deleted.
NOTE: If you're running docker containers:
Deploy sripts for building and running web of needs as docker containsers (see webofneeds/webofneeds/won-docker/deploy*.sh
) include building and running server/broker certificate generation container gencert
. It generates self-signed certificates for the server with the specified name (or IP) protected with the specified password if there are no certificates already present in the mounted volume. The generated key and certificate are in pem format (for Tomcat server) and java keystore format (for broker). If you already have server certificate for your server, and they are in the required format, you don't need to run the gencert
. If you do want to generate and use self-signed certificate for your web of needs deployment, run it with changed parameters (server name and password), so that they correspond to your server name and to your desired password. Make sure that the same volume containing the certificate is mounted to the wonnode or owner container it is intended for. E.g. the location with the certificate of server.example.at
should be mounted when owner application is run as docker container if the owner is being deployed at server.example.com
. When using other than default file pathes and passwords for certificates, make sure that the same values are used in application properies files and in server.xml
.
NOTE: Inspecting keystores using keytool
: owner/node keystores are saved in bouncycastle's UBER format. keytool -list -v -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -storetype UBER -storepass <YOUR_KEYSTORE_PASSWORD> -keystore t-keystore.jks
Locate the JRE you are using with eclipse (Window -> Preferences -> Java -> Installed JREs
).
-
Navigate to the
[JRE]/lib/security
folder -
look for the
java.security
file in your JDK's folder structure (for Oracle Java it should be in$JAVA_HOME/lib/security
, in OpenJDK-12 it was in$JAVA_HOME/conf/security
) -
edit the file
java.security
-
find the
List of providers and their preference orders
, which looks like this:security.provider.1=sun.security.provider.Sun security.provider.2=sun.security.rsa.SunRsaSign security.provider.3=sun.security.ec.SunEC ...
-
add this line (replace
11
with the last number in the list plus one)security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider
- For Java 8: the contents of
[won-checkout-dir]/webofneeds/webofneeds/target/required-libs/
(which will be there after the first build) to the[JRE]/lib/ext/
folder - For Java >=9: add the contents of
[won-checkout-dir]/webofneeds/webofneeds/target/required-libs/
to the front of your class-path (support forlib/ext
has been dropped with java 9). If you're using Eclipse for the build, you can do so via "[Run Button] >> Run Configurations >> [tomcat run config name] >> Classpath >> select 'Bootstrap Entries' >> Add JARs"
(if you miss this step, you'll see BC exceptions when running the owner/node)
Select Server in the "Servers"-Tab at the bottom and click play (or right-click the server and press "play" in the context-menu)
SEVERE [main] org.apache.tomcat.util.net.jsse.JSSESocketFactory.getStore Failed to load keystore type JKS with path C:\Users\[username]/.keystore due to C:\Users\[username]\.keystore
java.io.FileNotFoundException: C:\Users\[username]\.keystore
Reason: we use tomcat APR. This means that in conf/server.xml
, the following line must be present:
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
and the apache tomcat native library needs to be installed. On Windows, this means you find the file tcnative-1.dll
in tomcats lib
folder, for more information, see http://tomcat.apache.org/native-doc/.
On linux you might need to build it for yourself, see "Ubuntu Installation Notes - Building TCNative](./ubuntu-installation-notes.md#building-tcnative)
Error configuring application listener of class [org.springframework.web.context.ContextLoaderListener]
java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
Reason: The Maven Dependencies are not defined in the Web Deployment Assembly of the Web Application project.
Solution:
- Right click on
won-owner-webapp
project >>Properties
>>Deployment Assembly
>>Add...
>>Java Build Path Entries
>>Maven Dependencies
. Project
>>Clean...
>> selectwon-owner-webapp
>> selectBuild only the selected projects
>>Clean
.- Do a maven install
- Right click on server >>
Publish
>>Start
Turns out that you need to have a JDK installed. Download a recent JDK and tell eclipse to use that one by default: Window >> Preferences >> Java >> Installed JREs
. For me, Jdk11 did not work, but Jdk8u202 did.
If you run your project and encounter a "Out of memory" error you should probably add this to your run configuration: -XX:MaxPermSize=128M
. This should only be necessary if you use JDK 1.8.
If you get a compile error like below you can just ignore it. There is a corrupt .class
file in the maven dependencies and will go away with future updates and everything is OK untill you use it, but you won't. This will only affect Chinese speaking users since it is the LocaleElements_zh__PINYIN.class
file for Pinyin.
Another possibility is to find the icu4j .jar
file and delete the LocaleElements_zh__PINYIN.class
file. This is a quick and dirty hack, but it works.
Apr 16, 2013 2:07:59 PM org.apache.catalina.startup.ContextConfig processAnnotationsJar
SEVERE: Unable to process Jar entry [com/ibm/icu/impl/data/LocaleElements_zh__PINYIN.class] from Jar [jar:file:/C:/DATA/atus/Code/webofneeds/webofneeds/won-node-webapp/target/won/WEB-INF/lib/icu4j-2.6.1.jar!/] for annotations
org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 60
at org.apache.tomcat.util.bcel.classfile.Constant.readConstant(Constant.java:133)
at org.apache.tomcat.util.bcel.classfile.ConstantPool.<init>(ConstantPool.java:60)
More info about this error can be found at:
- http://stackoverflow.com/questions/6751920/tomcat-7-servlet-3-0-invalid-byte-tag-in-constant-pool
- http://maven.40175.n5.nabble.com/Problem-when-mvn-site-site-Generating-quot-Dependencies-quot-report-td113470.html
- http://jira.codehaus.org/browse/MPIR-142
This means that Tomcat could not access the temp directory where it stores the .ttl
files. This is either the TMP
global variable or the %tomcat_dir%/tmp
directory. The problem is that if you're on Windows and installed Tomcat in C:/Program Files/
. Unless you are an admin you will not have access to any of these.
You can either grant your user access to one of these directories or change the directory in won-node/src/main/resources.localhost/
by changing the rdf.file.path
.
Check the error message for the actual directory in question. Expect something like
Caused by: java.io.FileNotFoundException: C:\Program Files\apache-tomcat-7.0.35\temp\1.ttl (Access denied)
org.apache.coyote.AbstractProtocol.init Failed to initialize end point associated with ProtocolHandler ["http-apr-8443"]
This problem or other similar errors that can be referred as "port bind problems" are causd by setting the port that is used by WoN-node or WoN-webapp in the Tomcat Server Settings of IntelliJ. Leave the field "HTTP port" in the "Run/Debug Configurations" free (the default is 8080 and does not cause any problem).
stating that 'node' was not found.
solution: run mvn install
before mvn clean
Make sure you've gone through the steps in "Install the bouncycastle security provider and the trust manager".
If this error still occurs, it could happen that Tomcat can't find or access the the bc .jar
files during startup. Below is a collection of actions that may fix the problem and places to copy the .jar
files into. You may want to try them both separately and combined to find a setup that works for you.
You should be able to find both bcpkix-jdk15on-1.52.jar
and bcprov-jdk15on-1.52.jar
in your maven directory (default location is: C:/Users/[user name]/.m2/repository/org/bouncycastle/
). If not, build the whole project with mvn install -Dmaven.test.skip=true
and check again.
- in Eclipse, edit the server launch configuration properties (accessible via "Run As...") and add both
.jar
files as External JARs to User Entries (suggested in: Building, Step "Add the JSTL jar to classpath") - copy both
bcpkix-jdk15on-1.52.jar
andbcprov-jdk15on-1.52.jar
to%tomcat_dir%/lib/
(suggested in: Crytpographic Keys and Certificates, Step 11) - copy both
bcpkix-jdk15on-1.52.jar
andbcprov-jdk15on-1.52.jar
toC:/Program Files/Java/[jre dir]/lib/ext/
and install the bouncy castle security provider (suggested in: issue#1393) - In the Tomcat server's
server.xml
, find the xml element<Host appBase="webapps" ...
and add the xml attributestartStopThreads="2"
- NOTE: This only has an effect if two or more webapps, e.g. a node and an owner, are started on the server.
This happens when the webapp uses a different public key than the activemq http endpoint.
We have seen this happen in two different ways:
- The keys in the pem files and in the jks files are identical, but they were changed since the applications were started - most likely by a letsencrypt certificate renewal.
- There are different keys in the pem files than in the jks and pfx files
If you suspect 1 might be the case, just restart the docker containers. If the problem goes away, that's what it was.
In case 2, probably the certificate renewal updated the pem files but did not update the jks and pfx files. The consequence is that the node webapp uses the new key (as nginx loads the pem file) and the activemq server uses the old key (as it loads the jks file).
To check if this is the problem: list the keys in the jks/pfx file (using keytool -list -v -keystore t-keystore.pfx
) and compare them to the key information available for, eg. https://{your-won-node}/won/resource
in the browser or some other http client. If the keys are the same, this is not the problem.
To fix this: overwrite the jks and pfx files by exporting the key from the pem file. This can be done by executing the openssl
and keytool
commands in the letsencrypt's container script certificate-request-and-renew.sh