Confusions regarding InetAdress.getByName() - java

I am trying to write a class which would print the actual hostname of the IP address supplied as an argument to the InetAddress.getByName(). But everytime I run the program the IP address gets printed on the console rather than the hostname.
This is my output:=
208.73.211.249
What would I have to do to print it correctly?
import java.net.*;
public class Inet1 {
public static void main(String[] args) throws UnknownHostException {
InetAddress ia=null;
ia=InetAddress.getByName("74.125.236.50");
System.out.print(ia.getHostName());
}
}

InetAddress inetAddr = InetAddress.getByName("74.125.236.50");
String hostname = inetAddr.getHostName(); // Get the host name

The underlying system configuration might not allow you to access the host name. Then there's nothing you can do on Java level.
Have you tried
System.out.println(ia.getCanonicalHostName());
?

Related

Failing unit test with mockito.mockStatic

So, I'm writing a junit test and I can't seem te figure out why it is failing. I'm using Mockito.mockStatic in order to mock InetAddres.class. Running the unit tests all at once fails. Running them separately succeeds. I understand static blocks are initialized once. What I can't seem to figure out is why class Host is not reinitialized with every unit test. Any help is appreciated
J
Here is my code:
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import java.net.InetAddress;
import java.net.UnknownHostException;
import static org.assertj.core.api.Assertions.assertThat;
class HostTest {
#Test
void testLocalhost() {
try (MockedStatic<InetAddress> inetAddressMockedStatic = Mockito.mockStatic(InetAddress.class)) {
InetAddress inetAddress = Mockito.mock(InetAddress.class);
Mockito.when(inetAddress.getHostName()).thenReturn("LOCALHOST");
inetAddressMockedStatic.when(InetAddress::getLocalHost).thenReturn(inetAddress);
assertThat(Host.getLOCALHOST()).isEqualTo("LOCALHOST");
Mockito.reset(inetAddress);
}
}
#Test
void testIP() {
try (MockedStatic<InetAddress> inetAddressMockedStatic = Mockito.mockStatic(InetAddress.class)) {
InetAddress inetAddress = Mockito.mock(InetAddress.class);
Mockito.when(inetAddress.getHostAddress()).thenReturn("127.0.0.1");
inetAddressMockedStatic.when(InetAddress::getLocalHost).thenReturn(inetAddress);
assertThat(Host.getIP()).isEqualTo("127.0.0.1");
}
}
#Test
void testUnkownHostExceptionIP() {
try (MockedStatic<InetAddress> inetAddressMockedStatic = Mockito.mockStatic(InetAddress.class)) {
inetAddressMockedStatic.when(InetAddress::getLocalHost).thenThrow(UnknownHostException.class);
assertThat(Host.getIP()).isEqualTo("Unkown ip");
}
}
#Test
void testUnkownHostExceptionLocalhost() {
try (MockedStatic<InetAddress> inetAddressMockedStatic = Mockito.mockStatic(InetAddress.class)) {
inetAddressMockedStatic.when(InetAddress::getLocalHost).thenThrow(UnknownHostException.class);
assertThat(Host.getLOCALHOST()).isEqualTo("Unkown hostname");
}
}
}
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Host {
private static String LOCALHOST;
private static String IP;
static {
try {
InetAddress localhost = InetAddress.getLocalHost();
LOCALHOST = localhost.getHostName();
IP = localhost.getHostAddress();
} catch (UnknownHostException e) {
LOCALHOST = "Unkown hostname";
IP = "Unkown ip";
}
}
public static String getLOCALHOST() {
return LOCALHOST;
}
public static String getIP() {
return IP;
}
}
The static initializer is only executed once, when the class is loaded. This means it will only run for the first test case using the Host class.
In your example, once testLocalhost is run, the class is used in the line Host.getLOCALHOST(), by which point its initializer has been executed. It never runs again throughout the rest of the unit tests.
If you switch the order of these test cases, you'll get a different result.
Judging by your test cases, there's a few things you could do to make the code match your expectations. Since the IP and the host name will change throughout the execution of your program, they shouldn't be static members set in the static initializer block.
Get rid of shared state. Setting aside concurrency and memory visibility, static members will be visible to all instances of the class. Omit the static keyword and make these into regular fields
public class Host {
private final String hostName;
private final String ip;
// Constructor, use this to build new instances
public Host(String hostName, String ip) {
this.hostName = hostName;
this.ip = ip;
}
// No longer static, this is now an instance method
public getHostName() {
return this.hostName;
}
public getIp() {
return this.ip;
}
}
Build instances of your class, passing arguments to the constructor to customize its behaviour.
// Host.getIp(); // If IP and host name can vary, don't make them static
InetAddress localhost = InetAddress.getLocalHost();
// build a new instance of Host, provide the relevant data at construction time
Host testedHost = new Host(localhost.getHostName(), localhost.getHostAddress());
// call the instance method, this doesn't affect your other tests
assertThat(testedHost.getIp()).is(someIp);
// at this point, the Host instance you created may be garbage-collected to free memory (you don't need to do that yourself)
Now every test case will be independent from the others. Just create a new instance of Host every time you need one.
Get rid of static mocks. notice how the InetAddress method invocations were moved outside the Host class. By passing them through the constructor, you make the code easier to test. Inversion of control is achieved.
Instead of a public constructor, you could use a factory method. Bottom line is that if you want to have the class change its behaviour, it's usually better to create new instances and encapsulate any state.
Static classes and members are better suited for things like immutable contants that won't change throughout the execution of your program, or utility methods that don't rely on any internal state, i.e. pure functions.

