An interesting illusion with a checker board. Are those lines parallel?
http://hcpcrew.at/pix/illu_003.gif
The second one is a bit rude:
http://hcpcrew.at/pix/chinese.jpg
Newer versions of ActiveMQ have support for XML name space schema declarations to allow easier configuration of container beans. Adding the following XMLNS declaration to the
beans
container will allow you to use ActiveMQ’s amq
name space.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd">
<amq:broker start="true" brokerName="bs-localhost">
<amq:networkConnectors>
<!-- more configurations -->
</amq:networkConnectors>
</amq:broker>
</bean>
When the application is deployed (in Tomcat) it will work as expected, however if you try to run it under Eclipse the container fails to start with the message:
org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'http://activemq.apache.org/schema/core/activemq-core.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is notThe. Caused by: org.xml.sax.SAXParseException: cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'amq:broker'. </xsd>
amq:broker
maybe replaced with amq:connectionFactory
depending on which name elements you have actually used.
In order for Eclipse to understand the amq
name space you must add xbean support for ActiveMQ. This is achieved by adding xbean-spring-3.4.jar
to your dynamic web project.
According to the ActiveMQ website the XSD declaration will be automatically fished out of the jar and used to help Eclipse give you features like command completion for the XML schema. In fact what happens, is that Eclipse lights up like a Christmas tree moaning that it can’t find the schema declaration. Below is a set of instructions to tell Eclipse how to associate the activemq-core.xsd
url with the activemq-core.xsd
found in the jar file which is shipped as part of ActiveMQ.
- Select Windows->Preferences from the Eclipse menu bar.
- Select XML->XML Catalog from the left hand configuration tree.
- Highlight User Specified Entries and select Add.
- The Add XML Catalog Entry windows appears.
- In the Location enter the path to the activemq-all jar, then add !/activemq.xsd to the end of the jar name. e.g.
jar:file:C:/Java/libs/activemq/apache-activemq-5.2.0/activemq-all-5.2.0.jar!/activemq.xsd
- Under KeyType enter Namespace Name
- and under Key enter http://activemq.apache.org/schema/core
- then click Ok.
- Now we need to do the same for the other name space file, so hit Add again.
- In the Location enter the path to the activemq-all jar, then add !/activemq.xsd to the end of the jar name. e.g. jar:file:C:/Java/libs/activemq/apache-activemq-5.2.0/activemq-all-5.2.0.jar!/activemq.xsd
- Under KeyType enter Schema Location
- and under Key enter http://activemq.apache.org/schema/core/activemq-core.xsd
- Click Ok, Ok.
Having spent the last (almost) year learning about J2EE Frameworks (specifically The Spring Framework) I found this article very funny. It aptly describes the trials and tribulations of creating applications using framework tools, in a way that any one can understand. The article uses the analogy of building a spice rack to help describe the problems that you’ll face.
http://discuss.joelonsoftware.com/default.asp?joel.3.219431.12
The comments are, in the most part, funny too. I think, however, that the article author and the commenters missed the point of why Spring’s Dependancy Injection is so useful. To be fair the article was written in 2005, so maybe they have learnt a bit more since then.
The Dependancy Injection design pattern is defined in lots of ways; most of them using more big words which have books of descriptions behind them. I would like to describe what makes Dependancy Injection useful in layman’s terms. A small knowledge of Java is required by the layman!
Let’s say you want to write an application to see which person has grown the most over the last year. You have a database full of everyone’s names, their height at the start of the year and the height at the end of the year. So your database table looks like:
and your database has 60,000,000 record’s (one record for each person in the country).
Ok, simple problem - but it requires database access, calculations and output of results. The complexity of our problem means that the program will take 2 days to run so we want to make sure that when it runs it comes out with the correct answer first time, with no bugs.
In pseudo code it is easy:
person_id | person_name | start_height | end_height |
# make it smaller than the smallest diference remember biggest_difference = -1 remember person = -1 for each person in database height = end_height - start_height # make it smaller than the smallest diference if (height > biggest_difference) remember biggest_difference = height remember person = person_id end-if end-for output person " has grown the most by " biggest_difference " cm"After 2 days of running it spits out.
Little Jimmy has grown the most by 10 cmAfter the program has run you realise that we have just wasted the last 2 days because the answer is wrong. You forgot to take into account the fact that Little Jimmy shares his growth with 100,000 other people, so we have to rewrite our program and run it again. There must be a better way… This is where dependency injection can help us. The idea is that you split your code up into pieces. One piece gets the data for the sums and another piece does the sums and works out the answer. The bit that gets the data sits behind an interface. In our example we want to test the bit that does the sums. So we create that first to help us decide the kinds of questions we need to ask (i.e. what our interface should look like). So in Java:
class WhoIsTheTallest
{
OurDataSource ods;
void setOurDataSource(OurDataSource ods)
{
this.ods = ods;
}
int findTallest()
{
Person person;
int height;
int maxHeight = -1;
int tallestPersonIndex = -1;
int numberOfPeople = ods.getNumberOfPeople();
for (int index = 0 ; index < numberOfPeople ; ++index)
{
person = ods.getPerson(index);
height = person.getEndHeight() - person.getStartHeight();
if (height > maxHeight)
{
tallestPersonIndex = index;
maxHeight = height;
}
}
return tallestPersonIndex;
}
main ()
{
int tallestPersonIndex = findTallest();
Person person = ods.getPerson(tallestPersonIndex);
System.out.println(person.getName() + " has grown " + maxHeight + " cm");
}
}
In the example above OurDataSource
is an interface which implements 2 methods:
interface OurDataSource
{
int getNumberOfPeople();
Person getPerson(int index);
}
Now that we have our interface we can write a couple of implementations. First, we will write a fake version of OurDataSource
. A fake object is generally referred to as a Mock, and is usually prefixed with the word Mock. Let’s make a really simple class called MockOurDataSource
which implements our new interface.
class MockOurDataSource implements OurDataSource
{
ArrayList<Person> people ;
MockOurDataSource ()
{
people = new ArrayList<Person> ();
people.add(new Person(1, "Tom", 110, 190));
people.add(new Person(2, "Dick", 120, 180));
people.add(new Person(3, "Harry", 100, 200));
}
int getNumberOfPeople()
{
return people.size();
}
Person getPerson(int index)
{
return people.get(index);
}
}
The next class to write is a testing class, which will use our mock class as a data source. The mock class has a small amount of simple data, which means that we can work out what the answer should be by hand and use it to make sure our program is working.
class TestWhoIsTheTallest extends TestCase
{
WhoIsTheTallest testClass ;
setup()
{
ApplicationContext ac = new
ClassPathXmlApplicationContext("config.xml");
testClass = ac.getBean("whoIsTheTallest");
}
testFindTallest()
{
int tallestId = testClass.findTallest();
assertEquals(tallestId, 3);
}
}
where config.xml
contains a description of how the class is constructed.
<bean id="whoIsTheTallest" class="WhoIsTheTallest">
<property name="ourDataSource">
<bean class="MockOurDataSource"/>
</property>
</bean>
As you can see from this example, once we have got our program working we can write a real implementation of OurDataSource
that talks to an actual database using JDBC. After learning hibernate you may want to replace the JdbcOurDataSource
with HibernateOurDataSource
. Switching the implementation from one to another is a simple matter of changing the configuration file. The class source does not have to change and the class file does not have to be recompiled.
The Dependency Injection mechanism allows the separation of application and configuration. With the same compiled code you can run the application in test mode and in a live environment. Isn’t that cool?JMX can incur an overhead to an application so many libraries have an option to switch it on explicitly.
In order to get a JMX view into ActiveMQ (JMS implementation) you must switch on JMX on the container and on the ActiveMQ library.
To active JMX under Tomcat you can follow these instructions to Allow remote JMX management for Tomcat or Switch on Tomcat JMX under Eclipse.
Once Tomcat is set up you can set up JMX on ActiveMQ. The Broker is the place inside the messaging system, where all the action is. It contains the queues (pipeline messaging) and topics (publisher-subscriber) along with flow control and related information. Under a Spring bean configuration this would be set up like this:
<amq:broker start="true" brokerName="localhost" useJmx="true">
<!-- other configuration options -->
</amq:broker>
In order to switch on JMX to monitor a Tomcat instance you must firstly switch it on and then tell it what port to listen on. There is also optional support for user names and passwords. JMX helps with remote management and as a consequence will generally let you do some pretty evasive stuff with the internals of your application. So if it is in a production environment passwords might be a good idea!
During Tomcat’s start up sequence it calls the file
TOMCAT_HOME/bin/setenv.bat
(or TOMCAT_HOME/bin/setenv.sh
depending on your environment) which sets up any extra environment variables or Java VM command line options. In some of the Tomcat distributions this file does not exist, so you must create it yourself.
Tomcat’s servlet container is called Catalina so inside TOMCAT_HOME/bin/setenv.bat
we must set our JMX options in the environment variable CATALINA_OPTS
. All the arguments must go on the same line.
set CATALINA_OPTS=-Dcom.sun.management.jmxremote ^ -Dcom.sun.management.jmxremote.port=8181 ^ -Dcom.sun.management.jmxremote.authenticate=false ^ -Dcom.sun.management.jmxremote.ssl=falseThere is extra information on the Sun site related to user name and password authentication, but this was not set by default. The default was to have no authentication. After makeing the changes, restart Tomcat.