Jersey Grizzly REST service not visible outside localhost - rest

I'm trying to write a REST service in java using Jersey and Glassfish Grizzly. I have a very simple case working internally, but can't seem to call on the server from an external address. I've tried using a variety of different pairs of machines with externally visible IP's, and tried specifying the actual IP address in the server instead of localhost, but nothing works. I'm somewhat loosely following the official user guide here. My resource:
package resources;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
#Path("/simpleREST")
public class SimpleRESTResource
{
#GET
#Produces("text/plain")
public String getMessage()
{
return "Message from server\n";
}
}
And the server:
import java.io.IOException;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.grizzly.http.server.HttpServer;
import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
import com.sun.jersey.api.core.PackagesResourceConfig;
import com.sun.jersey.api.core.ResourceConfig;
public class Main
{
public static final URI BASE_URI = UriBuilder.fromUri("http://localhost").port(9998).build();
public static void main(String[] args) throws IOException
{
System.out.println("Starting grizzly...");
ResourceConfig rc = new PackagesResourceConfig("resources");
HttpServer myServer = GrizzlyServerFactory.createHttpServer(BASE_URI, rc);
System.out.println(String.format("Jersey app started with WADL available at %s/application.wadl\n" +
"Try out %s/simpleREST\nHit enter to stop it...", BASE_URI, BASE_URI));
System.in.read();
myServer.stop();
}
}
On the same machine, I can successfully interact with the server using
curl -X GET localhost:9998/simpleREST
OR
curl -X GET [external numeric address]:9998/simpleREST
Many thanks in advance for any suggestions.
SOLUTION
I have fixed this problem by setting the server URI to http://0.0.0.0:9998 instead of localhost, 127.0.0.1, or the actual address.

To make a server IP adress visible outside of localhost, you must fist open the neccessary firewall ports(if you have one), or use "0.0.0.0" instead of "localhost" in order for the server to listen to all IP addresses and network adapters. Before testing it in your local network, try pinging your server device from your client device to check if there is an actual connection or if the devices are not connected at all.

With Jersey and Grizzly 2.30, it's simpler:
final ResourceConfig rc = new ResourceConfig().packages("com.rest");
HttpServer httpServer = Grizzly
HttpServerFactory.createHttpServer(URI.create("http://0.0.0.0:9998/api/"), rc);

or, you can try these codes below:
ResourceConfig rc = new PackagesResourceConfig("your-rest-packages");
HttpHandler handler = ContainerFactory.createContainer(HttpHandler.class, rc);
server = new HttpServer();
server.getServerConfiguration().addHttpHandler(handler);
//attach listeners
InetAddress localHost = InetAddress.getLocalHost();
String localHostAddr = localHost.getHostAddress();
NetworkListener localHostListener = new NetworkListener("localhost", localHostAddr, port);
server.addListener(localHostListener);
InetAddress loopback = InetAddress.getLoopbackAddress();
String loopbackAddr = loopback.getHostAddress();
NetworkListener loopbackListener = new NetworkListener("loopback", loopbackAddr, port);
now your server could both list to localhost and loopback

Related

Micronaut + Vertx + testcontainers

