I am facing a strange problem and I can't figure out the problem. I have a web application/portlet deployed in Liferay portal which should be sending an email. I have the configuration correct and the code looks like this:
Session mailSession = mailSender.getSession();
Transport transport = mailSession.getTransport("smtp");
Message message = buildMessage(); // placeholder for building the message
try {
transport.sendMessage(msg, msg.getAllRecipients());
} finaly {
transport.close();
}
This, however, always tries to connecto to localhost:
com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1;
liferay_1 | nested exception is:
liferay_1 | java.net.ConnectException: Connection refused (Connection refused)
Now, I though that the connection settings are not correct, so I decided to log them:
LOG.debug("Host:" + mailSender.getHost() + " --- Port: " + mailSender.getPort());
LOG.debug("Password:" + mailSender.getPassword() + " --- User: " + mailSender.getUsername());
mailSession.getProperties().entrySet().forEach(p -> LOG.debug("---" + p.getKey() + "-" + p.getValue()));
And they are indeed correct in the session:
liferay_1 | DEBUG [http-nio-8080-exec-1] (MailSenderService:92) - Host:test-host --- Port: 5678
liferay_1 | DEBUG [http-nio-8080-exec-1] (MailSenderService:93) - Password:$test --- User: test
liferay_1 | DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
liferay_1 | DEBUG [http-nio-8080-exec-1] (MailSenderService:97) - ---mail.transport.protocol-smtp
liferay_1 | DEBUG [http-nio-8080-exec-1] (MailSenderService:97) - ---mail.debug-true
liferay_1 | DEBUG [http-nio-8080-exec-1] (MailSenderService:97) - ---mail.smtp.auth-test
liferay_1 | DEBUG [http-nio-8080-exec-1] (MailSenderService:97) - ---mail.smtp.starttls.enable-true
liferay_1 | DEBUG [http-nio-8080-exec-1] (MailSenderService:99) - Transport:smtp://liferay#
I can't figure out what else I can do and I don't know from where does the transport get localhost and port 25.
After further investigation, I discovered that there is a method for connecting to a specified host.
/**
* Similar to connect(host, user, password) except a specific port
* can be specified.
*
* #param host the host to connect to
* #param port the port to connect to (-1 means the default port)
* #param user the user name
* #param password this user's password
* #exception AuthenticationFailedException for authentication failures
* #exception MessagingException for other failures
* #exception IllegalStateException if the service is already connected
* #see #connect(java.lang.String, java.lang.String, java.lang.String)
* #see javax.mail.event.ConnectionEvent
*/
public synchronized void connect(String host, int port,
String user, String password) throws MessagingException
Using this one, you can specify the exact host, port and credentials. Why the Session does not contain this information and why it is not being used, even though the Transport and Session are obtained fro the original JavaMailSenderImpl is still a mystery to me.
What version of Liferay are you on?
First thing first, you will need to check if your credentials are correctly set up in Control Panel > Server Administration > Mail.
Check your:
Outgoing SMTP Server and
Outgoing Port
if they are still pointing to localhost and 25 respectively.
Second, the implementation looks unfamiliar to me. Can you try this way?
import com.liferay.mail.kernel.service.MailServiceUtil;
...
Message message = buildMessage();
MailServiceUtil.sendEmail(message);
or if you want to get a session
MailServiceUtil.getSession()
Related
I am starting to study how can I implement an application supporting Failover/FaultTolerance on top of JMS, more precisely EMS
I configured two EMS servers working both with FaultTolerance enabled:
For EMS running on server on server1 I have
in tibemsd.conf
ft_active = tcp://server2:7232
in factories.conf
[GenericConnectionFactory]
type = generic
url = tcp://server1:7232
[FTTopicConnectionFactory]
type = topic
url = tcp://server1:7232,tcp://server2:7232
[FTQueueConnectionFactory]
type = queue
url = tcp://server1:7232,tcp://server2:7232
And for EMS running on server on server2 I have
in tibemsd.conf
ft_active = tcp://server1:7232
in factories.conf
[GenericConnectionFactory]
type = generic
url = tcp://server2:7232
[FTTopicConnectionFactory]
type = topic
url = tcp://server2:7232,tcp://server1:7232
[FTQueueConnectionFactory]
type = queue
url = tcp://server2:7232,tcp://server1:7232
I am not a TIBCO EMS expert but my config seems to be good: When I start EMS on server1 I get:
$ tibemsd -config tibemsd.conf
...
2022-07-20 23:04:58.566 Server is active.
2022-07-20 23:05:18.563 Standby server 'SERVERNAME#server1' has connected.
then if I start EMS on server2, I get
$ tibemsd -config tibemsd.conf
...
2022-07-20 23:05:18.564 Accepting connections on tcp://server2:7232.
2022-07-20 23:05:18.564 Server is in standby state for 'tcp://server1:7232'
Moreover, if I kill active EMS on server1, I immediately get the following message on server2:
2022-07-20 23:21:52.891 Connection to active server 'tcp://server1:7232' has been lost.
2022-07-20 23:21:52.891 Server activating on failure of 'tcp://server1:7232'.
...
2022-07-20 23:21:52.924 Server is now active.
Until here, everything looks OK, active/standby EMS servers seems to be correctly configured
Things get more complicated when I write a piece of code how is supposed to connect to these EMS servers and to periodically publish messages. Let's try with the following code sample:
#Test
public void testEmsFailover() throws JMSException, InterruptedException {
int NB = 1000;
TibjmsConnectionFactory factory = new TibjmsConnectionFactory();
factory.setServerUrl("tcp://server1:7232,tcp://server2:7232");
Connection connection = factory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
connection.start();
for (int i = 0; i < NB; i++) {
LOG.info("sending message");
Queue queue = session.createQueue(QUEUE__CLIENT_TO_FRONTDOOR__CONNECTION_REQUEST);
MessageProducer producer = session.createProducer(queue);
MapMessage mapMessage = session.createMapMessage();
mapMessage.setStringProperty(PROPERTY__CLIENT_KIND, USER.toString());
mapMessage.setStringProperty(PROPERTY__CLIENT_NAME, "name");
producer.send(mapMessage);
LOG.info("done!");
Thread.sleep(1000);
}
}
If I run this code while both active and standby servers are up, everything looks good
23:26:32.431 [main] INFO JmsEndpointTest - sending message
23:26:32.458 [main] INFO JmsEndpointTest - done!
23:26:33.458 [main] INFO JmsEndpointTest - sending message
23:26:33.482 [main] INFO JmsEndpointTest - done!
Now If I kill the active EMS server, I would expect that
the standby server would instantaneously become the active one
my code would continue to publish such as if nothing had happened
However, in my code I get the following error:
javax.jms.JMSException: Connection is closed
at com.tibco.tibjms.TibjmsxLink.sendRequest(TibjmsxLink.java:307)
at com.tibco.tibjms.TibjmsxLink.sendRequestMsg(TibjmsxLink.java:261)
at com.tibco.tibjms.TibjmsxSessionImp._createProducer(TibjmsxSessionImp.java:1004)
at com.tibco.tibjms.TibjmsxSessionImp.createProducer(TibjmsxSessionImp.java:4854)
at JmsEndpointTest.testEmsFailover(JmsEndpointTest.java:103)
...
and in the logs of the server (the previous standby server supposed to be now the active one) I get
2022-07-20 23:32:44.447 [anonymous#cersei]: connect failed: server not in active state
2022-07-20 23:33:02.969 Connection to active server 'tcp://server2:7232' has been lost.
2022-07-20 23:33:02.969 Server activating on failure of 'tcp://server2:7232'.
2022-07-20 23:33:02.969 Server rereading configuration.
2022-07-20 23:33:02.971 Recovering state, please wait.
2022-07-20 23:33:02.980 Recovered 46 messages.
2022-07-20 23:33:02.980 Server is now active.
2022-07-20 23:33:03.545 [anonymous#cersei]: reconnect failed: connection unknown for id=8
2022-07-20 23:33:04.187 [anonymous#cersei]: reconnect failed: connection unknown for id=8
2022-07-20 23:33:04.855 [anonymous#cersei]: reconnect failed: connection unknown for id=8
2022-07-20 23:33:05.531 [anonymous#cersei]: reconnect failed: connection unknown for id=8
I would appreciate any help to enhance my code
Thank you
I think I found the origin of my problem:
according to the page Tibco-Ems Failover Issue, the error message
reconnect failed: connection unknown for id=8
means: "the store (ems db) was'nt share between the active and the standby node, so when the active ems failed, the new active ems was'nt able to recover connections and messages."
I realized that it is painful to configure a shared store. To avoid it, I configured two tibems on the same host, by following the page Step By Step How to Setup TIBCO EMS In Fault Tolerant Mode:
two tibemsd.conf configuration files
configure a different listen port in each file
configure ft_active with url of other server
configure factories.conf
By doing so, I can replay my test and it works as expected
I have created API key for sendGrid:
I have following spring mail configuration:
spring.mail.default-encoding=UTF-8
spring.mail.host=smtp.sendgrid.net
spring.mail.username=apikey
spring.mail.password=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
spring.mail.port=25
spring.mail.protocol=smtp
spring.mail.test-connection=true
And I have following code:
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message,
MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
StandardCharsets.UTF_8.name());
Template template = freemarkerConfig.getTemplate(templateFileName);
String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, props);
helper.setTo("myEmail#gmail.com");
helper.setText(html, true);
helper.setSubject(subject);
helper.setFrom(from);
sender.send(message);
logger.debug("Send email to {} with subject: [{}]", Arrays.toString(to), subject);
Then I try to start application and experience following error:
27.01.18 20:07:20.460 [main] WARN c.d.m.s.c.MailSenderValidatorAutoConfiguration - Mail server is not available
com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.sendgrid.net, 25; timeout -1
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2118)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:712)
at javax.mail.Service.connect(Service.java:366)
at org.springframework.mail.javamail.JavaMailSenderImpl.connectTransport(JavaMailSenderImpl.java:501)
at org.springframework.mail.javamail.JavaMailSenderImpl.testConnection(JavaMailSenderImpl.java:382)
How can I fix this?
P.S.
Everything correct for port 587
But I want to use ssl and set port=465
spring.mail.port=465
And at this case my application freezes on startup.and after 5 min prints:
27.01.18 21:06:05.960 [main] WARN c.d.m.s.c.MailSenderValidatorAutoConfiguration - Mail server is not available
javax.mail.MessagingException: Could not connect to SMTP host: smtp.sendgrid.net, port: 465, response: -1
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2106)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:712)
at javax.mail.Service.connect(Service.java:366)
at org.springframework.mail.javamail.JavaMailSenderImpl.connectTransport(JavaMailSenderImpl.java:501)
at org.springframework.mail.javamail.JavaMailSenderImpl.testConnection(JavaMailSenderImpl.java:382)
How can I avoid this?
I used the port 2525 (Non-privileged) instead of 578 (privileged) to solve the problem locally. I can still use the privileged one on the cloud. That solved my problem.
You may need add something like this to your configuration.
spring.mail.smtp.ssl.enable=true
There is a probability that SendGrid SMTP servers are not discoverable in your country. try a proxy or VPN.
I am creating an interface capable of reading e-mails from a shared mailbox. I have already tried several different approaches I could find in stack over, but none worked. Examples:
Properties props = System.getProperties();
// Set manual Properties
props.setProperty("mail.imaps.socketFactory.class", SSL_FACTORY);
props.setProperty("mail.imaps.socketFactory.fallback", "false");
props.setProperty("mail.imaps.port", "993");
props.setProperty("mail.imaps.socketFactory.port", "993");
props.put("mail.imaps.host", "outlook.office365.com");
try {
/* Create the session and get the store for read the mail. */
Session session = Session.getDefaultInstance(System.getProperties(), null);
Store store = session.getStore("imaps");
store.connect("outlook.office365.com", 993, "eduardo.david#hpe.com/APSDataExtract", "-myPassword-");
gives me the following result:
Exception while connecting to server: AUTHENTICATE failed.
javax.mail.AuthenticationFailedException: AUTHENTICATE failed.
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:661)
at javax.mail.Service.connect(Service.java:295)
at t2.OutLookReader_imaps.<init>(OutLookReader_imaps.java:39)
at t2.OutLookReader_imaps.main(OutLookReader_imaps.java:121)
If I try other codes, the result is the same:
store.connect("outlook.office365.com", 993, "hpe\\eduardo.david#hpe.com\\APSDataExtract", "-myPassword-");
Result:
Exception while connecting to server: * BYE Connection is closed. 13
javax.mail.MessagingException: * BYE Connection is closed. 13;
nested exception is:
com.sun.mail.iap.ConnectionException: * BYE Connection is closed. 13
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:668)
at javax.mail.Service.connect(Service.java:295)
at t2.OutLookReader_imaps.<init>(OutLookReader_imaps.java:39)
at t2.OutLookReader_imaps.main(OutLookReader_imaps.java:121)
Caused by: com.sun.mail.iap.ConnectionException: * BYE Connection is closed. 13
at com.sun.mail.iap.Protocol.handleResult(Protocol.java:356)
at com.sun.mail.imap.protocol.IMAPProtocol.authplain(IMAPProtocol.java:603)
at com.sun.mail.imap.IMAPStore.login(IMAPStore.java:736)
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:642)
... 3 more
store.connect("outlook.office365.com", 993, "hpe\\eduardo.david\\APSDataExtract", "-myPassword-");
Result:
Inside MailReader()...
Exception while connecting to server: * BYE Connection is closed. 13
javax.mail.MessagingException: * BYE Connection is closed. 13;
nested exception is:
com.sun.mail.iap.ConnectionException: * BYE Connection is closed. 13
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:668)
at javax.mail.Service.connect(Service.java:295)
at t2.OutLookReader_imaps.<init>(OutLookReader_imaps.java:39)
at t2.OutLookReader_imaps.main(OutLookReader_imaps.java:121)
Caused by: com.sun.mail.iap.ConnectionException: * BYE Connection is closed. 13
at com.sun.mail.iap.Protocol.handleResult(Protocol.java:356)
at com.sun.mail.imap.protocol.IMAPProtocol.authplain(IMAPProtocol.java:603)
at com.sun.mail.imap.IMAPStore.login(IMAPStore.java:736)
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:642)
... 3 more
store.connect("outlook.office365.com", 993, "hpe\\davidedu\\APSDataExtract", "-myPassword-");
Result:
Inside MailReader()...
Exception while connecting to server: * BYE Connection is closed. 13
javax.mail.MessagingException: * BYE Connection is closed. 13;
nested exception is:
com.sun.mail.iap.ConnectionException: * BYE Connection is closed. 13
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:668)
at javax.mail.Service.connect(Service.java:295)
at t2.OutLookReader_imaps.<init>(OutLookReader_imaps.java:39)
at t2.OutLookReader_imaps.main(OutLookReader_imaps.java:121)
Caused by: com.sun.mail.iap.ConnectionException: * BYE Connection is closed. 13
at com.sun.mail.iap.Protocol.handleResult(Protocol.java:356)
at com.sun.mail.imap.protocol.IMAPProtocol.authplain(IMAPProtocol.java:603)
at com.sun.mail.imap.IMAPStore.login(IMAPStore.java:736)
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:642)
... 3 more
To access my own inbox, code works perfectly:
store.connect("outlook.office365.com", 993, "eduardo.david#hpe.com", "-myPassword-");
Inside MailReader()...
No. of Unread Messages : 580
No. of Messages : 849
No. of Deleted Messages : 2
Can anybody give to this java new programmer a simple solution in order to read a shared mailbox?
I solved it adding this parameters:
sysProps.setProperty("mail.imaps.auth.plain.disable", "true");
sysProps.setProperty("mail.imaps.auth.ntlm.disable", "true");
I connected using:
store.connect("outlook.office365.com", "name#abc.com\\sharedmailAlias", "password");
My email: name#abc.com
My shared email address:
sharedmailAlias#abc.com
I've encountered the same issue as in this question, using Spring Boot 1.3.0 and not having my controllers annotated with #RestController, just #Path and #Service. As the OP in that question says,
this is, to me, anything but sensible
I also can't understand why would they have it redirect to /error. And it is very likely that I'm missing something, because I can only give back 404s or 200s to the client.
My problem is that his solution doesn't seem to work with 1.3.0, so I have the following request flow: let's say my code throws a NullPointerException. It'll be handled by one of my ExceptionMappers
#Provider
public class GeneralExceptionMapper implements ExceptionMapper<Throwable> {
private static final Logger LOGGER = LoggerFactory.getLogger(GeneralExceptionMapper.class);
#Override
public Response toResponse(Throwable exception) {
LOGGER.error(exception.getLocalizedMessage());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
And my code returns a 500, but instead of sending it back to the client, it tries to redirect it to /error. If I don't have another resource for that, it'll send back a 404.
2015-12-16 18:33:21.268 INFO 9708 --- [nio-8080-exec-1] o.glassfish.jersey.filter.LoggingFilter : 1 * Server has received a request on thread http-nio-8080-exec-1
1 > GET http://localhost:8080/nullpointerexception
1 > accept: */*
1 > host: localhost:8080
1 > user-agent: curl/7.45.0
2015-12-16 18:33:29.492 INFO 9708 --- [nio-8080-exec-1] o.glassfish.jersey.filter.LoggingFilter : 1 * Server responded with a response on thread http-nio-8080-exec-1
1 < 500
2015-12-16 18:33:29.540 INFO 9708 --- [nio-8080-exec-1] o.glassfish.jersey.filter.LoggingFilter : 2 * Server has received a request on thread http-nio-8080-exec-1
2 > GET http://localhost:8080/error
2 > accept: */*
2 > host: localhost:8080
2 > user-agent: curl/7.45.0
2015-12-16 18:33:37.249 INFO 9708 --- [nio-8080-exec-1] o.glassfish.jersey.filter.LoggingFilter : 2 * Server responded with a response on thread http-nio-8080-exec-1
2 < 404
And client's side (curl):
$ curl -v http://localhost:8080/nullpointerexception
* STATE: INIT => CONNECT handle 0x6000572d0; line 1090 (connection #-5000)
* Added connection 0. The cache now contains 1 members
* Trying ::1...
* STATE: CONNECT => WAITCONNECT handle 0x6000572d0; line 1143 (connection #0)
* Connected to localhost (::1) port 8080 (#0)
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x6000572d0; line 1240 (connection #0)
* STATE: SENDPROTOCONNECT => DO handle 0x6000572d0; line 1258 (connection #0)
> GET /nullpointerexception HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.45.0
> Accept: */*
>
* STATE: DO => DO_DONE handle 0x6000572d0; line 1337 (connection #0)
* STATE: DO_DONE => WAITPERFORM handle 0x6000572d0; line 1464 (connection #0)
* STATE: WAITPERFORM => PERFORM handle 0x6000572d0; line 1474 (connection #0)
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 404 Not Found
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< Content-Length: 0
< Date: Wed, 16 Dec 2015 17:33:37 GMT
<
* STATE: PERFORM => DONE handle 0x6000572d0; line 1632 (connection #0)
* Curl_done
* Connection #0 to host localhost left intact
So it's always a 404. Unless I do have such an /error resource, then what? what am I supposed to return? All I have at that point is a GET request to /error. And I don't want those extra requests consuming resources and polluting my logs.
What am I missing? And if nothing, what should I do with my exception handling?
You can set the Jersey property ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR to true.
Whenever response status is 4xx or 5xx it is possible to choose between sendError or setStatus on container specific Response implementation. E.g. on servlet container Jersey can call HttpServletResponse.setStatus(...) or HttpServletResponse.sendError(...).
Calling sendError(...) method usually resets entity, response headers and provide error page for specified status code (e.g. servlet error-page configuration). However if you want to post-process response (e.g. by servlet filter) the only way to do it is calling setStatus(...) on container Response object.
If property value is true the method Response.setStatus(...) is used over default Response.sendError(...).
Type of the property value is boolean. The default value is false.
You can set Jersey property simply by calling property(key, value) in your ResourceConfig subclass constructor.
I'm trying to connect to a Informix database server with jdbc using the standard way :
connection = DriverManager.getConnection("jdbc:informix-sqli://"+ip+
/"+sid+":INFORMIXSERVER="+server+";user="+user+";password="+pass+"");
But it keeps trying to connect and does not throw a error message (I suppose it tries to connect because it does not show anything). I'm using IBM Informix driver 4.10.00.1534 and Java 1.7.
I have been using this method to connect to Informix servers until now, in fact it only fails with one server. I can connect to this server through Informix clients with odbc but it keeps failing with jdbc with no error message.
Is there any method to verbose the jdbc connection? Any suggestion about why it fails?
UPDATE: The sqlidebug trace:
C->S (4)
SQ_VERSION
SQ_EOT
S->C (14)
SQ_VERSION
"7.31.TD6" [8]
SQ_EOT
C->S (66)
SQ_INFO
INFO_ENV
Name Length = 12
Value Length = 8
"DBTIME"="%d/%M/%Y"
"DBTEMP"="/tmp"
"SUBQCACHESZ"="10"
INFO_DONE
SQ_EOT
S->C (2)
SQ_EOT
C->S (16)
SQ_DBOPEN
"database" [8]
NOT EXCLUSIVE
SQ_EOT
S->C (28)
SQ_DONE
Warning..: 0x15
# rows...: 0
rowid....: 0
serial id: 0
SQ_COST
estimated #rows: 1
estimated I/O..: 1
SQ_EOT
C->S (78)
SQ_PREPARE
# values: 0
CMD.....: "select site from informix.systables where tabname = ' GL_COLLATE'" [65]
SQ_NDESCRIBE
SQ_WANTDONE
SQ_EOT
And the jdbctrace.log says:
trying com.informix.jdbc.IfxDriver
SQLWarning: reason(Database selected) SQLState(01I04)
SQLWarning: reason(Float to decimal conversion has been used) SQLState(01I05)
SQLWarning: reason(Database has transactions) SQLState(01I01)
SQLWarning: reason(Database selected) SQLState(01I04)
SQLWarning: reason(Database has transactions) SQLState(01I01)
SQLWarning: reason(Database selected) SQLState(01I04)
Try to run code that connects do Informix database but also shows full exception info and create trace files. One trace file is for JDBC, one is for Informix. Change URL to database, username and password, and run it. You will probably see the problem on screen or in trace file:
import java.io.FileWriter;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
class informix_trace
{
public static void main(String[] args)
{
try
{
Class.forName("com.informix.jdbc.IfxDriver");
FileWriter fwTrace = new FileWriter("c:\\JDBCTrace.log");
PrintWriter pwTrace = new PrintWriter(fwTrace);
DriverManager.setLogWriter(pwTrace);
String debug_url = "SQLIDEBUG=C:\\sqlidebug.trace";
String url = "jdbc:informix-sqli://1.2.3.4:9088/test_db:informixserver=ol_testifx;DB_LOCALE=pl_PL.CP1250;CLIENT_LOCALE=pl_PL.CP1250;charSet=CP1250;" + debug_url
Connection connection = DriverManager.getConnection(url, "user", "passwd");
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT FIRST 1 DBINFO('version','full') FROM systables;");
while (resultSet.next())
System.out.println(resultSet.getObject(1));
}
catch (Exception e)
{
e.printStackTrace();
}
}
} // class informix_trace
Informix trace file will be with some postfix (timestamp or similar info) and in my case it was something like sqlidebug.trace1391758523500.0. It is binary but you can analyze it using sqliprt utility.
Example of my session with wrong database name:
c:\>sqliprt sqlidebug.trace1391758523500.0
SQLIDBG Version 1
...
S->C (12)
SQ_ERR
SQL error..........: -329
ISAM/RSAM error....: -111
Offset in statement: 0
Error message......: "" [0]
SQ_EOT
In JDBCTrace.log I can found more interesting info (I see it also on my screen):
SQLState(IX000) vendor code(-111)
java.sql.SQLException: ISAM error: no record found.
at com.informix.util.IfxErrMsg.getSQLException(IfxErrMsg.java:413)
at com.informix.jdbc.IfxSqli.E(IfxSqli.java:3412)
at com.informix.jdbc.IfxSqli.dispatchMsg(IfxSqli.java:2324)
....
at java.sql.DriverManager.getConnection(Unknown Source)
at informix_trace.main(informix_trace.java:20)
getConnection failed: java.sql.SQLException: No database found or wrong system privileges.
(I have translated it from Polish so it can be little different)
My suggestion is to:
build ConnectString and show us its full content, this way we will see if in ip there is only IP address or if it is with port number
instead of adding username and password to ConnectString use 3 parameter version of getConnection() just like:
getConnection("jdbc:informix-sqli://169.0.5.10:9088/test_db:informixserver=ol_test;DB_LOCALE=pl_PL.CP1250;CLIENT_LOCALE=pl_PL.CP1250;charSet=CP1250", username, password)
(of course set your own locale instead of my Polish locale)
To spy network traffic use tools like Wireshark. Start capturing ip traffic to your Informix database. In my case Wireshark rule is:
ip.addr == 169.0.5.10
If I set up wrong IP Wireshark will display "Destination unreachable".
You can also see someting using netstat:
c:\>netstat -an | grep 9088
TCP 169.0.1.126:4295 169.0.5.10:9088 TIME_WAIT
It was when my application stopped working.
In case of error (wrong IP port) I see:
c:\>netstat -an | grep 9089
TCP 169.0.1.126:4398 169.0.5.10:9089 SYN_SENT
IBM says that: From version 3.00.JC1 of IBM® Informix® JDBC Driver onwards, debug drivers are no longer shipped.
Informix JDBC Driver now supports SQLIDEBUG. You no longer need to set values for TRACE, TRACEFILE or PROTOCOLTRACE, PROTOCOLTRACEFILE. You only need to set SQLIDEBUG. and the page goes on to outline the steps you need to create a trace. Copying:
Set the CLASSPATH to the Informix JDBC Driver package.
c:\Infx\Java>set
CLASSPATH=C:\infx\JDBC3.00JC3\lib\ifxjdbc.jar;C:\infx\JDBC3.00JC3\lib\ifxjdbcx.jar;.
Compile simple.java
c:\Infx\Java>javac simple.java
Ensure that SQLIDEBUG is set correctly
c:\Infx\Java>grep SQLIDEBUG simple.java
conn=DriverManager.getConnection("jdbc:informix-sqli://irk:1526/sysmaster:INFORMIXSERVER=irk940;USER=informix;
PASSWORD=ximrofni;SQLIDEBUG=C:\infx\java\trace");
Note: SQLIDEBUG is set in the connection string. It points to where
the trace file will be found with a certain format i.e.
trace.xxxxxxx
Remove or move all other trace files
c:\Infx\Java>del trace*
Run java.simple
c:\Infx\Java>java simple systables syscolumns ... ...
oledbordinals
Then locate the trace file
c:\Infx\Java>dir trace* Volume in drive C has no label. Volume
Serial Number is B823-46D8
Directory of c:\Infx\Java
04/04/2006 14:12 20,560 trace1144156355642.0 1 File(s) 20,560 bytes
0 Dir(s) 4,067,995,648 bytes free
c:\Infx\Java>
You will be able to see that a trace file has been created however
you will not be able to read the file.
Send the trace file to your local technical support office for
analysis.
Of course, if you're not using Version 3.00.JC1 of the Informix drivers, ignore the above and follow a different set of instructions; again duplicated for your convenience:
To turn on tracing, specify the environment variables TRACE,
TRACEFILE, PROTOCOLTRACE, and PROTOCOLTRACEFILE in the database URL or
the property list when you establish a connection to an Informix
database or database server. TRACE can be set to one of the following
levels:
Tracing not enabled. This is the default value.
Traces the entry and exit points of methods.
Same as Level 1, plus generic error messages are also traced.
Same as Level 2, plus data variables are also traced. TRACEFILE Specifies the full pathname of the operating system file on the client
computer to which the TRACE messages are written.
PROTOCOLTRACE traces the SQLI protocol messages sent between your Java
program and the Informix database server.
Can be set to the following levels:
Protocol tracing not enabled. This is the default value.
Traces message IDs.
Same as Level 1, plus the data in the message packets are also traced. PROTOCOLTRACFILE specifies the full pathname of the operating
system file on the client computer to which the PROTOCOLTRACE messages
are written.
Hope that helps
try different jdbc version
check NETTYPE configuration parameter and compare it with current number of informix sessions
dump java thread states (kill -3 ) when jdbc connection hangs
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import com.informix.*;
public class DBConnect {
static String url="jdbc:informix-sqli://host_name:port/database_name:INFORMIXSERVER=server;user=username;password=password";
public static void main(String [] args){
try {
Class.forName("com.informix.jdbc.IfxDriver");
}catch (Exception e){
System.out.println("ERROR: failed to load Informix JDBC driver.");
e.printStackTrace();
return;
}
try{
DriverManager.registerDriver((com.informix.jdbc.IfxDriver)Class.forName("com.informix.jdbc.IfxDriver").newInstance());
}catch(Exception ex){
System.out.println("Driver is not Registered");
}
try{
Connection conn = DriverManager.getConnection(url);
System.out.println("Connection Successful");
}catch (SQLException e){
System.out.println("ERROR: failed to connect!");
System.out.println("ERROR: " + e.getMessage());
e.printStackTrace();
return;
}
}
}
For more info go through [this book] (http://www.cursor-distribution.de/aktuell.11.70.xC6/documentation/ids_jdbc_bookmap.pdf)
The problem I encountered was that Informix was listening on local IPv6 address on port 7360, command netstat -a was displaying this format :
TCP [feab::11ab:78ab:efab:8aab%17]:7360 myhostname:0 LISTENING
Therefore my jdbc connection was always failing until I figured out I should have use the IPv6 address in the URL :
jdbc:informix-sqli://fe80::1125:78c0:ef17:8ab5%17:7360:user=informix;password=test;INFORMIXSERVER=ol_informix1210_2
You can test that the connection is working with this simple script :
/***************************************************************************
*
* Title: SimpleConnection.java
*
* Description: Demo a connection to a server (no database specified)
*
* An example of running the program:
*
* java SimpleConnection
* 'jdbc:informix-sqli://myhost:1533:user=<username>;password=<password>'
*
* Expected result:
*
* >>>Simple Connection test.
* URL = "jdbc:informix-sqli://myhost:1533:user=<username>;password=<password>"
* >>>End of Simple Connection test.
*
***************************************************************************
*/
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class SimpleConnection {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("FAILED: connection URL must be provided in order to run the demo!");
return;
}
String url = args[0];
String testName = "Simple Connection";
Connection conn = null;
System.out.println(">>>" + testName + " test.");
System.out.println("URL = \"" + url + "\"");
try {
Class.forName("com.informix.jdbc.IfxDriver");
} catch (Exception e) {
System.out.println("FAILED: failed to load Informix JDBC driver.");
}
try {
PrintWriter out = new PrintWriter(System.out, true);
DriverManager.setLogWriter(out);
conn = DriverManager.getConnection(url);
} catch (SQLException e) {
System.out.println("FAILED: failed to connect!");
}
try {
conn.close();
} catch (SQLException e) {
System.out.println("FAILED: failed to close the connection!");
}
System.out.println(">>>End of " + testName + " test.");
}
}