is it possible to make a system SMS Based Query in Java

is it possible to make a system SMS Based Query in Java?because im planning to try and make a System Based on java that has SMS Based query like when you send some sort of code to the system it replies also with a sms
Yes, check out twilio. Pretty great and can set up a cool chat bot type of thing either using some web server or amazon lambda. You can set a script so it will take certain inputs, do whatever code you want and send an output.
// Install the Java helper library from twilio.com/docs/java/install
import com.twilio.Twilio;
import com.twilio.rest.api.v2010.account.Message;
import com.twilio.type.PhoneNumber;
import java.net.URISyntaxException;
public class SmsSender {
// Find your Account Sid and Auth Token at twilio.com/console
public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
public static final String AUTH_TOKEN = "your_auth_token";
public static void main(String[] args) throws URISyntaxException {
Twilio.init(ACCOUNT_SID, AUTH_TOKEN);
Message message = Message
.creator(new PhoneNumber("+14159352345"), // to
new PhoneNumber("+14158141829"), // from
"Where's Wallace?")
.create();
}
}

InetAddress to return the actual Public address of a website from IP

I have been trying several methods in some of the posts to get the actual Public Address from an IP(like facebook.com), but I have not been successful so far. I have been trying the below code to get the web address of facebook :
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Main {
public static void main(String args[]) throws UnknownHostException {
InetAddress addr = InetAddress.getByName("31.13.76.68");
String host = addr.getHostName();
System.out.println(host);
}
}
But what it returns me is this: edge-star-mini-shv-01-sea1.facebook.com. Is this the CNAME that is getting returned? I get the same results with getCanonicalHostName. Some websites even return corp address with gives me no information of the actual public address that IP is associated with. Is there a way to get the actual public address for a given IP? say 31.13.76.68 returns facebook.com, and 74.125.196.100 should return google.com and not yk-in-f100.1e100.net as I am getting in my case.

Basic RMI Example