How do I configure Micronaut app using Vert.x and testcontainers? I'm trying:
application-test.yml
datasources:
default:
url: jdbc:tc:mysql:8:///db
driverClassName: org.testcontainers.jdbc.ContainerDatabaseDriver
vertx:
mysql:
client:
uri: jdbc:tc:mysql:8:///db
Tests with micronaut-data-jdbc work, but with micronaut-vertx-mysql-client not work:
Error:
Message: Cannot parse invalid connection URI: jdbc:tc:mysql:8:///db
I'm not very familiar with testecontainers, but it seems like it doesn't come up with a fixed port, so I don't know how to configure the connection URI.
Thanks!
It might be a problem that micronaut-vertx-mysql-client does not support the Testcontainers JDBC URL scheme (hard to say without further logs).
In this case, I would suggest to use Testcontainers with database container objects instead of the special JDBC URL.
I got a solution to the problem:
Micronaut + jdbc hikari + vertx mysql client + flyway mysql
package br.com.app;
import io.micronaut.context.ApplicationContext;
import io.micronaut.context.env.PropertySource;
import io.micronaut.core.util.CollectionUtils;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.client.HttpClient;
import io.micronaut.runtime.EmbeddedApplication;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
#Testcontainers
class AuthTest {
static Logger log = LoggerFactory.getLogger(AuthTest.class.getName());
#Container
static MySQLContainer mysql = new MySQLContainer("mysql:8");
private HttpClient client;
private static EmbeddedApplication application;
private static ApplicationContext context;
#BeforeAll
public static void initTests(){
log.info("Mysql is running {}, port {}", mysql.isRunning(), mysql.getFirstMappedPort());
var port = mysql.getFirstMappedPort();
var host = mysql.getHost();
var database = mysql.getDatabaseName();
var user = mysql.getUsername();
var password = mysql.getPassword();
var url = String.format("jdbc:mysql://%s:%s/%s", host, port, database);
application = ApplicationContext.run(EmbeddedApplication.class,
PropertySource.of(
"test",
CollectionUtils.mapOf(
"vertx.mysql.client.port", port,
"vertx.mysql.client.host", host,
"vertx.mysql.client.database", database,
"vertx.mysql.client.user", user,
"vertx.mysql.client.password", password,
"datasources.default.url", url,
"datasources.default.username", user,
"datasources.default.password", password,
"flyway.datasources.default.enabled", true
)
));
context = application.getApplicationContext();
}
#BeforeEach
void beforeEach(){
this.authService = context.getBean(AuthService.class);
this.client = context.getBean(HttpClient.class);
}
#Test
void testItWorks() {
Assertions.assertTrue(application.isRunning());
}
// api tests
}
Help links:
https://dev.to/major13ua/micronaut-integration-testing-using-testcontainers-2e30
https://github.com/major13ua/micronaut-tc/blob/main/src/test/java/com/example/testcontainer/controller/DemoControllerTest.java

IAm using InetAddress to get server IP but it resolves to local host because my server name is same as server IP, what should I do?

