There are a lot of documents out there explaining that you should use various other things (including simple proxying) but AJP is flexible and fast, and it really helps me integrate our SAML2 SSO without any of the webapps having to worry about any of that.
I am now trying to get a spring-boot application working the same way and having a really terrible time of it. The main symptom is "Bad Gateway" with error messages like:
[error] ajp_get_reply::jk_ajp_common.c (2126): (boot_worker_1) Tomcat
is down or refused connection. No response has been sent to the client
(yet)
[info] ajp_service::jk_ajp_common.c (2623): (boot_worker_1) sending
request to tomcat failed (recoverable), because of protocol error
(attempt=1)
[error] ajp_connection_tcp_get_message::jk_ajp_common.c (1289): wrong
message format 0x4854 from 127.0.0.1:8092
The last one seemed like a clue but I have not been able to find it.
The spring boot manual seems to suggest that if you only have a single connection you can set it up in application.properties - this is what I would ideally like to do, but I haven't been able to find any examples of this. From a distribution point of view, though, this seems ideal - publish a jar, give the user a documented properties file.
Since that didn't work, I tried doing it programmatically like this:
#Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
Connector ajpConnector = new Connector();
ajpConnector.setProtocol("AJP/1.3");
ajpConnector.setPort(8092);
ajpConnector.setSecure(false);
ajpConnector.setAllowTrace(false);
ajpConnector.setScheme("http");
tomcat.addAdditionalTomcatConnectors(ajpConnector);
return tomcat;
}
(I'd really rather not get into having to configure SSL for a localhost connection because it just complicates things, and once you spend time in the unsecured worlds of zookeeper, kafka, etc. you kind of give up after a while and figure your ESB is RFC1918 and firewalled anyway).
My questions are:
1) Can this all really be done with the properties file, and how?
2) With the above hard-coded configuration, I can telnet to port 8092 and issue GET requests ... I'm not sure why I can do this, because these GETs are http and I have configured the protocol to AJP/1.3 so I don't THINK it should work. But is that the problem Apache is having? I can't find any explanation of "wrong message format 0x4854" or error "-11."
--Chris
i had the same problem and resolve it by adding the connector implementation.
for example :
Connector ajpConnector = new Connector("org.apache.coyote.ajp.AjpNioProtocol");
list of available implementations :
https://tomcat.apache.org/tomcat-8.0-doc/config/ajp.html#Common_Attributes
(protocol)
or simply specify the protocol (AJP instead of HTTP):
Connector ajpConnector = new Connector("AJP/1.3");
For complete example to dynamically read values from properties file please see https://blog.swdev.ed.ac.uk/2015/06/24/adding-embedded-tomcat-ajp-support-to-a-spring-boot-application/
Related
I have a Spring Boot application (version 1.5.1.RELEASE) and I am using spring-boot-starter-data-jpa as a dependency to manage my database. I am using postgres as my database and configured it using the below properties.
spring.datasource.url=${POSTGRES_URL}
spring.datasource.username=${POSTGRES_USER}
Now when I run my tests which are almost 120, I get too many client already open error for abou 10 test cases while starting the test case itself and it fails.(remaining 100 test cases pass with success as they are able to get a connection to database)
First thing I did is increased my default postgres max connections count from 100 to 200 in the postgres server config file and my tests pass successfully after this change.
Now I investigated a bit and tried setting the parameters for connection pooling properties such as :
spring.datasource.tomcat.max-active=200
spring.datasource.tomcat.test-on-borrow=true
spring.datasource.tomcat.max-wait=10000
However these properties do not work and the tests fails again giving the same error as above. I tried reading from multiple different blogs and spring documentation for setting the connection pool properties but did not find what might be going wrong with me.
I also think that if I set the above property spring.datasource.tomcat.max-active to 100 connections it should work with the help of tomcat jdbc pooling as i think in current scenario it is trying to open a new connection to database for each test case and I am in a fear that this same scenario might happen when I deploy this code to production environment and a new connection will be opened to the database for each request.
Does anyone have faced this problem before or is there something wrong I am doing.
Thanks in advance for the help.
Try upgrading Spring boot version, 1.5.10-RELEASE is the current version.
Also, I found the connection pool properties for my application were not being applied when the property prefix tomcat was included. If you are still having issues try removing that.
i.e.
spring.datasource.tomcat.max-active=200
Becomes
spring.datasource.max-active=200
See https://artofcode.wordpress.com/2017/10/19/spring-boot-configuration-for-tomcats-pooling-data-source
I am trying to use JMeter to work with IBM MQ.
As per the article I created the JNDI Bindings.
Now I am trying to connect JMeter using the JNDI Bindings. I give the QCF (Queue Connection Factory), but it is throwing an error
"Response message: java.lang.IllegalStateException: QueueConnectionFactory expected, but got javax.naming.Reference"
I searched around a lot, but didnt find anything. I looked at source code for Sampler and it looks like it is not able to find the Connection Factory from the JNDI.
Any idea what could i be missing? I Didnt know if the Configuration details would help, if it would i can provide that.
Thanks in Advance!
I was able to resolve this by copying all the MQ Jars (that comes with a complete Websphere MQ installation) and placing them into JMeter/Lib.
Now it works fine.
Thanks for anyone who viewed this. Hope my answer may provide some light to others who may encounter the same problem.
the glassfish application server provides a nice monitoring REST interface.
To use it u can enable several monitorable items in the admin console, for example the EJB container. The documentation says, you can retreive EJB-statistics for every deployed application.
If you request a URL like localhost:4848/monitoring/domain1/server/applications/APPNAME/EJBNAME you will get statistics for a given EJB of the application.
Further, there is a possibility to look more deeply into each bean-method of the ejb, for example the executiontime, about which the documentation says:
"Time, in milliseconds, spent executing the method for the last successful/unsuccessful attempt to run the operation. This is collected for stateless and stateful session beans and entity beans if monitoring is enabled on the EJB container."
The problem now is, monitoring is enabled on the EJB-container (Level set to HIGH), but nothing is sampled in any bean-method in any EJB in any deployed application.
Is there something special to do in the bean and/or the glassfish ?
Thanks in advance for help,
Chris
EDIT:
Ok, I noticed something more about that behaviour:
In the server log you get a log message for each deployed EJB like that:
INFO: EJB5181:Portable JNDI names for EJB DataFetcher // ...
If I set the ejb-container monitoring level to HIGH (which is what I want to do), I get the following warning for each deployed EJB, regardless which app I deploy:
WARNING: MNTG0201:Flashlight listener registration failed for listener class : com.sun.ejb.monitoring.stats.StatelessSessionBeanStatsProvider , will retry later
I googled the warning but none of the resulst really help me enabling EJB monitoring...
This seems to be a Bug in Glassfish.
EJB Monitoring is currently not working in 3.1.2.
JIRA issue is already raised: http://java.net/jira/browse/GLASSFISH-19677
There is nothing "special" to do.
http://docs.oracle.com/cd/E18930_01/html/821-2431/abeea.html
For me it seems as if you probably enabled the monitoring option on the wrong configuration. Please double check.
To get rid of this message you can disable the monitoring on ejb container option below in the image
From Monitor Data--->Configure monitoring--->make ejb container log off
I am facing a strange situation while using HornetQ.
My application architecture -
JMS provider : HornetQ (Standalone server, not used for anything else. I've created 2 queues on this server, say Q1 and Q2).
Producer : A web application deployed on a separate machine. This application creates instances of "ObjectMessage", passing a "Job" class instance as argument to the "ObjectMessage.setObject()" method and adds the message to Q1. Uses Spring JMS.
I also set a string property named "AGENT" in the message before adding it to the queue.
What's peculiar is that if I call ObjectMessage.setStringProperty("AGENT", null) or if I do not add the property to the message itself, the message does not get added to Q1. However, this does not happen on Q2, and I'm able to see the message in HornetQ's JMX console.
Is there some queue specific configuration that I should be looking out for?
Apologies for the loose wording - My team and I have been facing a tough time trying to fix this issue.
Thanks.
How are you creating the Producer? and How are you sending it?
It seems you're not committing on a transactional session?
I'm assuming you are using JMS, but I would need to see some code to help you in a better fashion. Usually the JBoss Forum is a better suitable place for discussions like this, since the SOF is not really a discussion forum.
I think the best would be you open a forum on JBoss (since it will be followed by a discussion) and provide the link here.
I am currently trying to use an embedded ldap server for unit tests.
In Spring Security, you can quickly define an embedded ldap server for testing with the tag with some sample data loaded from the specified ldif.
I will be using Spring Ldap to perform ldap operations, and thinking of testing the usual CRUD features of my User service object.
Is there, however, a way to ensure that the entries in the embedded server to be in the same consistent state (sort of like a delete all and reload the ldif entries) for each test I am running?
I thought of the following:
1) Indicate that the method dirties the context, and force a recreation of the embedded ldap server, which sounds painful as it would have to restart the server for every method
2) Create the test entries in a test organization, such that I can unbind them and simply load in the ldif file again there.
I prefer 2, but it seems like the Spring LDAP has no good helpers to load and send across the content of a ldif file.
Any suggestions on how you perform ldap testing with an embedded ldap server of spring, or of the two possible solutions I mention?
Thanks
Doesn't Spring LDAP provide transactional control around LDAP operations? If so, why not use Spring test framework with its auto-rollback capability?
I also know of a JDBC-LDAP bridge driver that wraps an LDAP repository, presenting it as a relational database. I've used iBatis to connect to this (I've written this up at http://lokibear.blogspot.com, see articles from July). I've not yet tried applying transactional control, but the website for the driver mentions the ability to ignore transactions (which means you can also not ignore them...right?).
Like I say, I haven't tried this yet; but, if this provides transactions around LDAP, then you can again use the Spring test framework to get auto-rollback in place. I've put out a quick cheatsheet around that framework - see the September posts at my blog.
Sorry, I might be missing your goal here; but perhaps these suggestions are useful. Good luck!
I may be off-track here, but if you're not testing the LDAP integration itself, you could Mock out the LDAP connection with a Mock object that always returns the values you expect so that your other Unit Tests can complete.
If you're testing the LDAP connection then you're really doing an integration test. In which case it's probably best to connect to a real LDAP implementation.
You may or may not know that the embedded LDAP functionality is not provided by Spring LDAP itself, but Apache Directory Server. Unfortunately, the LDIF loader in Apache DS (as wired by Spring, anyway) has very poor error handling and reporting capability, and as such is probably not going to behave as you really want for a unit test. Your best bet if you really want to start from a clean slate each time is to take the lead of the Spring Security LDAP unit tests and reinitialize Apache DS every time, with a clean LDIF file load.
Alternatively, you could eschew LDIF altogether and construct your own unit test wrapper that verifies the pre- and post-conditions of the data prior to your unit tests running. This would be more work, but ultimately may work out better for you.
Works fine for me:
#Inject
private ApplicationContext applicationContext;
#Before
public void reloadLdapDirectory() throws NamingException, IOException{
ApacheDSContainer apacheDSContainer = (ApacheDSContainer) applicationContext.getBean(BeanIds.EMBEDDED_APACHE_DS);
LdapTestUtils.clearSubContexts(contextSource, DistinguishedName.EMPTY_PATH);
ClassPathResource classPathResource = new ClassPathResource("ldap.ldif");
File tempFile = File.createTempFile("spring_ldap_test", ".ldif");
try {
InputStream inputStream = classPathResource.getInputStream();
IOUtils.copy(inputStream, new FileOutputStream(tempFile));
LdifFileLoader fileLoader = new LdifFileLoader(apacheDSContainer.getService().getAdminSession(), tempFile.getAbsolutePath());
fileLoader.execute();
}
finally {
try {
tempFile.delete();
}
catch (Exception e) {
// Ignore this
}
}
}
I asked something similar and got an answer from Luke Taylor: Integration tests with spring-security and ldap