best approach to have multiple object as a service result - java

I have a java service that sends a JSON as a result.
my service depends on some condition creat a conversationVO object and converts it to JSON and in the other condition create a participantVO object and convert it to JSON and finally, it sends/returns the JSON object as a result.
the question is that is it rational that my service sends different objects as a result? is this approach correct? or it's better that I create another VO, for example, resultVO object that has 2 fields of conversationVO and participantVO and it the conditions I fill one of 2 fields and finally send the JSON of new resultVO?
you can find codes below.
public static void getThreadInfo(User currentUser, String uniqueName, long senderPeerId, String contactType, String uniqueId) {
try (HibernateSession session = SessionManager.openSession()) {
if (uniqueName == null || uniqueName.isEmpty()) {
throw new ChatException(ChatException.UNIQUE_NAME_IS_NEEDED, "UNIQUE_NAME_IS_NEEDED. " + uniqueId);
}
User participant = UserCRUD.getUserByUsername(uniqueName, session);
if (participant != null && participant.isActive()) {
sendParticipantThreadInfo(currentUser, participant, senderPeerId, uniqueId);
} else {
sendThreadInfo(currentUser,uniqueName, contactType, senderPeerId, uniqueId, session);
}
} catch (Throwable e) {
logger.warn("An exception occured", e);
ControllerHelper.sendError(
uniqueId,
new Long[]{senderPeerId},
e);
}
}
private static void sendParticipantThreadInfo(User currentUser, User participant, long senderPeerId, String uniqueId) {
ParticipantVO participantVO = ServiceHelper.fillParticipantSummary(participant);
ChatMessage chatMessage = new ChatMessage();
chatMessage.setType(ChatMessage.GET_THEAD_INFO);
chatMessage.setContent(JsonUtil.getJson(participantVO));
chatMessage.setUniqueId(uniqueId);
chatMessage.setSubjectId(participant.getId());
ControllerHelper.sendMessage(
new ResultVO(
chatMessage,
Collections.singletonList(senderPeerId),
null,
true,
ChatSettings.MESSAGE_NORMAL_PRIORITY,
currentUser
)
);
}
private static void sendThreadInfo(User currentUser,
String uniqueName,
String contactType,
long senderPeerId,
String uniqueId,
HibernateSession session) {
try {
MessageThread messageThread = getThreadByUniqueName(uniqueName, contactType, session);
if (messageThread == null) {
throw new ChatException(ChatException.USER_NOT_FOUND, "User or thread not found! " + uniqueId);
}
ConversationVO conversationVO = ServiceHelper.fillConversation(messageThread,
null,
true,
false,
contactType, session);
ChatMessage chatMessage = new ChatMessage();
chatMessage.setSubjectId(messageThread.getId());
chatMessage.setContent(JsonUtil.getJson(conversationVO));
chatMessage.setType(ChatMessage.GET_THEAD_INFO);
chatMessage.setUniqueId(uniqueId);
ControllerHelper.sendMessage(
new ResultVO(
chatMessage,
Collections.singletonList(senderPeerId),
null,
true,
ChatSettings.MESSAGE_NORMAL_PRIORITY,
currentUser
)
);
} catch (Throwable e) {
logger.warn("An exception occured", e);
ControllerHelper.sendError(
uniqueId,
new Long[]{senderPeerId},
e);
}
}

NewResultVO<T>{
private String code;
private T data; // T is your ResultVO or other VO.
}
Client get code "0000000" to do ...
Client get code "9999999" to do ...

Better Approach is send data in a single result like below format.
JSON Result
{
"ChatId": 1,
"Description": "test",
"conversation": [
{
"conversationId":1,
"conversationType":"content"
},
{
"conversationId":2,
"conversationType":"content"
}
],
"participant": [
{
"participantId":1,
"participantName":"Name1"
},
{
"conversationId":2,
"participantName":"Name2"
}
]
}

Related

How to authenticate Springboot API based on User role that is being fetched from DB