I am using following code to connect Jmeter to a remote mongo DB with authentication. I am using InetAddress to get server IP but it resolves to local host because my server name is same as server IP, what alternative should I use?
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import java.util.Arrays;
try {
String mongoUser = vars.get("mongouser");
String userDB = vars.get("userdb");
char[] password = vars.get("password").toCharArray();
MongoCredential credential = MongoCredential.createCredential(mongoUser,
userDB, password);
MongoClientSettings settings = MongoClientSettings.builder()
.applyToClusterSettings {builder ->
builder.hosts(Arrays.asList(new
ServerAddress(InetAddress.getByName(vars.get("mongohost"))
,vars.get("mongoPort").toInteger())))}
.build();
MongoClient mongoClient = MongoClients.create(settings);
MongoDatabase database = mongoClient.getDatabase(vars.get("databaseName"));
MongoCollection<Document> collection = database.getCollection(vars.get("collectionName"));
vars.putObject("collection", collection);
return "Connected to " + vars.get("collectionName");
}
catch (Exception e) {
SampleResult.setSuccessful(false);
SampleResult.setResponseCode("500");
SampleResult.setResponseMessage("Exception: " + e);
}
Iam getting following error which shows that InetAdress is not resolving my mongo host name (which is same as Mongo host IP i-e 10.80.47.101)
Response code: 500
Response message: Exception: com.mongodb.MongoTimeoutException: Timed out
after 30000 ms while waiting to connect. Client view of cluster state is
{type=UNKNOWN, servers=[{address=ibexdc1v-dbdev10.corp.ibexglobal.com:27002,
type=UNKNOWN, state=CONNECTING, exception=
{com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by
{java.net.ConnectException: Connection refused: connect}}]
If ibexdc1v-dbdev10.corp.ibexglobal.com is correct hostname for your mongohost JMeter Variable you check whether MongoDB instances is listening on port 27002 and ensure that the port is open in your operating system firewall
If ibexdc1v-dbdev10.corp.ibexglobal.com is not correct hostname for your mongohost JMeter Variable you should fix your machine DNS configuration
You can explicitly specify the hostname by slightly amending your script, i.e. change this line:
builder.hosts(Arrays.asList(new ServerAddress(InetAddress.getByName(vars.get("mongohost")), vars.get("mongoPort").toInteger())))
to this one:
builder.hosts(Collections.singletonList(new ServerAddress(vars.get("mongohost"), vars.get("mongoPort") as int)))
You might also be interested in the MongoDB Performance Testing with JMeter article

Sending an email using Google's SMTP server

I'm having a trouble sending an email using Google's SMTP Server. I've looked for a solution but i have not found one. So here's the code.
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
...
...
...
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt)
{
Properties props = new Properties();
props.put("true", "mail.smtp.auth");
props.put("true","mail.smtp.starttls.enable");
props.put("smtp.gmail.com", "mail.smtp.host");
props.put("587", "mail.smtp.port");
Session sess=Session.getDefaultInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication("myemail#gmail.com", "mypassword");
}
}
);
try{
Message message= new MimeMessage(sess);
message.setFrom(new InternetAddress("myemail#gmail.com"));
message.setRecipients(Message.RecipientType.TO,InternetAddress.parse("myemail#gmail.com"));
message.setSubject("message");
message.setText("text");
Transport.send(message);
JOptionPane.showMessageDialog(null, "Sent!");
}catch(Exception e){
JOptionPane.showMessageDialog(null, e);
}
Each time when i press the button, it show me this error:
javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25;
nested exception is:
java.net.ConnectException: Connection refused: connect
I've tried 3 ports: 25, 465, 587 , but it always gives me that error. I even made new rules for the port 25 to the firewall settings, but that doesn't seem to do the trick. Any thoughts what am i doing wrong? Could hibernate cause the problem? Because i'm using it in this project. Plus, i have installed mysql.
Your program is trying to connect to a local port, that's why it failed. If your listing is real code, you got the key and value backwards in the props.set statements.

Could not find or load main class in Client-Server programming

I am trying to run Client code in Clinet-Server programming in java and I am getting error "Could not find or load main class."
javac DateClient.java
java DateClient (I have also tried "java -cp . DateClient" but still not working).
Program which I am trying to run is :
package edu.lmu.cs.networking;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import javax.swing.JOptionPane;
public class DateClient {
public static void main(String[] args) throws IOException {
String serverAddress = JOptionPane.showInputDialog(
"Enter IP Address of a machine that is\n" +
"running the date service on port 9090:");
Socket s = new Socket(serverAddress, 9090);
BufferedReader input =new BufferedReader(new InputStreamReader(s.getInputStream()));
String answer = input.readLine();
JOptionPane.showMessageDialog(null, answer);
System.exit(0);
}
}
Your class is in the package edu.lmu.cs.networking. Its name is thus edu.lmu.cs.networking.DateClient. And you thus need to execute it with
java -cp . edu.lmu.cs.networking.DateClient
(assuming . contains the edu directory, which contains the lmu directory, which contains the cs directory, which contains the networking directory, which contains the file DateClient.class).

Neo4j cannot accept big http rest requests