I am trying out a basic RMI example .But whenever I run the service I get the following error
java.rmi.ConnectException: Connection refused to host: 116.203.202.217; nested exception is:
java.net.ConnectException: Connection timed out: connect
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:601)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:322)
at sun.rmi.registry.RegistryImpl_Stub.bind(Unknown Source)
at java.rmi.Naming.bind(Naming.java:111)
at rmi.remote.RemteImpl.main(RemteImpl.java:29)
Here is the code
package rmi.remote;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class RemteImpl extends UnicastRemoteObject implements RemoteIntf{
protected RemteImpl() throws RemoteException {
super();
// TODO Auto-generated constructor stub
}
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public String sayHello() throws RemoteException {
// TODO Auto-generated method stub
return "hi";
}
public static void main(String a[])
{
try {
RemoteIntf service=new RemteImpl();
Naming.bind("Remote",service);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I am using windows 7 OS
Your bind string is incorrect. It should be "rmi://localhost/Remote". And you should also check your 'hosts' file to make sure it maps "localhost" to 127.0.0.1, and your real hostname to your real host address.
It looks like your RMI registry is not running, which is causing the bind call to fail. You are also not binding to a URL but just to a name.
Usually you'd call bind like so:
Naming.bind("//registryHost:port/remote", service);
where registryHost points at the machine that is running your RMI registry.
For a simple local test you'd make the URL "//localhost:port/remote" and run the rmiregistry service on your local machine.
How to do this is explained for example here:
http://www.javacoffeebreak.com/articles/javarmi/javarmi.html
Excerpt:
To start the registry, Windows users should do the following (assuming that your java\bin directory is in the current path):-
start rmiregistry
To start the registry, Unix users should do the following:-
rmiregistry &
public class RemteImpl extends UnicastRemoteObject implements RemoteIntf{
from RemoteInf is a interface which implements Remote, so, in your main code
RemoteIntf service=new RemteImpl(); //avoid this
//priort to adding this also consider to make sure you have initialized security Manager for allowing connection from or all given IP address.
RemoteImpl service = new RemoteImpl();
should be changed to
RemoteInt service = new RemoteImpl();
where a server object is needed. After that , create a server registry in your code if don't want to use rmiregistry.
LocateRegistry.createRegistry(*port*);
finally, bind the service to a url where a rmi service is provided, using
String url = "rmi://127.0.0.1/RemoteObjectRegisteration" ; //or (your remote ip
address on place of 127.0.0.1)
Naming.bind(url, service);
and the server side should be okay. and You should take some time learning how to ask questions in stack overflow.........

Do I need all classes on the client, server and registry for RMI to work?

I'm doing my first steps with RMI, and I have a simple question.
I have a .jar file which has the implementation of several methods from a library.
I want to call this methods in the .jar file using RMI.
What I'm trying is to create a kind of a wrapper to do it.
So, I'm working on something like this:
Interface class: This interface has the methods to be implemented by the remote object.
Implementation class: This class, has the implementation of the interface methods, each implementation calls the corresponding method in the .jar file. E.g., the jar file has a method called getDetails(), and it returns a "ResponseDetail" object. ResponseDetail is a response class I have in the .jar.
Server class: it binds the methods to the rmiregistry
Client class: it will consume the methods implemented in implementation.
So far so good? :)
Now, I have a lib folder where resides the .jar file.
In the server machine I have deployed the Interface, Implementation and Server classes. I've generated the stub, and I ran the rmiregistry successfully, but, with these details:
To start the rmiregistry, I had to set the classpath in the command line to reference the .jar files, otherwise I get the java.lang.NoClassDefFoundError. I did it with this .sh file:
THE_CLASSPATH=
for i in `ls ./lib/*.jar`
do
THE_CLASSPATH=${THE_CLASSPATH}:${i}
done
rmiregistry -J-classpath -J".:${THE_CLASSPATH}"
To start the server, I had to set the classpath as well to reference the .jar files, otherwise, I get the java.lang.NoClassDefFoundError. I've used something like this:
THE_CLASSPATH=
for i in `ls ./lib/*.jar` do
THE_CLASSPATH=${THE_CLASSPATH}:${i}
done
java -classpath ".:${THE_CLASSPATH}" Server
Client machine:
To run the Client.class file from the client machine, I had to copy the .jar files to it, and make reference to them in the classpath, because otherwise, it does not run and I get the java.lang.NoClassDefFoundError. I had to use this on the client machine:
THE_CLASSPATH=
for i in `ls ./lib/*.jar`
do
THE_CLASSPATH=${THE_CLASSPATH}:${i}
done
java -classpath ".:${THE_CLASSPATH}" HelloClient
Is this ok? I mean, do I have to copy the .jar files to the client machine to execute methods through RMI?
Prior to JDK v5 one had to generate the RMI stubc using the rmic (RMI Compiler). This is done automatically from JDK v5 on. Moreover, you can start the RMI Registry from within the Java code as well. To start with a simple RMI application you may want to follow the following steps:
Create the interface:
import java.rmi.*;
public interface SomeInterface extends Remote {
public String someMethod1() throws RemoteException;
public int someMethod2(float someParameter) throws RemoteException;
public SomeStruct someStructTest(SomeStruct someStruct) throws RemoteException;
}
Implement the interface:
import java.rmi.*;
import java.rmi.server.*;
public class SomeImpl extends UnicastRemoteObject implements SomeInterface {
public SomeImpl() throws RemoteException {
super();
}
public String someMethod1() throws RemoteException {
return "Hello World!";
}
public int someMethod2( float f ) throws RemoteException {
return (int)f + 1;
}
public SomeStruct someStructTest(SomeStruct someStruct) throws RemoteException {
int i = someStruct.getInt();
float f = someStruct.getFloat();
someStruct.setInt(i + 1);
someStruct.setFloat(f + 1.0F);
return someStruct;
}
}
Implement a non-primitive serializable object that is to be passed between a client and the server:
import java.io.*;
public class SomeStruct implements Serializable {
private int i = 0;
private float f = 0.0F;
public SomeStruct(int i, float f) {
this.i = i;
this.f = f;
}
public int getInt() {
return i;
}
public float getFloat() {
return f;
}
public void setInt(int i) {
this.i = i;
}
public void setFloat(float f) {
this.f = f;
}
}
Implement the server:
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.net.*;
import java.io.*;
public class SomeServer {
public static void main(String args[]) {
String portNum = "1234", registryURL;
try{
SomeImpl exportedObj = new SomeImpl();
startRegistry( Integer.parseInt(portNum) );
// register the object under the name "some"
registryURL = "rmi://localhost:" + portNum + "/some";
Naming.rebind(registryURL, exportedObj);
System.out.println("Some Server ready.");
} catch (Exception re) {
System.out.println("Exception in SomeServer.main: " + re);
}
}
// This method starts a RMI registry on the local host, if it
// does not already exist at the specified port number.
private static void startRegistry(int rmiPortNum) throws RemoteException{
try {
Registry registry = LocateRegistry.getRegistry(rmiPortNum);
registry.list( );
// The above call will throw an exception
// if the registry does not already exist
} catch (RemoteException ex) {
// No valid registry at that port.
System.out.println("RMI registry is not located at port " + rmiPortNum);
Registry registry = LocateRegistry.createRegistry(rmiPortNum);
System.out.println("RMI registry created at port " + rmiPortNum);
}
}
}
Implement the client:
import java.io.*;
import java.rmi.*;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
public class SomeClient {
public static void main(String args[]) {
try {
String hostName;
String portNum = "1234";
String registryURL = "rmi://localhost:" + portNum + "/some";
SomeInterface h = (SomeInterface)Naming.lookup(registryURL);
// invoke the remote method(s)
String message = h.someMethod1();
System.out.println(message);
int i = h.someMethod2(12344);
System.out.println(i);
SomeStruct someStructOut = new SomeStruct(10, 100.0F);
SomeStruct someStructIn = new SomeStruct(0, 0.0F);
someStructIn = h.someStructTest(someStructOut);
System.out.println( someStructIn.getInt() );
System.out.println( someStructIn.getFloat() );
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
A larger client-server application should be divided into three modules:client, server, and common (for classes shared between the server and client code, i.e. the remote interface and the non-primitive object in this example). The client application will then be created from client + common modules on the classpath and the server from server + common modules on the classpath.
I used this example many years ago to learn basics of RMI and it still works. However it is far from being perfect (default Java package used, incorrect exception handling, hostname and port parameters are hard-coded and not configurable, etc.)
Nevertheless, it is good for starters. All the files can be placed in one directory and compiled using the simple javac *.java command. The server application can then be started using the java SomeServer and the client one by launching the java SomeClient command.
I hope this helps to understand the Java RMI which is, in fact, far more complicated than just this.
You shouldn't be generating stubs (if you are following a tutorial, it is way old). you can run the client without necessarily having the jars locally (using remote classloading), but it's way easier to do it this with the jars available locally (i've personally done a fair bit of RMI and never actually deployed a system with remote classloading). typically, you want 2 jars, a "client" jar with just the remote interfaces (and any Serializable classes used by those interfaces) and a "server" jar which includes the implementation classes. you would then run the server with the server jar, and the rmiregistry/client with the client jars.
This is a pretty good (up to date and simple) getting started guide.
To say it in short what the other answers elaborated:
The client needs only the common interfaces (and the client classes), not the server implementation.
The server needs interfaces and implementation (and your server main class).
The rmiregistry needs only the interfaces.
(Actually, you can start your own registry inside the server process - then you don't need the rmiregistry at all. Have a look at the createRegistry methods in the java.rmi.registry.LocateRegistry class.)
"Interfaces" here means both the remote interfaces and any (serializable) classes used by these as parameter or argument types.
How you distribute these classes to jar files is independent of this.

Categories