Issue
I had created REST API on Spring Boot for my Android application, when I try to hit the API it works well in Postman but not in my application kindly help me out by looking to my code I shall be very thankful to the community members.
@RestController
@RequestMapping(value = USER_URL)
public class UserController {
private final UserService userService;
//email service
@Autowired
private EmailServiceImpl emailServiceImpl;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping(value = LOGIN, consumes = MediaType.ALL_VALUE)
public ResponseEntity<Object> authenticateUser(@RequestParam(EMAIL) String email,
@RequestParam(PASSWORD) String password) {
if (userService.authenticateUser(email, password).size() > 0) {
//generating auth token
String token;
try {
token = MD5.getMD5Hex(email + DateTime.getCurrentTime(Constants.DATETIME.formatyyyyMMddHHmmss));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return ResponseHandler.negativeResponse(
HttpStatus.INTERNAL_SERVER_ERROR,
HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(),
"error generating auth token");
}
//adding authToken to users Entity
userService.updateUserAuthToken(email, token);
//sending response
return ResponseHandler.positiveResponse(
HttpStatus.OK,
HttpStatus.OK.getReasonPhrase(),
SUCCESS,
userService.authenticateUser(email, password).iterator().next(),
USER);
} else
return ResponseHandler.negativeResponse(
HttpStatus.NOT_FOUND,
HttpStatus.NOT_FOUND.getReasonPhrase(),
EMAIL_PASS_NOT_MATCH);
}
SPRING pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.spring-app</groupId>
<artifactId>spring-app</artifactId>
<version>0.2.5</version>
<packaging>jar</packaging>
<name>spring-app</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>groupid</groupId>
<artifactId>artifiactId</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-XDignore.symbol.file</arg>
<arg>-parameters</arg>
</compilerArgs>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
ANDROID Model User.java
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class User {
@SerializedName("id")
@Expose
private int id;
@SerializedName("full_name")
@Expose
private String fullName;
@SerializedName("email")
@Expose
private String email;
@SerializedName("phone")
@Expose
private String phone;
@SerializedName("role")
@Expose
private String role;
@SerializedName("created_at")
@Expose
private String createdAt;
@SerializedName("auth_token")
@Expose
private String authToken;
@SerializedName("password")
@Expose
private String password;
@SerializedName("image")
@Expose
private String image;
public User(Integer id, String fullName, String email, String phone, String role, String createdAt, String authToken, String password, String image) {
this.id = id;
this.fullName = fullName;
this.email = email;
this.phone = phone;
this.role = role;
this.createdAt = createdAt;
this.authToken = authToken;
this.password = password;
this.image = image;
}
public User(int id, String fullName, String email, String phone, String role, String createdAt, String authToken, String image) {
this.id = id;
this.fullName = fullName;
this.email = email;
this.phone = phone;
this.role = role;
this.createdAt = createdAt;
this.authToken = authToken;
this.image = image;
}
public User() {
}
public int getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public String getAuthToken() {
return authToken;
}
public void setAuthToken(String authToken) {
this.authToken = authToken;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", fullName='" + fullName + '\'' +
", email='" + email + '\'' +
", phone='" + phone + '\'' +
", role='" + role + '\'' +
", createdAt='" + createdAt + '\'' +
", authToken='" + authToken + '\'' +
", password='" + password + '\'' +
", image='" + image + '\'' +
'}';
}
}
ANDROID Model GenericResponse.java
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class GenericResponse {
@SerializedName("error")
@Expose
private String error;
@SerializedName("message")
@Expose
private String message;
@SerializedName("user")
@Expose
private User user;
@SerializedName("timestamp")
@Expose
private String timestamp;
@SerializedName("status")
@Expose
private int status;
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public int getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
}
ANDROID RestApiInterface.java
public interface RestApiInterface {
//login
@Multipart
@POST(USER_URL + LOGIN)
Call<GenericResponse> signInRequest(@Part("email") RequestBody email,
@Part("password") RequestBody password);
}
ANDROID RestApiManager.java
public class RestApiManager {
public static Retrofit retrofit = null;
//
public static Retrofit getClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
private static OkHttpClient getClientt() {
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.MINUTES)
.readTimeout(5, TimeUnit.MINUTES)
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header(AUTH_KEY_ATTRIBUTE, AUTH_KEY_VALUE)
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
})
.build();
return client;
}
}
ANDROID Method SendSignInRequestToServer()
/*Network Calls for sign in*/
public void sendSignInRequestToServer(String email, String password) {
RestApiInterface restService = RestApiManager.getClient().create(RestApiInterface.class);
RequestBody email_ = RequestBody.create(MediaType.parse("text/plain"), email);
RequestBody password_ = RequestBody.create(MediaType.parse("text/plain"), password);
Call<GenericResponse> connection = restService.signInRequest(email_, password_);
connection.enqueue(new Callback<GenericResponse>() {
@Override
public void onResponse(Call<GenericResponse> call, retrofit2.Response<GenericResponse> response) {
progressDialog.dismiss();
if (response.body() != null) {
if (response.body().getStatus() == 200) {
((AuthenticationActivity) getActivity()).goToHomeActivity();
} else {
new CustomToast().Show_Toast(getActivity(), mainView, response.body().getMessage());
ll_signIn.startAnimation(shakeAnimation);
}
}
}
@Override
public void onFailure(Call<GenericResponse> call, Throwable t) {
if (t instanceof IOException) {
Toast.makeText(getActivity(), "this is an actual network failure :( inform the user and possibly retry", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(getActivity(), "conversion issue! big problems :(", Toast.LENGTH_SHORT).show();
// todo log to some central bug tracking service
}
}
});
}
POSTMAN response
{
"error": "OK",
"message": "success",
"user": {
"role": "admin",
"image": "",
"email": "[email protected]",
"phone": "11223344",
"created_at": "23:40:49",
"full_name": "sultan",
"auth_token": "c7cec6c452f645af1e3a7368aee1b364",
"id": 4
},
"timestamp": "2020-06-04T03:28:59.710+0000",
"status": 200
}
ERROR on application side It always hit onFailure I don't know what I'm doing wrong kindly help me out thanks
Solution
I had found that on android x you need to define network security configuration for this, you need to create an XML file in res->xml->network-security-config.xml here and mention this in your manifest
android:networkSecurityConfig="@xml/network-security-config"
network-security-config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">EXAMPLE.COM/API etc</domain>
</domain-config>
</network-security-config>
Answered By - Suul
Answer Checked By - Timothy Miller (JavaFixing Admin)