I'm trying to send one very big http post request to stand alone neo4j server (neo4j-community-1.9.M01).
Bellow is the sample code that I'm using.
The input file: ideas/src/test/test-rest.txt contains one very big json string (more than (250k).
The problem is that I cannot control a lot of settings of the web server launched by the standalone version of neo4j. Probably there is some limit on the web server that prevent me to send big post requests. Could someone help me to find out this setting.
Alternative : could some one tell me how to replace the default webserver used by neo4j for example with tomcat.
The error that I receive on the client is:
Caused by: java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:105)
at java.io.FilterOutputStream.write(FilterOutputStream.java:80)
at org.apache.commons.httpclient.WireLogOutputStream.write(WireLogOutputStream.java:86)
at com.sun.jersey.client.apache.DefaultApacheHttpMethodExecutor$3.writeRequest(DefaultApacheHttpMethodExecutor.java:186)
at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at com.sun.jersey.client.apache.DefaultApacheHttpMethodExecutor.executeMethod(DefaultApacheHttpMethodExecutor.java:210)
Here are some logs from the web client:
11-11#08:28:01 INFO (HttpMethodDirector.java:445) - Retrying request
11-11#08:28:01 DEBUG (HttpConnection.java:692) - Open connection to localhost:7474
11-11#08:28:01 DEBUG ( Wire.java:70) - >> "POST /db/data/batch HTTP/1.1[\r][\n]"
11-11#08:28:01 DEBUG (HttpMethodBase.java:1352) - Adding Host request header
11-11#08:28:01 DEBUG ( Wire.java:70) - >> "Accept: application/json; stream=true[\r][\n]"
11-11#08:28:01 DEBUG ( Wire.java:70) - >> "X-Stream: true[\r][\n]"
11-11#08:28:01 DEBUG ( Wire.java:70) - >> "Content-Type: application/json[\r][\n]"
11-11#08:28:01 DEBUG ( Wire.java:70) - >> "User-Agent: Jakarta Commons-HttpClient/3.1[\r][\n]"
11-11#08:28:01 DEBUG ( Wire.java:70) - >> "Content-Length: 246292[\r][\n]"
11-11#08:28:01 DEBUG ( Wire.java:70) - >> "Host: localhost:7474[\r][\n]"
11-11#08:28:01 DEBUG ( Wire.java:70) - >> "[\r][\n]"
11-11#08:31:22 DEBUG (HttpMethodDirector.java:404) - Closing the connection.
11-11#08:31:22 DEBUG (HttpMethodDirector.java:434) - Method retry handler returned false. Automatic recovery will not be attempted
11-11#08:31:22 DEBUG (HttpConnection.java:1178) - Releasing connection back to connection manager.
Here is the client code:
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.client.apache.ApacheHttpClient;
import org.apache.commons.io.FileUtils;
import org.neo4j.rest.graphdb.RequestResult;
import org.neo4j.rest.graphdb.UserAgent;
import javax.ws.rs.core.MediaType;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
public class Main {
private static final UserAgent userAgent = new UserAgent();
public static final MediaType STREAMING_JSON_TYPE = new MediaType(APPLICATION_JSON_TYPE.getType(),APPLICATION_JSON_TYPE.getSubtype(), stringMap("stream","true"));
public static void main(String[] args) throws URISyntaxException, IOException {
String data = FileUtils.readFileToString(new File("ideas/src/test/test-rest.txt"));
Client client = createClient();
WebResource resource = client.resource(new URI("http://localhost:7474/db/data/batch"));
WebResource.Builder builder = resource.accept(STREAMING_JSON_TYPE).header("X-Stream", "true");
builder.entity( toInputStream(data), APPLICATION_JSON_TYPE );
System.out.println(RequestResult.extractFrom(builder.post(ClientResponse.class)));
}
private static InputStream toInputStream(String data) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(4024 * 1024);
outputStream.write(data.getBytes());
byte[] buf = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(buf);
return inputStream;
}
protected static Client createClient1() {
Client client = Client.create();
client.setConnectTimeout(800);
client.setReadTimeout(800);
client.setChunkedEncodingSize(80 * 1024);
userAgent.install(client);
return client;
}
protected static Client createClient() {
Client client = ApacheHttpClient.create();
return client;
}
private static Map<String, String> stringMap(String stream, String aTrue) {
HashMap<String, String> result = new HashMap<String, String>();
result.put(stream, aTrue);
return result;
}
}
Thanks in advance.
I found the reason of the problem.
I was running under Virtual BOX 4.2.0 with Windows XP guest machine and windows 7 host machine machine.
After putting the server on another machine, the problem disappeared.
I investigated with wireshark, before the failure I saw a lot of tcp packages that were not acknowledged and therefore retransmitted.
My question is still opened:how to replace the default webserver used by neo4j for example with tomcat?