I have user role saved in DB, so based on role ID authentication has to be done for each API.
I tried few approaches but did not succeed.
Code Snippet:
CONTROLLER:
#PreAuthorize("#AuthService.getUserRole(1)")
#PostMapping(name = "POST - Save the user info to Automation Counter table", path = "userlogininfo")
#Operation(summary = "Save the user info to Automation Counter table")
public ResponseEntity<ApiResponse> saveUserInfoinDB(#RequestBody SaveUserInfo saveUserInfoDetails, Principal principal)
{
try
{
saveUserInfoDetails.ntid = principal.getName().split("\\n")[0];
if (saveUserInfoDetails.firstName != null && saveUserInfoDetails.lastName != null && saveUserInfoDetails.ntid != null && saveUserInfoDetails.applicationName !=null)
{
ApiResponse apiResponse = restService.osmAPIPost("/dashboard/userlogininfo",saveUserInfoDetails);
return ResponseEntity.ok(apiResponse);
}
else
{
ApiResponse response = new ApiResponse<>(false, "Did not receive data in correct format", null);
return ResponseEntity.badRequest().body(response);
}
}
catch (Exception ex)
{
String logMessage = SharedUtils.logErrorMessage(this.getClass().getSimpleName(), ex, "Error while saving user info in DB.");
ApiResponse response = new ApiResponse<>(false, logMessage, null);
return ResponseEntity.badRequest().body(response);
}
}
SERVICE:
#Service
public class AuthService {
private final AuthRepository authRepository;
public AuthService(AuthRepository authRepository)
{
this.authRepository = authRepository;
}
public boolean getUserRole(int roleId)
{
try
{
boolean userRole=authRepository.getUserLoginInfo(Principal.class.getName().split("\\n")[0],roleId);
return userRole;
}
catch (Exception ex)
{
throw ex;
}
}
}
REPOSITORY:
#Transactional
public boolean getUserLoginInfo(String ntid, int roleId )
{
try
{
String returnValue=null;
String sql = "SELECT Alias FROM Users where NTID=? AND RoleId=?" ;
returnValue= osmv2JdbcTemplate.queryForObject(sql,String.class,ntid,roleId);
if(returnValue!=null)
{
return true;
}
else
{
return false;
}
}
catch(Exception ex)
{
String logMessage = SharedUtils.logErrorMessage(this.getClass().getSimpleName(), ex, "Could not fetch the User alias based on role ID and NTID from DB");
LOGGER.info(logMessage);
return false;
}
}
I have created custom method that will be used in #PreAuthorize but it did not work. The method is fetching the role id from DB based on username.Please help.. Thanks in advance:)

IllegalStateException while reading response

I am reading JAVAX response using readEntity() method but I am getting following stacktrace :
java.lang.IllegalStateException: Entity input stream has already been closed.
at org.glassfish.jersey.message.internal.EntityInputStream.ensureNotClosed(EntityInputStream.java:225) ~[jersey-common.jar:?]
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:832) ~[jersey-common.jar:?]
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:785) ~[jersey-common.jar:?]
at the line
Map<String, Map> mapEntityFromResponse = res.readEntity(Map.class);
Here is my code
public Output getClaimsFromAPI(#NonNull final Input xyzInput)
throws PermanentException, TransientException {
final Response res = fetchHealBeamServiceResponse(webTarget, xyzInput);
Object respondentMapObject;
Map<String, Map> mapEntityFromResponse = res.readEntity(Map.class);
if (mapEntityFromResponse != null) {
respondentMapObject = mapEntityFromResponse.get(ServiceConstants.MAP_KEY);
return getOutputFromResponseMap(respondentMapObject, xyzInput);
} else {
throw new RuntimeException("The response returned does not contain map");
}
}
private Response fetchHealBeamServiceResponse(WebTarget healBeamTarget,
Input xyzInput)
throws PermanentException, TransientException {
Response res = null;
try {
res = healBeamTarget
.path(HealBeamServiceConstants.GET_CUSTOMER_PATH)
.register(Configurator.getSoaOpNameFeatureForCustomerResource())
.resolveTemplate(ServiceConstants.ID, xyzInput.getId())
.request(MediaType.APPLICATION_JSON_TYPE)
.property(HealBeamServiceConstants.SERVICE_KEY, SOA_SERVICE_NAME)
.property(HealBeamServiceConstants.OPERATION_KEY, SOA_OP_NAME_GET_CUSTOMER)
.acceptLanguage(java.util.Locale.getDefault())
.get();
if (Response.Status.REQUEST_TIMEOUT.getStatusCode() == res.getStatusInfo().getStatusCode()) {
throw new TransientException("Request timed out with status" + res.getStatusInfo().getStatusCode());
} else if (Response.Status.OK.getStatusCode() != res.getStatusInfo().getStatusCode()) {
log.error("Some Error"):
}
return res;
} catch (RuntimeException e) {
throw new PermanentException("Unexpected Exception Occured, Exception Message " + e.getMessage());
} finally {
if (res != null) {
res.close();
}
}
}
You are closing your response in finally right before it gets returned, that is the reason, why you can't read from it in your calling method getClaimsFromAPI().
Just to demonstrate: What do you think the method main() posted below would print?
public class NewApp {
public static void main(String[] args) {
Person p = demonstrate();
System.out.println(p.name);
}
public static Person demonstrate(){
Person person = new Person();
try {
person.name = "name set in try";
return person;
} catch (Exception ex) {
throw ex;
} finally {
person.name = "name set in finally";
}
}
}
class Person {
public String name;
}

Get User online/offline state

I have chat app where i need to develop user online state and for this i am calling API in every 15 seconds on server, which will return all logged in users and their online state in 0(Offline) and 1(Online).
I need to show whether user is online or offline (leaves app not logged out) while chatting.I have 1 array list which shows when app is launch with all logged in user id and their details including their online state and i created second API which return users online state in JSON.I have following option to achieve users online state
Replace existing array list item:-I am getting User ID and their online state in JSON but i need to run loop in every 15 second which replace values in existing arraylist
Store JSON in someway where i can easily find user id and its state:- If i store JSON in array list i need to run loop to find ID and its state which i dont want to,So which is best way to store JSON so i can easily get user state by its User ID.
Here is how i am getting JSON
protected List<WrapperClass> doInBackground(Void... params) {
userSession=new UserSession(context,"Elaxer");
UserState_Update=new ArrayList<>();
String data = null;
try {
String ID=userSession.getUserID(); //Getting Value from shared pref
data = URLEncoder.encode("User_ID", "UTF-8") + "=" + URLEncoder.encode(ID, "UTF-8");
Log.d(TAG,"Login ID "+ ID);
Log.d(TAG,"DO IN BACKGROUND START ");
URL url=new URL(URL_Path_NearBy);
connection= (HttpURLConnection) url.openConnection();
Log.d(TAG,connection.toString());
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
//For POST Only - Begin
OutputStream os = connection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write(data);
writer.flush();
writer.close();
os.close();
connection.connect();
InputStream inputStream=connection.getInputStream();
reader=new BufferedReader(new InputStreamReader(inputStream));
Log.d(TAG,"GET INPUT STREAM AND PUUTING INTO READER");
String line;
StringBuffer stringBuffer=new StringBuffer();
while ((line=reader.readLine())!=null){
stringBuffer.append(line);
}
String completeJSON=stringBuffer.toString();
Log.d(TAG,"JSON ARRAY START");
JSONObject parentArray=new JSONObject(completeJSON);
JSONArray jsonArray=parentArray.getJSONArray("uData");
String LastSeen;
int LoginStatus,User_ID;
int Rec_Online_Status;
for (int i = 0; i <jsonArray.length() ; i++) {
JSONObject childObject=jsonArray.getJSONObject(i);
LastSeen=childObject.getString("lastseen") ;
LoginStatus=childObject.getInt("login_status") ;
User_ID=childObject.getInt("User_ID");
String UseID= String.valueOf(User_ID);
Log.d(TAG,"JSON Values "+LastSeen+" "+LoginStatus+" "+User_ID);
WrapperClass wrapperClass=new WrapperClass(UseID,LoginStatus);
UserState_Update.add(wrapperClass);
}
return UserState_Update; //List<WrapperClass> UserState_Update
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
This is the response as JSON
{
"status": "SUCCESS",
"uData": [
{
"User_ID": "4",
"login_status": "1",
"lastseen": "0000-00-00 00:00:00"
},
{
"User_ID": "1",
"login_status": "0",
"lastseen": "0000-00-00 00:00:00"
},
{
"User_ID": "12",
"login_status": "1",
"lastseen": "0000-00-00 00:00:00"
},
{
"User_ID": "33",
"login_status": "0",
"lastseen": "0000-00-00 00:00:00"
}
]
}
Is this right way to get user online state? (I know FCM is right way but FCM currently not ready on app server side)
UPDATE 2:-As code recommended by #XngPro i implement on doinBackground
Map<String,Online_Status_Wrapper.User> map=new HashMap<>();
Online_Status_Wrapper wrapper=gson.fromJson(completeJSON,Online_Status_Wrapper.class);
Log.d(TAG,"Wrapper Get Data value "+wrapper.getuData());
Log.d(TAG,"Wrapper Get Status value "+wrapper.getStatus());
for (Online_Status_Wrapper.User u: wrapper.getuData()){
map.put(u.getUser_ID(),u);
}
Log.d(TAG,"State of Other User users "+map.get(12).getLogin_status());//HERE I AM GETTING NullPointerException
return map;
I think you should use a Java serialization/deserialization library like Gson.
Hope to help you~
Example
private static void bar() {
String jsonStr = "{\"status\":\"SUCCESS\",\"uData\":[{\"User_ID\":\"4\",\"login_status\":\"1\",\"lastseen\":\"0000-00-00 00:00:00\"},{\"User_ID\":\"1\",\"login_status\":\"0\",\"lastseen\":\"0000-00-00 00:00:00\"},{\"User_ID\":\"12\",\"login_status\":\"1\",\"lastseen\":\"0000-00-00 00:00:00\"},{\"User_ID\":\"33\",\"login_status\":\"0\",\"lastseen\":\"0000-00-00 00:00:00\"}]}";
Gson gson = new Gson();
UserFoo userFoo = gson.fromJson(jsonStr, UserFoo.class);
Map<String, UserFoo.User> map = new HashMap<>();
for (UserFoo.User u : userFoo.getUData()) {
map.put(u.getUser_ID(), u);
}
System.out.println("userId: 12, loginState: " + map.get("12").getLogin_status());
}
public static class UserFoo {
/**
* status : SUCCESS
* uData : [{"User_ID":"4","login_status":"1","lastseen":"0000-00-00 00:00:00"},{"User_ID":"1","login_status":"0","lastseen":"0000-00-00 00:00:00"},{"User_ID":"12","login_status":"1","lastseen":"0000-00-00 00:00:00"},{"User_ID":"33","login_status":"0","lastseen":"0000-00-00 00:00:00"}]
*/
private String status;
private List<User> uData;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public List<User> getUData() {
return uData;
}
public void setUData(List<User> uData) {
this.uData = uData;
}
public static class User {
/**
* User_ID : 4
* login_status : 1
* lastseen : 0000-00-00 00:00:00
*/
private String User_ID;
private String login_status;
private String lastseen;
public String getUser_ID() {
return User_ID;
}
public void setUser_ID(String User_ID) {
this.User_ID = User_ID;
}
public String getLogin_status() {
return login_status;
}
public void setLogin_status(String login_status) {
this.login_status = login_status;
}
public String getLastseen() {
return lastseen;
}
public void setLastseen(String lastseen) {
this.lastseen = lastseen;
}
}
}
public class Test {
public static void main(String[] args) {
bar();
}
private static void bar() {
String jsonStr = "{\"status\":\"SUCCESS\",\"uData\":[{\"User_ID\":\"4\",\"login_status\":\"1\",\"lastseen\":\"0000-00-00 00:00:00\"},{\"User_ID\":\"1\",\"login_status\":\"0\",\"lastseen\":\"0000-00-00 00:00:00\"},{\"User_ID\":\"12\",\"login_status\":\"1\",\"lastseen\":\"0000-00-00 00:00:00\"},{\"User_ID\":\"33\",\"login_status\":\"0\",\"lastseen\":\"0000-00-00 00:00:00\"}]}";
Gson gson = new Gson();
UserFoo userFoo = gson.fromJson(jsonStr, UserFoo.class);
Map<String, UserFoo.User> map = new HashMap<>();
for (UserFoo.User u : userFoo.getUData()) {
map.put(u.getUser_ID(), u);
}
System.out.println("userId: " + "12, loginState: " + map.get("12").getLogin_status());
}
public static class UserFoo {
/**
* status : SUCCESS
* uData : [{"User_ID":"4","login_status":"1","lastseen":"0000-00-00 00:00:00"},{"User_ID":"1","login_status":"0","lastseen":"0000-00-00 00:00:00"},{"User_ID":"12","login_status":"1","lastseen":"0000-00-00 00:00:00"},{"User_ID":"33","login_status":"0","lastseen":"0000-00-00 00:00:00"}]
*/
private String status;
private List<User> uData;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public List<User> getUData() {
return uData;
}
public void setUData(List<User> uData) {
this.uData = uData;
}
public static class User {
/**
* User_ID : 4
* login_status : 1
* lastseen : 0000-00-00 00:00:00
*/
private String User_ID;
private String login_status;
private String lastseen;
public String getUser_ID() {
return User_ID;
}
public void setUser_ID(String User_ID) {
this.User_ID = User_ID;
}
public String getLogin_status() {
return login_status;
}
public void setLogin_status(String login_status) {
this.login_status = login_status;
}
public String getLastseen() {
return lastseen;
}
public void setLastseen(String lastseen) {
this.lastseen = lastseen;
}
}
}
}
Print

jsonrpc4j: how to get List<SomeObject> from server?

I'm trying to get a list of objects AccountData from my JSON-RPC server using jsonrpc4j.
Here is code:
class AccountData {
public Integer id;
public Double accDeposit;
public Double accCredit;
public String accPerson;
public String accAddressCity;
public String accAddressStreet;
public String accAddressBuild;
public String accAddressApt;
public Date accRegDate;
public String accPersonPassport;
public String accPersonPhone;
public String accPersonEmail;
public String accComments;
public String accLogin;
public String accPassword;
}
public void initialize() {
try {
JsonRpcHttpClient client = new JsonRpcHttpClient(new URL("http://localhost:8032/api"));
try {
List<AccountData> accountData = Arrays.asList(client.invoke("getUserAccount", new Object[]{}, AccountData.class));
System.out.println("Method invoked");
if (accountData != null) {
for (AccountData data : accountData) {
System.out.println("login=" + data.accLogin);
}
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
And I'm getting an exception:
> com.googlecode.jsonrpc4j.HttpException: null
com.googlecode.jsonrpc4j.JsonRpcHttpClient.invoke(JsonRpcHttpClient.java:166)
com.googlecode.jsonrpc4j.JsonRpcHttpClient.invoke(JsonRpcHttpClient.java:121)
com.googlecode.jsonrpc4j.JsonRpcHttpClient.invoke(JsonRpcHttpClient.java:132)
My JSON-RPC server returns result correctly, I've tested in python/php clients. Single results (non-array) works correctly too in Java.
The JSON you posted is not valid. Try it at http://jsonlint.com/
You should use double quotes instead of single quotes and also None should be in double quotes too:
{
"id": 0,
"result": [{
"accDeposit": 100.0,
"accComments": "test account",
"accPersonPassport": "FR8382",
"accAddressStreet": "None",
"accPersonEmail": "john#johndoe.john",
"accPassword": "test",
"accPersonPhone": "+70717654321",
"id": 8,
"accPerson": "John Doe",
"accAddressCity": "test city",
"accRegDate": "2016-07-11",
"accLogin": "john",
"accCredit": 0.0,
"accAddressBuild": "1",
"accAddressApt": "18"
}],
"jsonrpc": "2.0"
}
Use AccountData[].class
`
try {
JsonRpcHttpClient client = new JsonRpcHttpClient(new URL("http://localhost:8032/api"));
try {
List<AccountData> accountData = Arrays.asList(client.invoke(
"getUserAccount",
new Object[]{},
AccountData[].class
));
System.out.println("Method invoked");
if (accountData != null) {
for (AccountData data : accountData) {
System.out.println("login=" + data.accLogin);
}
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
`

How to implement servlet response.redirect in jersey?

While i am try to implement response.redirect in jersey by using Response.temporaryRedirect(location) and Response.seeOther(location), But both are not working as like Servlet response.sendRedirect.
As i tried,
Java script :-
function loginFunction(){
var password=$("#password").val();
var username=$("#emailId").val();
function make_base_auth(user, password) {
var tok = user + ':' + password;
var hash = btoa(tok);
return "Basic " + hash;
}
$.ajax({
url:'/test/login/filter',
type:'GET',
crossDomain: true,
beforeSend : function(req) {
req.setRequestHeader('Authorization', make_base_auth(username, password));
},
success:function(res,status,xhr){
userToken=xhr.getResponseHeader("Authorization");
localStorage.setItem("userToken", userToken);
if(userToken != undefined || userToken != null){
window.location.href = "./index.html";
}else{
$('.errmsg').html('please provide a valid credentials.')
$(this).load();
}
},
error : function(jqXHR, textStatus, errorThrown) {
console.log("textStatus is:"+textStatus);
}
});
}
Jersey Code:-
#Path("/login")
public class UserLogin {
private static Map<String ,Token> tokTable=new HashMap<String ,Token>();
#GET
#Path("/filter")
public void filter(#Context ContainerRequestContext context){
String authentication = filterContext.getHeaderString(HttpHeaders.AUTHORIZATION);
if (authentication == null) {
throw new AuthenticationException("Authentication credentials are required");
}
if (!authentication.startsWith("Basic ")) {
return null;
}
authentication = authentication.substring("Basic ".length());
String[] values = new String(DatatypeConverter.parseBase64Binary(authentication), Charset.forName("ASCII")).split(":");
String username=null,givenPass=null;
try{
username = values[0];
givenPass=org.glassfish.jersey.internal.util.Base64.encodeAsString( values[1]);
}catch(Exception e){
throw new AuthenticationException("User name and password can't be empty\r\n");
}
}
User user = AuthLookUpTables.userTable.get(username);
// Validate the extracted credentials
if ( user == null ) {
logger.info("USER NOT AUTHENTICATED");
throw new AuthenticationException("Invalid username");
}
String password=org.glassfish.jersey.internal.util.Base64.encodeAsString(givenPass.concat(user.getSalt()));
if ((username == null) || (password == null)) {
throw new WebApplicationException(400);
}
String dbPass=org.glassfish.jersey.internal.util.Base64.encodeAsString(user.getHashedPassword().concat(user.getSalt()));
if ( dbPass.equals(password) ) {
logger.info("USER AUTHENTICATED");
//SOme code using for main sever.
} else {
logger.info("USER NOT AUTHENTICATED");
throw new AuthenticationException("Invalid username or password\r\n");
}
return user;
}
POJO (USER):-
public class User {
public String username;
public String roles;
public String salt;
public String hashedPassword;
//and below getter and setter methods
}
Custom Exception:-
public class AuthenticationException extends RuntimeException {
public AuthenticationException() {
super();
}
public AuthenticationException(String message) {
super(message);
}
}
Exception Mapper:-
#Provider
public class AuthenticationExceptionMapper implements ExceptionMapper<AuthenticationException> {
private Logger logger=Logger.getLogger(AuthenticationExceptionMapper.class);
#Context
UriInfo uriInfo;
public Response toResponse(AuthenticationException e) {
UriBuilder builder=null;
if (e.getMessage() != null) {
builder=UriBuilder.fromPath(uriInfo.getBaseUriBuilder().toString()).path("..");
return Response.temporaryRedirect(builder.build()).build();
} else {
return Response
.status(Status.UNAUTHORIZED)
.type("text/plain")
.entity(e.getMessage())
.build();
}
}
}
this is what i get in developer tool,
But, i am expecting server redirect to login page, how do i do that, kindly same one help me to do this.
thank you

Categories