Java compilation basics
![]()
These are here because I am switching between different languages a lot at the moment, and I trip up over basics from time to time! Place these files in the indicates directory and they will compile and run. "comp.sh" is what I always call a little unix shell-script to compile and run something. I usually create one before getting into Make or Ant or whatever a language uses, to check things actually work!
![]()
simple.java:
public class simple
{
public static void main(String [] args) {
System.out.println("hello");
}
}
Remember that class name must be the same (including case) as the file name.
comp.sh:
# echo "Compile and run simple.java" javac simple.java java simple
simple2.java:
/*
* Note that to run this, the .class must be in directory ./samples/mypackage
*/
package samples.mypackage;
public class simple2
{
public static void main(String [] args) {
System.out.println("hello");
}
}
comp.sh:
# echo "Compile and run simple2.java" echo "Since this involves a package, it involves a directory structure" rm samples/mypackage/* javac simple2.java cp simple2.class samples/mypackage java samples.mypackage.simple2
(The compilation creates the directory structure for the package)
simple3.java (Unchanged):
/*
* Note that to run this, the .class must be in directory ./samples/mypackage
*/
package samples.mypackage;
public class simple3
{
public static void main(String [] args) {
System.out.println("hello");
}
}
comp.sh:
# echo "Compile and run simple3.java" echo "Since this involves a package, it involves a directory structure" rm -rf samples javac simple3.java mkdir samples mkdir samples/mypackage cp simple3.class samples/mypackage java samples.mypackage.simple3 # echo "Jar it up, delete directory and run jar" echo "Using the jar means using a classpath" jar cf samples.jar samples rm -rf samples java -cp samples.jar samples.mypackage.simple3
This creates the jar and runs the class from it.
simple4.java (unchanged):
/*
* Note that to run this, the .class must be in directory ./samples/mypackage
*/
package samples.mypackage;
public class simple4
{
public static void main(String [] args) {
System.out.println("hello");
}
}
build.xml (for ant):
<?xml version="1.0" ?>
<project default="buildAll">
<target name="buildAll" depends="clean, compile, makedirs, jar, run">
<echo message="Finished building and running the jar file" />
</target>
<target name="compile">
<javac srcdir="." debug="true"/>
</target>
<target name="makedirs">
<!-- mkdir creates parent dirs if they do not exist -->
<mkdir dir="samples/mypackage"/>
</target>
<target name="jar" depends="makedirs, compile">
<copy file="simple4.class" todir="samples/mypackage" />
<jar destfile="samples.jar" basedir="." includes="samples/mypackage/*" />
<!-- If you get the jar command wrong, you still get a jar, but one that has no .class files.
Check the contents of the jar with:
jar tf samples.jar
-->
<exec executable="jar" >
<arg line="tf samples.jar" />
</exec>
</target>
<target name="run" depends="jar">
<echo message="Run the jar" />
<java classname="samples.mypackage.simple4" classpath="samples.jar" />
</target>
<!-- - - - - - - - - - - - - - - - - -
target: clean
- - - - - - - - - - - - - - - - - -->
<target name="clean">
<delete verbose="true" failonerror="false">
<fileset dir=".">
<include name="*.class" />
</fileset>
</delete>
<delete file="samples.jar" />
<delete dir="samples" />
</target>
</project>
Hmm. Snappy it isn't. But it does the same as the shell-script above.
Here's a shell script that creates index.jsp (containing 1 line of stuff), the web.xml needed, and then creates and deploys a war file containing it.
create.sh:
#
# From http://access1.sun.com/techarticles/simple.WAR.html
#
echo "== Clean =="
rm -rf *.jsp *.war
rm -rf WEB-INF
rm -rf ~/apache-tomcat-5.5.17/webapps/mywar ~/apache-tomcat-5.5.17/webapps/mywar.war
echo "== Create simple index.jsp =="
echo '<%
out.println("Running a simple jsp");
%>' > index.jsp
echo "== Create WEB-INF directory =="
mkdir WEB-INF
mkdir WEB-INF/classes
mkdir WEB-INF/lib
echo "== Create empty deployment descriptor =="
echo '<web-app>
<display-name>Simple war</display-name>
<welcome-file-list id="WelcomeFileList_1">
<welcome-file>displayStatus.jsp</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>' > WEB-INF/web.xml
echo "== Create war =="
jar cvf mywar.war WEB-INF *.jsp
echo "== Display contents of war =="
jar tf mywar.war
echo "== Copy to apache_home/web_apps to deploy it =="
cp mywar.war ~/apache-tomcat-5.5.17/webapps
cp index.jsp ~/apache-tomcat-5.5.17/webapps/ROOT/simple.jsp
echo " Now try to connect to http://127.0.0.1/mywar"
The manual is complete rubbish. All you do is this:
Create a WSDL in eclipse using WTP
Generate your stubs using wsdl2java.
Compile these to classes (i.e. src/com/gsk/cix/*.java to build/com/gsk/cix/*.class)
Jar the classes up (jar build/*)
Copy the jar file into {tomcat_home}/webapps/axis/WEB-INF/lib
Add an entry to the server-config.wsdd file in {tomcat_home}/webapps/axis/ to tell axis what the entry point of your classes is.
Then it just works, and appears on happyaxis.jsp.
The thing to remember is that Axis is a web application itself. All you're doing is sticking an extra jar or two in its lib directory, and then editing the config file so that Axis knows what the entry point is.
The stubs generated are mostly gunk, which could just as well be jarred up and forgotten. The one that contains your methods -- the ones you chose when you generated the WSDL -- is ~~~impl.java. Put your own code in another file, and just call it from there (so you can regenerate the impl file if you add more methods).
The following contains a simple axis project, with the axis 1.3 jars and various other jars in the lib dir. It should all compile and run from the build.xml.
This is simple enough.
Download axis-2.1.1.1 to your PC, and unpack it to c:\axis-2.1.1.1
Make sure that the environment variable AXIS2_HOME points to it
Make sure AXIS2_HOME/bin is in the path
Create a temporary directory c:\grot, and copy the wsdl to it
In that directory do:
wsdl2java -uri mywsdl.wsdl
You get a directory com in c:\grot. This works because there is a wsdl2.java.bat in your AXIS2_HOME with paths etc.
What's in here is two files, a mywsdlStub.java and a callback handler. To run the client, you will instantiate mywsdlStub.java from a runner class.
The runner.java is thus to run CISStub.java:
import com.gsk.cix.CISStub;
import com.gsk.cix.CISStub.ListDatabases;
import com.gsk.cix.CISStub.ListDatabasesResponse;
import com.gsk.cix.CISStub.SubStructureSearch;
import com.gsk.cix.CISStub.SubStructureSearchRequest;
import com.gsk.cix.CISStub.SubStructureSearchResponse;
import com.gsk.cix.CISStub.ArrayOfString;
import com.gsk.cix.CISStub.SearchResult;
/**
* http://ws.apache.org/axis2/1_1_1/userguide-creatingclients.html#createclients
* @author wrp43058
*
*/
public class runner {
public static void main(String[] args) {
try{
CISStub _cis = new CISStub("http://hlwus010.corpnet2.com:5603/cis"); // Link to the service
ListDatabasesResponse _reply = null;
_reply = _cis.ListDatabases( new ListDatabases() ); // ListDatabases has no parms, but axis wants an empty object, so pass one. null does NOT work
for (String x : _reply.getDatabases().getString() ) // This method gets back an array of strings; loop around them
{
System.out.println(x);
}
} catch(Exception e){
e.printStackTrace();
}
}
}
You have a directory com containing Java source files (e.g. after doing WSDL2Java). How to get these into eclipse and compiling?
Start eclipse, in the Java perspective
Do File|New|Java Project, give it a name myproject. When it prompts, get it to create a source folder src. Make sure output goes to bin, not to myproject. Press Finish.
In Windows Explorer, copy the com directory to the workspace/myproject/src folder.
In Eclipse, refresh -- the package should now appear in the Navigator.
If this is Axis, you need to tell the project where the Axis jar's are -- right click on the project, Build Path|Configure Build Path, libraries (? something like this), add external jars, and browse to the Axis home directory and select the lot. Alternatively first copy them all to a lib directory in the project, and do the same exercise pointing to there.
Right click on the project and do "Build Project". The whole thing will now build.
If you want to include the runner.java file above, just create that by right-clicking on project, New|Java class, call it runner and put it in a new Runner package, or alternatively just drop it into src.
You need a standard log4j.properties file which you drop into the root of a project. This then pipes the output to a file in the format specified. Here is one:
log4j.rootLogger = DEBUG, File
#File--4 File Appender
log4j.appender.File=org.apache.log4j.FileAppender
log4j.appender.File.File=./log.out
log4j.appender.File.Append=false
#File -- layout for File appender
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.conversionPattern=%n%d{yyyy-MM-dd,HH:mm:ss,SSS} %-5p: %c.%M %m
log4j.appender.FIle.layout.TreadPrinting=true
log4j.appender.FIle.layout.ContextPrinting=false
log4j.appender.FIle.layout.CategoryPrefixing=false
You can specify the level (here DEBUG); the file name (here log.out) and whether File or Console.
Download here.
You need to add it to JUnit test case thus:
import java.io.File; import org.apache.log4j.PropertyConfigurator; public class EISWebRendererTransformListTest extends TestCase { protected void setUp() throws Exception { PropertyConfigurator.configure("." + File.separator + "log4j.properties"); } ...
Can also do DefaultConfigurator() with no parms, which just pipes to stdout.
One very effective method that requires no log4j.properties at all is to include the following in your JUnit setup. This really did suppress everything from org.hibernate jars.
// Suppress all the crud
BasicConfigurator.configure();
Logger.getLogger("org").setLevel(Level.ERROR);
Logger.getLogger("com.gsk").setLevel(Level.ERROR);
If you get this:
log4j:WARN No appenders could be found for logger (com.gsk.mdr.dps.util.RunExternalCommand). log4j:WARN Please initialize the log4j system properly.It means that you have defined in 'rootLogger' something for which there are no entries lower down the file.
(e.g. log4j.rootLogger = DEBUG, Consolexxx will give that error with the download file)
In JUnit you can also do this (which works if you have no log4j.properties)
package com.gsk.mdr.dps.methods;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import com.gsk.mdr.dps.ws.CalculatePropertiesReply;
import com.gsk.mdr.dps.ws.CalculatePropertiesRequest;
public class CalculatePropertiesImpl {
private Logger log = Logger.getLogger(ListPropertiesImpl.class);
public CalculatePropertiesImpl() {
Logger.getRootLogger().setLevel(Level.ALL); <--- this bit
}
public CalculatePropertiesReply calculateProperties() {
log.info("Running calculateProperties");
// TODO: processing for calculate properties
}
}
Another example:
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class PersonTest {
private EntityManagerFactory emf;
private EntityManager em;
@Before
public void initEmfAndEm() {
BasicConfigurator.configure();
Logger.getLogger("org").setLevel(Level.ERROR);
emf = Persistence.createEntityManagerFactory("examplePersistenceUnit");
em = emf.createEntityManager();
}
@After
public void cleanup() {
em.close();
}
@Test
public void emptyTest() {
}
}
A further example of how to set this up in a class which is inherited by all the tests, and so you can turn it on or off with a single comment:
package com.gsk.mdr.....;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;
import org.junit.BeforeClass;
/**
* Add the chosen @BeforeClass annotation to the required logging and then extend this class in your junit class
*
*/
public class LoggerSetup {
// @BeforeClass
public static void setupNoLogging() {
Logger.getRootLogger().setLevel(Level.OFF);
}
@BeforeClass
public static void setupFullLoggingToConsole() {
Logger.getRootLogger().removeAllAppenders();
Logger.getRootLogger().addAppender( new ConsoleAppender( new SimpleLayout() ) );
Logger.getRootLogger().setLevel(Level.ALL);
}
}
Generating skeleton apps of the very simplest kind of each type. Use myEclipse perspective.
Point to note:
16:17:40,895 INFO [TomcatDeployer] undeploy, ctxPath=/grot, warUrl=.../deploy/grot.war/ 16:17:51,050 INFO [TomcatDeployer] deploy, ctxPath=/grot, warUrl=.../deploy/grot.war/If you change anything in a project but jsps and images, do a redeploy.
<?xml version="1.0"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd"> <faces-config> <navigation-rule> <from-view-id>/pages/inputname.jsp</from-view-id> <navigation-case> <from-outcome>greeting</from-outcome> <to-view-id>/pages/greeting.jsp</to-view-id> </navigation-case> </navigation-rule> <managed-bean> <managed-bean-name>personBean</managed-bean-name> <managed-bean-class>jsfks.PersonBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> </faces-config>
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<listener>
<listener-class>
org.apache.myfaces.webapp.StartupServletContextListener
</listener-class>
</listener>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
</web-app>
Why use an EAR rather than a war? Because each EAR can be configured in the application.xml to use its own class loader. This means that if you have several ear's, each containing different versions of the same jars, they won't be interfering with each other.
This can probably be done in a WAR by adding some sort of jboss -application.xml file in the META-INF file.
"JBOSS does allow further configuration/isolation of the classloaders in a WAR. The major difference that I can see between WAR classloading and EJB classloading is the "dynamic" classloading where classes are loaded over a web connection (ie. the classloading webservice within JBOSS itself).
"Both the Webapplication and EJB sides of an application would appear to use the same Unified Class loader as a parent unless configurated otherwise. This classloader has a "flat" repository so classes are loaded once: but this is configurable on either side.
"To control classloading within a WAR configuratio can be placed into the the jboss-web.xml file. Although the implication is that the ear method may be preferred.
http://wiki.jboss.org/wiki/Wiki.jsp?page=ClassLoadingConfiguration
"It would seem to me one of the reasons for having the two levels is that the separation of the web-tier from the middle tier. It seems logical to me that the WAR in an EAR is passed to the Servlet container. The rest of the application is EJB based and is kept isolated from the servlet container: the web-app then communicates with the backend through EJB."
Here are a couple of projects in eclipse. The first is for the very simplest JDBC; the second for JDBC against an Oracle RAC cluster. The latter needs an Oracle 10g driver, which is included in both.
But we shouldn't be using JDBC any more, but JPA with either the Toplink or Hibernate jars.
1. Start myEclipse. File|New|Project|MyEclipse|Java Enterprise Projects|Enterprise Application Project + 'Next'.
2. Project name: "cis2". Choose "Java EE 5.0" and "New EJB module project". + 'Next'.
3. On dialog 'define ejb project modules' just hit 'Next'; Uncheck all the JPA stuff and hit 'Finish'.
This creates the empty project. There is an EAR folder cis2, which we don't touch, and a cis2EJB folder where we do our magic. Now we generate the stubs from the WSDL.
4. Get the WSDL (in this case cis.wsdl) that we are going to use, and put it in cis2EJB/src/META-INF. (It has to be in the classpath to be served up by the service).
5. Create a lib and a test-lib folder under the cis2EJB. The latter will contain stuff that we only use in test or development.
6. Get the jars from the lib folder in the JAX-WS samples (jbossws-samples-1.2.1.GA\lib) and copy them to the lib. Delete the jbossws-tomcat-integration.jar file, and also the jbossws-jbossXX-integration.jar where XX is versions of JBoss other than the one we are running.
7. Place the following files in the test-lib.11/05/2007 14:43 58,225 activation.jar 11/05/2007 14:43 15,860 getopt.jar 11/05/2007 14:44 74,878 jaxb-api.jar 11/05/2007 14:44 794,494 jaxb-impl.jar 11/05/2007 14:43 3,026,197 jaxb-xjc.jar 11/05/2007 14:43 1,121,815 jbossws-wsconsume-impl.jar 11/05/2007 14:44 39,853 policy.jar 11/05/2007 14:44 26,688 stax-api.jar 15/12/2006 03:16 7,055,575 tools.jar 11/05/2007 14:44 191,699 wsdl4j.jar 11/05/2007 14:44 288,640 xmlsec.jartools.jar is from the JDK; most of the others are in the JBoss directory somewhere.8. Add all these jars in both dirs to the project. Right-click on EJB dir, Build Path|Configure Build Path|Libraries|Add External Jars.
9. We need something to run the wsconsume utility to generate the stubs. This build.xml and build.properties should be created in the cis2EJB folder.
10. Run the build.xml by right-clicking on it and Run As|Ant Build. This will created a folder generated in the root, visible when you hit F5 to refresh.
11. Make the generated/src folder a source folder by right-clicking on cis2EJB, Build Path|Configure Build Path|Source|Add Folder. Make sure it is the src folder inside generated that you use, not generated otherwise package names will not work.
12. Get the package name of the generated files by clicking on the generated folder. There should be a package in there. Copy the name.
Now we need to create the main POJO for our webservice, using the interface that has been generated.
13. Create a new class in cis2EJB/src by right-clicking on the folder and then New|Class. Give it exactly the same package as the generated above, and a class name of some kind (e.g. Cis2). But you need to add an interface -- click on Add next to the interfaces box to do that. This pops up a dialog box: start typing cissoap and a stub of that name will be displayed. Select it (this is the interface file of the web service stub), click Add, then OK. Then in the Java class dialog hit 'Finish'.
14. Cis2.java will open. Add some annotations before the 'public class Cis2...' stuff (you will need to import the headers -- click on them, hit Ctrl-1 and choose the import needed):@WebService @StatelessThe first of these is a JAX-WS annotation; the second an EJB one. This file is where the service will be implemented. At the moment all methods return null.
15. Also open the generated CISSoap.java and stick @Local above the 'public interface CISSoap' bit.
That's basically it. Now deploy the new web server.
16. Add cis2 to the JBoss server (if you haven't one right-click on the servers tab, choose Configure, look for JBoss4, add the path, choose enable, and it will appear) using Manage Deployments, and deploy it. Start the server.
17. Open firefox and look at http://localhost:8080/jbossws (port may be different depending on how you set up Jboss). This should show a page of web services. Click on 'view a list of deployed services' to see yours listed there with default path and url. If yours isn't there, bounce the server and remanage the deployment or redeploy.
If you want to tweak the url of the web service (it defaults to bean class + 'service') then add another annotation after @WebServices:
@WebContext(contextRoot="/myEJBServices", urlPattern="/Roger")
The first of these alters the path, the second the service name.
18. Now test your webservice. Fire up soap UI, and create a new project using the WSDL url from the list of deployed services. Then run one of the methods, such as 'ListDatabases' -- something that returns something and requires no parameters.
To add code, place it in the stub. So for instance:
public ArrayOfString listDatabases() {
// TODO Auto-generated method stub
ArrayOfString obj = new ArrayOfString();
obj.getString().add("db1");
obj.getString().add("db2");
return obj;
//return null;
}
and test in the same way.
Or even:
/** start-----------------------------------------------*/
public List<String> runCommand(String cmd) throws IOException {
// set up list to capture command output lines
ArrayList<String> list = new ArrayList<String>();
// start command running
Process proc = Runtime.getRuntime().exec(cmd);
// get command's output stream and
// put a buffered reader input stream on it
InputStream istr = proc.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(istr));
// read output lines from command
try {
String str;
while ((str = br.readLine()) != null)
list.add(str);
} catch (IOException e) {
System.err.println(e);
}
// although the process has been spawned, we will wait
// for command it to finish using the waitFor() command.
try {
proc.waitFor();
} catch (InterruptedException e) {
System.err.println("process was interrupted");
}
// display its output
String[] outlist = (String[]) list.toArray(new String[0]);
for (int i = 0; i < outlist.length; i++)
System.out.println(outlist[i]);
// Print the exit value for user information.
int returnCode = proc.exitValue();
System.err.println("exit value was : " + returnCode);
// close stream
br.close();
// return the return code
return list;
}
/** end-----------------------------------------------*/
public ArrayOfString listDatabases() {
// TODO Auto-generated method stub
ArrayOfString obj = new ArrayOfString();
// obj.getString().add("db1");
// obj.getString().add("db2");
// return obj;
// return null;
try {
obj.string = runCommand("cmd /c dir /b");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("===============================>problem");
}
return obj;
}
Possible errors
1. A response like
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<env:Body>
<env:Fault>
<faultcode>env:Client</faultcode>
<faultstring>Endpoint {http://gsk.com/cix/}CISPort does not contain operation meta data for: SubStructureSearch</faultstring>
</env:Fault>
</env:Body>
</env:Envelope>
This means that my input soap contained <SubStructureSearch> rather than <cix:SubStructureSearch>.
2. If from the following annotation above a web method, I omit everything in
brackets:
@WebMethod (operationName = "SubStructureSearch", action = "http://gsk.com/cix/SubStructureSearch")
then I get:
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<env:Body>
<env:Fault>
<faultcode>env:Client</faultcode>
<faultstring>Endpoint {http://gsk.com/cix/}CISPort does not contain operation meta data for: {http://gsk.com/cix/}SubStructureSearch</faultstring>
</env:Fault>
</env:Body>
</env:Envelope>
because the method name in the code is subStructureSearch(), not SubStructureSearch()
3. An empty request object being passed in probably means that the soap has omitted some essential element -- use SoapUi and validate the soap against the WSDL by right-clicking on it and choosing 'Validate'.
1. Start myEclipse. File|New|Project|MyEclipse|Java Enterprise Projects|Enterprise Application Project + 'Next'.
2. Project name: "cis2". Choose "Java EE 5.0" and "New Web module project". + 'Next'.
3. On dialog 'define ejb project modules' just hit 'Next'; Uncheck all the JPA stuff and hit 'Finish'.
This creates the empty project. There is an EAR folder cis2, which we don't touch, and a cis2Server folder where we do our magic. Now generate the stubs from the WSDL as before.
Do all the other bits. But we don't need the @local and @Stateless annotations -- these are EJB specific.
Once it's all generated, you need to customise the default WebRoot/WEB-INF/web.xml. This is what tells JBoss where to find the entry point for the web service -- the "deployment descriptor". By default it points to a .jsp. If you forget and try to deploy it anyway, the deployment will work, a warning message "Unable to process deployment descriptor for context 'null'" appears in the log, and nothing is visible at http://127.0.0.1:28080/jbossws/services.
Replace it with this (details from this link):
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <description>WebTier for the DPS Service</description> <display-name>DPS3WAR</display-name> <servlet> <description>Endpoint for DPS Web Service</description> <display-name>Dps3WebService</display-name> <servlet-name>Dps3</servlet-name> <servlet-class>com.gsk.mdr.dps.ws.Dps3</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Dps3</servlet-name> <url-pattern>/Dps3Service</url-pattern> </servlet-mapping> <session-config> <session-timeout>54</session-timeout> </session-config> </web-app>
The important point is the servlet-class. This must match the class you added to act as the endpoint.
This is extremely simple, using the following items from the JBossWs user guide.
Echo.java:
package echo;
@javax.jws.WebService
public class Echo
{
public String echo(String input)
{
return input;
}
}
web.xml:
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>Echo</servlet-name>
<servlet-class>echo.Echo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Echo</servlet-name>
<url-pattern>/Echo</url-pattern>
</servlet-mapping>
</web-app>
You don't need to use wsprovide to generate wrappers in JBossWs, unlike JAX-WS: but details are given in the link above.
| Plugin Name | Update Site |
| EPIC Perl plugin | http://e-p-i-c.sf.net/updates |
| Subclipse SVN plugin | http://subclipse.tigris.org/update_1.2.x |
| C++ plugin | http://download.eclipse.org/tools/cdt/releases/callisto |
| Ruby plugin | http://updatesite.rubypeople.org/release |
| Emma Plugin | http://update.eclemma.org/ |
| ShellEd | None |
| Jadclipse | None (Java disassembler) |
| Classpath helper | None (to see what jars in a project are used and which are not) |
Use Window|Preferences choose MyEclipse|Java Enterprise Project|Deployment to decide if stuff is deployed into a war or not by myEclipse.
Choose "Smart Deployment for dependent java projects", Library deployment policies should be all
unchecked.
This determines whether jars from testLib are copied into war on deployment from myEclipse or not.
Often you have jars in a testLib folder which you need to use for compilation, but do not want deployed, as they will clash with those in JBoss (log4j is a good example).
In myEclipse define things as above. But then no jars at all get deployed. To get around this, put those jars in the web project which you *do* want deployed in WebRoot/WEB-INF/Lib. myEclipse will automatically add them to the build path, and will auto-deploy them.
Do not have a 'lib' directory in a web project: it will cause confusion, and won't get deployed.
If you don't specify the @WebParam annotation, the generated wsdl contains 'arg0' instead of input.
package echo;
@javax.jws.WebService
public class Echo
{
@javax.jws.WebMethod
public String echo(
@javax.jws.WebParam(name="input")
String input)
{
return input;
}
}
Note also that specifying the namespace in the @WebService can be necessary. Do this if the deployment seems to work but the WSDL can't be opened in SoapUI, and it complains about namespaces. The namespace necessary should be in the generated stub @WebService.
JBoss (or Tomcat) often doesn't reload properly a redeployed war. You can force it to do so by editing a space into this file, and then removing it
again:
C:\jboss-4.0.5.GA\server\default\deploy\eRoute.ear\META-INF\application.xml
if the app is eroute.ear.
annotations --specify table (just a class, annotated with @entity) and columns (fields, with @item)
persistence.xml -- link classes to tables
The article assumes no Java EE knowledge?indeed, the JPA architecture itself delegates much of the heavy lifting to persistence providers, such as Hibernate, and reduces complexity by relying on sensible API defaults. In this example, only two JPA annotations, a single XML configuration file, and a few lines of extra code are used to persist a POJO from a client application. The annotations are as simple as the following:
@Entity
public class Person {
@Id @GeneratedValue
public Long id;
public String first;
public String middle;
public String last;
}
While object-relational mapping is not appropriate for all applications, the JPA makes this technique
a standard accessible to any Java application via an easy-to-use API. Do you envision yourself
using the JPA even outside an EJB 3 container?
http://www.artima.com/forums/flat.jsp?forum=276&thread=161630
http://today.java.net/pub/a/today/2006/05/23/ejb3-persistence-api-for-client-side-developer.html
Add @SuppressWarnings("all") at the top of a generated file to suppress all the warnings in it .
If you want to check large part of response is correct, do this as an xpath assert, click on 'declare' to get decl's. then type
//ns1:Response
click on 'current' (prsuming we've run the request) and it will store the portion of the response and vet against it
There was a little discussion of changing port numbers of JBOSS today. I noticed that the shutdown logic may contact the Naming service to shutdown jboss. So not changing other endpoints of the service may bring down all JBOSS that share the service.
What is interesting is there does seem to me a way for changing ports throughout the service through the use of a binding manager: which will be interesting to try. This page http://wiki.jboss.org/wiki/Wiki.jsp?page=ConfigurePorts gives information on the manual and binding manager methods.
What is quite interesting is the fetching of the port information appears to be url based. We could serve one set of port definitions for the whole team for unix and have our own port numbers defined by each using a different "server-name".
From http://forum.java.sun.com/thread.jspa?threadID=5241199&tstart=0
package krc.utilz.io;
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.FileNotFoundException;
/**
* @class: krc.utilz.io.Filez
* A collection of static "file handling" helper methods.
*/
public abstract class Filez
{
public static final int BFRSIZE = 4096;
/**
* reads the given file into one big string
* @param String filename - the name of the file to read
* @return the contents filename
*/
public static String read(String filename)
throws FileNotFoundException
{
try {
FileReader in = null;
StringBuffer out = new StringBuffer();
try {
in = new FileReader(filename);
char[] cbuf = new char[BFRSIZE];
int n = in.read(cbuf, 0, BFRSIZE);
while(n > 0) {
out.append(cbuf);
n = in.read(cbuf, 0, BFRSIZE);
}
} finally {
if(in!=null)in.close();
}
return out.toString();
} catch (IOException e) {
throw new RuntimeIOException(e.getMessage(), e);
}
}
/**
* (re)writes the given content to the given filename
* @param String content - the new contents of the fil
* @param String filename - the name of the file to write.
*/
public static void write(String content, String filename) {
try {
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(filename));
out.write(content);
} finally {
if(out!=null)out.close();
}
} catch (IOException e) {
throw new RuntimeIOException(e.getMessage(), e);
}
}
/**
* reads each line of the given file into an array of strings.
* @param String filename - the name of the file to read
* @return a fixed length array of strings containing file contents.
*/
public static String[] readArray(String filename)
throws FileNotFoundException
{
return readList(filename).toArray(new String[0]);
}
/**
* reads each line of the given file into an ArrayList of strings.
* @param String filename - the name of the file to read
* @return an ArrayList of strings containing file contents.
*/
public static ArrayList<String> readArrayList(String filename)
throws FileNotFoundException
{
return (ArrayList<String>)readList(filename);
}
/**
* reads each line of the given file into a List of strings.
* @param String filename - the name of the file to read
* @return an List handle ArrayList of strings containing file contents.
*/
public static List<String> readList(String filename)
throws FileNotFoundException
{
try {
BufferedReader in = null;
List<String> out = new ArrayList<String>();
try {
in = new BufferedReader(new FileReader(filename));
String line = null;
while ( (line = in.readLine()) != null ) {
out.add(line);
}
} finally {
if(in!=null)in.close();
}
return out;
} catch (IOException e) {
throw new RuntimeIOException(e.getMessage(), e);
}
}
/**
* reads the whole of the given file into an array of bytes.
* @param String filename - the name of the file to read
* @return an array of bytes containing the file contents.
*/
public static byte[] readBytes(String filename)
throws FileNotFoundException
{
return( readBytes(new File(filename)) );
}
/**
* reads the whole of the given file into an array of bytes.
* @param File file - the file to read
* @return an array of bytes containing the file contents.
*/
public static byte[] readBytes(File file)
throws FileNotFoundException
{
try {
byte[] out = null;
InputStream in = null;
try {
in = new FileInputStream(file);
out = new byte[(int)file.length()];
int size = in.read(out);
} finally {
if(in!=null)in.close();
}
return out;
} catch (IOException e) {
throw new RuntimeIOException(e.getMessage(), e);
}
}
/**
* do files A & B have the same contents
* @param String filenameA - the first file to compare
* @param String filenameA - the second file to compare
* @return boolean do-these-two-files-have-the-same-contents?
*/
public static boolean isSame(String filenameA, String filenameB)
throws FileNotFoundException
{
try {
File fileA = new File(filenameA);
File fileB = new File(filenameB);
//check for same physical file
if( fileA.equals(fileB) ) return(true);
//compare sizes
if( fileA.length() != fileB.length() ) return(false);
//compare contents (buffer by buffer)
boolean same=true;
InputStream inA = null;
InputStream inB = null;
try {
inA = new FileInputStream(fileA);
inB = new FileInputStream(fileB);
byte[] bfrA = new byte[BFRSIZE];
byte[] bfrB = new byte[BFRSIZE];
int sizeA=0, sizeB=0;
do {
sizeA = inA.read(bfrA);
sizeB = inA.read(bfrB);
if ( sizeA != sizeB ) {
same = false;
} else if ( sizeA == 0 ) {
//do nothing
} else if ( !Arrays.equals(bfrA,bfrB) ) {
same = false;
}
} while (same && sizeA != -1);
} finally {
Filez.close(inA, inB);
}
return(same);
} catch (IOException e) {
throw new RuntimeIOException(e.getMessage(), e);
}
}
/**
* checks the given filename exists and is readable
* @param String filename = the name of the file to "open".
* @param OPTIONAl String type = a short name for the file used to identify
* the file in any exception messages.
* For example: "input", "input data", "DTD", "XML", or whatever.
* @return a File object for the given filename.
* @throw FileNotFoundException if the given file does not exist.
* @throw IOException if the given file is unreadable (usually permits).
*/
public static File open(String filename)
throws FileNotFoundException
{
return(open(filename,"input"));
}
public static File open(String filename, String type)
throws FileNotFoundException
{
try {
File file = new File(filename);
String fullname = file.getCanonicalPath();
if(!file.exists()) throw new FileNotFoundException(type+" file does not exist: "+fullname);
if(!file.canRead()) throw new RuntimeIOException(type+" file is not readable: "+fullname);
return(file);
} catch (IOException e) {
throw new RuntimeIOException(e.getMessage(), e);
}
}
/**
* gets the filename-only portion of a canonical-filename, with or without
* the extension.
* @param String path - the full name of the file.
* OPTIONAL @param boolean cutExtension - if true then remove any .ext
* @return String the filename-only (with or without extension)
*/
public static String basename(String path) {
return(basename(path,false));
}
public static String basename(String path, boolean cutExtension)
{
String fname = (new File(path)).getName();
if (cutExtension) {
int i = fname.lastIndexOf(".");
if(i>0) fname = fname.substring(0,i);
}
return(fname);
}
/**
* gets the directory portion of a canonical-filename
* @param String path - the full name of the file.
* @return String the parent directory of the given path.
*/
public static String dirname(String path)
{
return( new File(path).getParent() );
}
/**
* close these "streams"
* @param Closeable... "streams" to close.
*/
public static void close(Closeable... streams) {
Exception x = null;
for(Closeable stream : streams) {
if(stream==null) continue;
try {
stream.close();
} catch (Exception e) {
if(x!=null)x.printStackTrace();
x = e;
}
}
if(x!=null) throw new RuntimeIOException(x.getMessage(), x);
}
}
This is what I did to end up with just servername:port/SQC as the endpoint.
1. Clear off all the stuff in web.xml. Should just look like this, with * in the pattern:
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <servlet> <servlet-name>SQC</servlet-name> <servlet-class>com.gsk.mdr.sqc.Sqc</servlet-class> </servlet> <servlet-mapping> <servlet-name>SQC</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
2. Edit the header in entry point
@WebService(name = "SQC", targetNamespace = "http://gsk.com/cix/")
public class Sqc implements SqcClassSoap {
3. Alter the properties of the myEclipse project using Project|Properties|MyEclipse|Web. Alter the web-context-root.
(write note on how to generate just a war from wsdl)
Actually setting up monitoring of an existing java process seems as easy as
jconsole [processID]
(for jconsole running as the same user as the process)
http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html
We've found it best to use Cygwin, open an xterm on our PC, and ssh -Y to <hostname>. Then we can run x applications on the server.
Installing cygwin
mkdir /cygdrive/c/mudid mkpasswd -l > /etc/passwd mkpasswd -d -u mudid --path-to-home=/cygdrive/c/mudid >> /etc/passwd mkgroup -l -d > /etc/group
Helpful links on 'fixed fonts' problem
http://x.cygwin.com/docs/ug/setup-cygwin-x-installing.html
http://x.cygwin.com/docs/faq/cygwin-x-faq.html#q-error-font-eof
(two suggestions but see i-hate-cygwin for the real problem)
http://cygwin.com/ml/cygwin-xfree/2007-05/msg00056.html
http://quantumg.blogspot.com/2006/11/god-damn-i-hate-cygwin.html
(some extra suggestions)
Installing SSH
http://pigtail.net/LRP/printsrv/cygwin-ssh.html
Troubleshooting
You can use
cggcheck -s
to look for strange problems.
Selenium is used to run integration tests. If you wish to run your test locally then you need to start a selenium server beforehand:
java -jar selenium-server.jar -port 5444
or
java -jar c:\selenium\server\selenium-server.jar -port 5444
Then can export IDE test as Java, and run in JUnit (see project source for example)
The power of EJB3 (see http://www.onjava.com/pub/a/onjava/2005/06/29/spring-ejb3.html)
From a very high level, the Spring framework sits above application servers and service libraries. The service integration code (e.g., data
access templates and helper classes) resides in the framework and is exposed to the application developers.
In contrast, the EJB 3.0 framework is tightly integrated into the application server and the service integration code is encapsulated behind a standard interface.
As a result, EJB 3.0 vendors can aggressively optimize the overall performance and developer experience. For instance, in JBoss's EJB 3.0 implementation, when you persist an Entity Bean POJO using the EntityManager, the underlying Hibernate session transaction is automatically tied to the calling method's JTA transaction, and it commits when the JTA transaction commits.
Using a simple @PersistenceContext annotation (see later in this article for an example), you can even tie the EntityManager and its underlying Hibernate transaction to an application transaction in a stateful session bean. The application transaction spans across multiple threads in a session and it is very useful in transactional web applications, such as multi-page shopping carts. The above simple and integrated programming interface is made possible due to the tight integration between the EJB 3.0 framework, Hibernate, and Tomcat inside of JBoss.
A similar level of integration is also archived between Oracle's EJB 3.0 framework and its underlying Toplink persistence service.
Another good example of integrated services in EJB 3.0 is clustering support. If you deploy an EJB 3.0 application in a server cluster, all of the fail-over, load-balancing, distributed cache, and state replication services are automatically available to the application. The underlying clustering services are hidden behind the EJB 3.0 programming interface and they are completely transparent to EJB 3.0 developers.
The phrasebook design pattern to separate out sql from perl (or another language)
The DAO pattern is a core J2EE pattern. It's the idea that it wraps the db connection and all access, so that nothing higher up needs to know anything about the db.
http://www.martinfowler.com/articles/injection.html Dependency injection pattern
It is relatively simple to serialize a DOM object to a string or other
stream.
import org.w3c.dom.Node;
import org.apache.xalan.serialize.SerializerToXML;
import java.io.StringWriter;
public static String serializeXml(Node node)
throws Exception {
try {
StringWriter sw = new StringWriter();
SerializerToXML serxml = new SerializerToXML();
serxml.setWriter(sw);
serxml.serialize(node);
serxml.flush();
return sw.toString();
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
package com.gsk.mdr.cis;
import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.gsk.mdr.cis.ws.IdSearchResponse;
/**
* Test that JAXB is configured the way we need it for CDATA
*
* Adapted from:
* https://jaxb.dev.java.net/faq/JaxbCDATASample.java
* at
* https://jaxb.dev.java.net/faq/index.html
*
* See also:
* http://java.sun.com/webservices/jaxb/users-guide/jaxb-works.html#arch_unmarshal
* http://java.sun.com/webservices/jaxb/users-guide/jaxb-using.html
* https://jaxb.dev.java.net/
* http://java.sun.com/developer/technicalArticles/WebServices/jaxb/
* http://forum.java.sun.com/thread.jspa?threadID=607524&messageID=3321898
*
* @author wrp43058
*
*/
public class JaxbTest {
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testOne() throws JAXBException, IOException {
File myfile = new File("c:\\sample.xml"); // in root dir
// unmarshal a doc into classes in generated package
JAXBContext jc = JAXBContext.newInstance("com.gsk.mdr.cis.ws");
Unmarshaller u = jc.createUnmarshaller();
IdSearchResponse o = (IdSearchResponse) u.unmarshal(myfile);
// get an Apache XMLSerializer configured to generate CDATA
XMLSerializer serializer = getXMLSerializer();
// Get list of classes known to our context
//System.out.println(jc.toString());
// create a JAXB marshaller
Marshaller m = jc.createMarshaller();
// Marshaller m = new Marshaller(serializer.asContentHandler());
// marshal using the Apache XMLSerializer, to stdout
// m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// m.marshal(o, System.out );
m.marshal(o, serializer.asContentHandler());
assertEquals("1", "1");
}
//--------------------------
private XMLSerializer getXMLSerializer() {
// configure an OutputFormat to handle CDATA
OutputFormat format = new OutputFormat();
// specify which of your elements you want to be handled as CDATA.
// The use of the '^' between the namespaceURI and the localname
// seems to be an implementation detail of the xerces code.
// When processing xml that doesn't use namespaces, simply omit the
// namespace prefix as shown in the third CDataElement below.
String[] cdataTags = { "ns1^chime", // <ns1:foo>
"ns2^bar", // <ns2:bar>
"chime", // ...
"http://gsk.com/cix/^chime" }; // <baz>
format.setCDataElements(cdataTags);
format.setNonEscapingElements(cdataTags);
// create the serializer and point to System.out
XMLSerializer serializer = new XMLSerializer(format);
serializer.setOutputByteStream(System.out);
return serializer;
}
}
Add 3 jars from the download of Shale to project build path:
shale-validator-1.04.jar shale-core-1.0.4.jar commons-validator-1.3.1.jar
In the .jsp to validate add:
<%@ taglib uri="http://shale.apache.org/core" prefix="val" %> ... <!-- add onsubmit() --> <h:form id="routesCatalogForm" onsubmit="return validateForm(this);"> ... <val:validatorScript functionName="validateForm"/> </h:form>
and in the form for each inputtext:
<t:inputText id="nbCopy" value="#{route.copyCount}" size="2" required="true"
displayValueOnly="#{routesCatalog.selectedRouteId != route.id || !route.updatable}" >
<val:commonsValidator type="intRange"
arg="#{msg.routesCatalogHeaderCopies}"
min="1"
max="99999999"
server="true"
client="true" >
</val:commonsValidator>
</t:inputText>
That's it. Build and run. This will run on client and server when you click the button. The 'arg' is a field name.
The possible validators are all listed in the validator-rules.xml inside the shale download.
I've found the faulty class... it is in Axis (1.3):
org.apache.axis.components.net.TransportClientPropertiesFactory.java
The class caches the proxy details in a HashMap. There will only ever be one set of proxy settings per protocol per JVM (as the HashMap is a static
member variable). In practice this means that with this version of Axis (1.3), all Axis clients are bound to use the same proxy server and
credentials in the same JVM.
I will try to run the test against Axis 1.4 just in case the problem was fixed in latest release of the 1.x series.
JSF links
Tutorial: http://www.oracle.com/technology/products/ias/toplink/jpa/tutorials/jsf-jpa-tutorial.html
From: http://www.jroller.com/page/marceloverdijk/?anchor=java_persistence_api_kickstart_example
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Cat {
private String id;
private String name;
private char sex;
private float weight;
public Cat() {
}
public Cat(String id, String name, char sex, float weight) {
this.id = id;
this.name = name;
this.sex = sex;
this.weight = weight;
}
@Id
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public float getWeight() {
return weight;
}
public void setWeight(float weight) {
this.weight = weight;
}
}
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="example">
<!-- Provider class name is required in Java SE -->
<provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
<!-- All persistence classes must be listed -->
<class>Cat</class>
<properties>
<!-- Provider-specific connection properties -->
<property name="toplink.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
<property name="toplink.jdbc.url" value="jdbc:hsqldb:mem:."/>
<property name="toplink.jdbc.user" value="sa"/>
<property name="toplink.jdbc.password" value=""/>
<!-- Provider-specific settings -->
<property name="toplink.ddl-generation" value="create-tables"/><!-- other values are: drop-and-create-tables|none -->
<property name="toplink.logging.level" value="DEBUG"/>
<property name="toplink.platform.class.name" value="oracle.toplink.essentials.platform.database.HSQLPlatform"/>
</properties>
</persistence-unit>
</persistence>
Because we are running HSQLDB in memory and have set ddl-generation to "create-tables" we don't have to install a database and even don't have to create the Cat table. Toplink Essentials will create the table automatically.
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class Example {
public static void main(String[] args) {
// Equivalent to loading all the driver jars for the database - slow, can store in application
EntityManagerFactory emf = Persistence.createEntityManagerFactory("example");
// Equivalent to opening a JDBC connection. Fast, don't put in session or application
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
Cat princess = new Cat("1", "Princess", 'F', 7.4f);
Cat blackie = new Cat("2", "Blackie", 'M', 7.6f);
em.persist(princess);
em.persist(blackie);
em.getTransaction().commit();
List<Cat> cats = em.createQuery("SELECT c FROM Cat c").getResultList();
for (Cat c : cats) {
System.out.println(c.getName());
}
} catch(Exception ex) {
em.getTransaction().rollback();
} finally {
em.close();
}
}
}
First we persist 2 Cat instances and later we retrieve them back againg using an EJBQL query.
[TopLink Info]: 2006.04.18 08:54:44.734--ServerSession(9800632)--TopLink, version: Oracle TopLink Essentials - 2006.4 (Build 060412) [TopLink Info]: 2006.04.18 08:54:45.093--ServerSession(9800632)--file:/C:/Projects/workspace/jpa_example-example login successful Princess Blackie
I initially got the following:
Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named example at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:89) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60) at Example.main(Example.java:17)
Judging from a ( http://forum.hibernate.org/viewtopic.php?p=2338535&sid=c09e91e627c221db39d467e31dfefc2c ) Hibernate forum, this can be caused by missing jars from the class path.
Or:
Looks like you persistence-unit name is wrong is in the xml
But I found (http://today.java.net/pub/a/today/2006/05/23/ejb3-persistence-api-for-client-side-developer.html ) this revealing note
The persistence.xml file must be in the META-INF directory of your application .jar. If you are using NetBeans, you can put it in a META-INF directory of your src directory and let NetBeans copy it to the right place during compilation.
In our case an eclipse project by default creates a ''bin'' directory in which the class files are created; copying the META-INF directory into ''bin'' means that it all works.
I did find that the code objected to one line in the downloaded file, which I therefore removed -- the DEBUG line. See http://www.oracle.com/technology/products/ias/toplink/jpa/howto/configure-logging.html -- value should be FINEST.
The right place to put the META-INF directory is under the ''src'' folder. Then eclipse copies it automatically. In fact if you structure your project correctly, with '''src''' and '''test-src''' source folders under the project root, you have a META-INF in each. The one in the latter points to hsqldb, so that the Junit tests can run against it; the one in the former points to the live Oracle instance.
Create your own Java objects, list them in the persistence.xml and start expirementing with them by persisting them and retrieving them using EJBQL queries. Note that when you run the example new tables are created automatically for your new Java objects.
* testjpa1.zip: Sample eclipse project
This lightweight db can be run in memory in the same JVM as a JUnit test. This means the db dies at the end of each run, thereby ensuring it is clean. (In-process mode). It's very fast and useful to test JPA.
* http://hsqldb.org/web/hsqlFAQ.html
Get the download, unzip to c:\foldername.
From the http://hsqldb.org/web/hsqlDocsFrame.html User Guide:
It is possible to run HSQLDB in a way that the database is not persistent and exists entirely in random access memory. As no information is written to disk, this mode should be used only for internal processing of application data, in applets or certain special applications. This mode is specified by the mem: protocol.
Connection c = DriverManager?.getConnection("jdbc:hsqldb:mem:aname", "sa", "");
http://www.herongyang.com/jtool/ -- java basics -- store and make sure have all onhand (esp. debugger)
http://homepage.usask.ca/~dol142/Files/Axis2T.pdf -- useful axis stuff
http://today.java.net/pub/a/today/2006/12/07/junit-reloaded.html -- JUnit4 stuff
http://home.cogeco.ca/~ve3ll/jatutor0.htm -- excellent Java tutorial
http://www.cafeconleche.org/books/xmljava/chapters/index.html -- good on Java and XML
http://java.sun.com/developer/EJTechTips/2005/tt1220.html Techtip with sample project which shows how to deploy a JAX-WS service in a war.
http://e-docs.bea.com/wls/docs91/webserv/annotations.html Jax-WS annotations reference.
http://schuchert.wikispaces.com/EJB3+Tutorial+5+-+Message+Driven+Beans Details on using JMS with EJB3
http://docs.jboss.org/ejb3/embedded/embedded.html Using the embedded JBoss container in JUnit
http://www.javaworld.com/javaworld/jw-07-2003/jw-0718-mdb.html Concurrent processing using message-driven beans
http://www.javaranch.com/newsletter/200311/Journal200311.jsp#a10 Distributed cache in J2EE
http://labs.jboss.com/file-access/default/members/jbosscache/freezone/docs/1.2.0/Tutorial.html Basics of POJO cache
http://www.inetfeedback.com/jarscan/index.jsp Jarscan. (jarscan.jar). java -jar jarscan.jar
http://java.sun.com/developer/JDCTechTips/2005/tt0727.html Information on processbuilder
http://www.artima.com/forums/flat.jsp?forum=276&thread=161630 Getting started with JPA
https://blueprints.dev.java.net/bpcatalog/ee5/persistence/namingconventions.html JPA naming conventions
http://weblogs.java.net/blog/bleonard/archive/2006/11/using_composite.html Composite primary keys in JPA
http://www.ubookcase.com/book/Sams/JBoss.4.0.The.Official.Guide/0672326485/main.html JBoss 4 guide
http://weblogs.goshaky.com/weblogs/lars/resource/eclipse.pdf Eclipse cheat sheet
tset -e -k = linux backspace
![]()
Constructive feedback is welcomed to Roger Pearse.
This page has been accessed by
people since 28th July 2006.
Return to Roger Pearse's Pages