im implementing a java web client which connects to two web services. so basically i have a table listing the status of these two web services. example:
<table>
<tr>
<th>webservice</th>
<th>status</th>
</tr>
<tr>
<td>webservice 1</td>
<td>connected</td>
</tr>
<tr>
<td>webservice 2</td>
<td>connected</td>
</tr>
</table>
my java controller:
class test {
#autowired
private WebServiceTemplate webservice1;
#autowired
private WebServiceTemplate webservice2;
public String mycontroller(...) {
webserviceReq request = new ObjectFactory().createwebserviceReq();
webserviceRes response = new ObjectFactory().createwebserviceRes();
try {
response = (webserviceRes)this.webservice1.marshalSendAndReceive(webserviceReq);
//...set all the data
}
catch(Exception e) {
}
try {
response = (webserviceRes)this.webservice2.marshalSendAndReceive(webserviceReq);
//...set all the data
}
catch(Exception e) {
}
}//end of function
}
if the connection to either webservice fails (mayb the webserivce crash or wat), show the status as disconnected.
currently the problem im facing is if either one connection fail, im getting http status 500, request processing failed.
how can i capture the connection failure for each webservice and print it into the status column?
In each of the catch blocks, extract relevant parts of the Exception in order to determine the specific error. Add them to the returned String.
Things might get easier by not catching Exception, but a subclass that is specifically thrown by your webservices. These might contain the relevant error information.
Related
I am trying implement websockets using spring with a java/web application to allow it to exchangte messages with a application written with c++ using qt (and the websockets library from it).
I have in my java/spring application this configuration:
WebScoketConfig.java
#Configuration
#EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new SocketHandler(), "/name");
}
}
SocketHandler.java
#Component
public class SocketHandler extends TextWebSocketHandler {
List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
#Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws InterruptedException, IOException {
Map<String, String> value = new Gson().fromJson(message.getPayload(), Map.class);
session.sendMessage(new TextMessage("Hello " + value.get("name") + " !"));
}
#Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
sessions.add(session);
}
}
and I created a very simple qt-creator project, with a main function and one class MainWindow, with two objects: a lineEdit, where the user types a message to send to server, and a pushButton, to proceed with the data send.
In my MainWindow class, I implement this slot to handle the data exchange:
void MainWindow::on_pushButton_clicked()
{
QString message = this->ui->lineEdit->text();
QWebSocket m_webSocket;
m_webSocket.open(QUrl(QStringLiteral("ws://localhost:8080/name")));
m_webSocket.sendTextMessage("Hello " + message + " !");
m_webSocket.close();
}
But when I execute both applications, and try send a message for the java/web application, nothing happens. I pretty sure the mistake I made it's on the c++/qt side, since in the java/spring side I have a html/javascript code which allow me testing the message exchage, nd works fine.
Anyone can tell me what I am doing wrong here?
update: minimal reproducible example - java/spring
the project can be generated with start.spring.io, only with spring-websocket as dependency. besides the 2 files I already add above, the project will have:
resources/static/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello WebSocket</title>
<link href="/main.css" rel="stylesheet">
</head>
<body>
<table>
<tr>
<td>
<button id="connect" type="button" onclick="connect();">Connect</button>
<button id="disconnect" type="button" disabled="disabled" onclick="disconnect();">Disconnect</button>
</td>
<td>
<label for="name">What is your name?</label>
<input type="text" id="name" placeholder="Your name here...">
<button id="send" type="button" onclick="send();">Send</button>
</td>
</tr>
</table>
<hr>
<table id="conversation" border="2">
<thead>
<tr>
<th>Greetings</th>
</tr>
</thead>
<tbody id="greetings">
</tbody>
</table>
<script src="/app.js"></script>
</body>
</html>
resources/app.js
var ws;
function connect() {
ws = new WebSocket('ws://localhost:8080/name');
ws.onmessage = function(text) {
var tr = document.createElement("tr");
var td = document.createElement("td");
td.innerText = text.data;
tr.appendChild(td);
document.querySelector("#greetings").appendChild(tr);
}
document.querySelector("#connect").setAttribute("disabled", "disabled");
document.querySelector("#disconnect").removeAttribute("disabled");
document.querySelector("#conversation").style.display = 'block';
document.querySelector("#greetings").innerHTML = "";
}
function disconnect() {
if (ws != null)
ws.close();
document.querySelector("#connect").removeAttribute("disabled");
document.querySelector("#disconnect").setAttribute("disabled", "disabled");
document.querySelector("#conversation").style.display = 'none';
document.querySelector("#greetings").innerHTML = "";
}
function send() {
var name = document.querySelector("#name");
var data = JSON.stringify({'name': name.value});
ws.send(data);
}
after build with mvn package, just run with java -jar target/app.jar.
update: minimal reproducible example - c++/qt
project is created with qt-creator, as type qt-widget. It will create a project with 5 files: websocket.pro, mainwindow.ui, mainwindow.h, mainwindow.cpp and main.cpp.
Open mainwindow.ui and add a lineEdit and pushButton from toolbar. right-click on the pushButton and choose Go to slot and select clicked(). Add the code above.
Update 2
void MainWindow::on_pushButton_clicked()
{
QString message = ui->lineEdit->text();
connect(&m_webSocket, &QWebSocket::connected, [this, message](){
QJsonObject object
{
{"name", message}
};
QJsonDocument d(object);
m_webSocket.sendTextMessage(d.toJson().toStdString().c_str());
m_webSocket.close();
});
m_webSocket.open(QUrl(QStringLiteral("ws://localhost:8080/name")));
}
The problem is that you are trying to send the text without verifying that the connection is successful. The solution is to use the connected signal, in addition to making m_webSocket a member of the class as advised in the comments:
*.h
private:
Ui::MainWindow *ui;
QWebSocket m_webSocket;
*.cpp
void MainWindow::on_pushButton_clicked()
{
QString message = ui->lineEdit->text();
connect(&m_webSocket, &QWebSocket::connected, [this, message](){
m_webSocket.sendTextMessage("Hello " + message + " !");
m_webSocket.close();
});
m_webSocket.open(QUrl(QStringLiteral("ws://localhost:8080/name")));
}
Update:
In your project I have noticed the following errors:
For some reason when I tested using Google Chrome I could not connect so I added registry.addHandler(new SocketHandler(), "/name").setAllowedOrigins("*"); to the configuration.
The variable "session" only handles sending data to a socket, if you want to send that information to all sockets (js and qt) then you must iterate.
When a session is disconnected do not remove it from "sessions" which can cause errors. You must remove session in the afterConnectionClosed method.
In your code you are calling to connect to the server in the slot associated with the connected signal which is silly since that slot is called after the connection and for this you should first call the open method. Anyway opening the connection, waiting for the connection to be established, sending the message and closing the connection is not a good idea, it is better to open the connection before sending the message and close it when necessary (for example when closing the GUI or the user wants to close it as it does in js since the sending of information is not instantaneous but is asynchronous).
The complete code is here.
AdminController.java
#Controller
public class AdminController {
#Autowired
HttpServletRequest request;
#Autowired
AdminDao adminDao;
#RequestMapping("/deletebatch")
public String deletebatch(){
int batchid = Integer.parseInt(request.getParameter("id"));
adminDao.deletebatch(batchid);
return "redirect:/viewbatch";
}
#AdminDaoImpl.java
#Repository("adminDao")
public class AdminDaoImpl implements AdminDao {
#Autowired
SessionFactory sessionFactory;
#Transactional
public void deletebatch(int batchid){
// Batch batch = (Batch) sessionFactory.getCurrentSession().load(Batch.class,batchid);
// if(batch!=null){
sessionFactory.getCurrentSession().delete(batchid);
//}
}
}
#viewbatch.jsp
<form >
<table border="1">
<tr>
<th>BATCH id</th>
<th>BATCH name</th>
<th>edit/delete</th>
</tr>
<c:forEach items="${batchlist}" var="batchlist">
<tr>
<td>${batchlist.batchid}</td>
<td>${batchlist.batchname}</td>
<td>edit/delete</td>
</tr>
</c:forEach>
When i try to delete i got the error :
HTTP Status 500 - Request processing failed; nested exception is
org.hibernate.MappingException: Unknown entity: java.lang.Integer"
and
i try putting the admincontroller as "/delete?id=${batchid}" also.
While i did this i got the problem like can't convert to string
Session.delete(Object); takes the entity you want to delete as parameter, i.e. a Batch object in your example.
In getCurrentSession().delete(batchid); you're passing an Integer - Hibernate tries to delete the Entity Integer from the database but can't find a mapping and therefore throws a MappingException.
The code you commented out in AdminDaoImpl.java is actually what you need to get an entity!
Hibernate Session.delete() an object if exists has examples on how to delete entities in Hibernate. There are also some hints on whether you should use Session.get(Batch.class, batchid) instead of Session.load().
This question is related to this. But since I haven't solved that question yet, I want to restate my problem a bit. I'm using Java Jersey REST API as my backend web service. The client side is a simple web form HTML page. Basically what I want is: If the user submits a web form and there are some errors caused by database unique constraint violation, I want the user to see an error message showing along with the id field in the form such as "ID already exists!". The web form is a simple form.html:
<form action="/myapp/rest/customer/created" method="POST">
<table border="1">
<tr>
<td>Customer name:</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>Customer ID:</td>
<td><input type="text" name="id"></td>
</tr>
<tr>
<td>Customer DOB:</td>
<td><input type="text" name="dob"></td>
</tr>
</table>
<br/>
<input type="submit" value="Submit">
</form>
If there is an error occurred, how to pass the error information from Jersey API to the client-side? My server-side POST call associated with this form submission is as follows:
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Path("created")
public Response createCustomer(#FormParam("id") int id,
#FormParam("name") String name, #FormParam("dob") Date dob)
throws ServletException, IOException {
URI uri = URI.create(uriInfo.getPath());
Response r;
r = Response.created(uri).build();
try {
dbController.create(id, name, dob); //This may throw exception.
} catch (DataAccessException ex) {
//To do: How to pass the error message to the client-side UI via e.g., Ajax?
}
return r;
}
First of all add this somewhere in your code. It will display the error message:
<span id="errorDiv" name="errorDiv" class="errorDiv" ></span>
Next, modify your form declaration as:
<form action="/myapp/rest/customer/created" method="POST" onsubmit="return checkForm()">
Before submitting the form it will call checkForm() function. if the function returns true then it will post the form. if not then it will prevent form from submission and display error message.
Assuming that you are submitting the form contents by using jQuery/AJAX calls. You can return a String(default value = 'success') from the server. In case there is an error change the specific string and return it and check the value client-side.
responseTxt is the value returned.
function checkForm(){
//get values from form
var name= $("#name").val();
var id= $("#id").val();
var dob= $("#dob").val();
$.post('DESTINATION',{name:name,id:id,dob:dob},function(responseTxt) {
//MAKE YOUR CHECK HERE. JUST AN EXAMPLE
if (responseTxt.substring(0,4)=='succ'){
//redirect to destination
return true;
}else{
//display error in errorDiv span
$('#errorDiv').html('<font color=red>Wrong username or password.</font>');
//prevents form to be submitted
return false;
}
});
}
Hope it helps
I'm trying to update a Spring controller to use annotations for a relatively simple 'change password' page. The only fields on the page are 'password' and 'confirm password'. When the form is submitted, it calls to a webservice to do the actual changing of the password. That webservice may return a InvalidPasswordException based upon password rules run within that service. So I want to catch the exception, then add an error message to the view to show up next to the 'password' field. The velocity code is already written using #springShowErrors, so I want to add the error in a way that in can be read in by that tag.
Here is my controller:
#Controller
#RequestMapping("/edit-password.ep")
public class EditPasswordFormControllerImpl {
#Autowired
private CustomerService customerService;
#Autowired
private CustomerSessionService customerSessionService;
#RequestMapping(method = RequestMethod.POST)
protected ModelAndView onSubmit(#ModelAttribute("editPasswordFormBean") EditPasswordFormBeanImpl editPasswordFormBean, BindingResult errors, HttpServletRequest request) throws EpWebException {
String nextView = "redirect:/manage-account.ep";
final CustomerSession customerSession = (CustomerSession) request.getSession().getAttribute(WebConstants.CUSTOMER_SESSION);
final Customer customer = customerSession.getShopper().getCustomer();
try {
CustomerInfo customerInfo = new CustomerInfo();
customerInfo.setCustomerId(customer.getUserId());
customerInfo.setPassword(editPasswordFormBean.getPassword());
UpdateAccountServiceRequest updateRequest = new UpdateAccountServiceRequest();
updateRequest.setClientId(CLIENT_ID);
updateRequest.setCustomerInfo(customerInfo);
//this is the webservice call that could throw InvalidPasswordException
customerService.updateUserAccount(updateRequest);
} catch (InvalidPasswordException e) {
// This is where I'm not sure what to do.
errors.addError(new ObjectError("password", e.getMessage()));
nextView = "edit-password.ep";
} catch (ServiceException e) {
throw new EpWebException("Caught an exception while calling webservice for updating user", e);
}
return new ModelAndView(nextView);
}
#RequestMapping(method = RequestMethod.GET)
protected String setupForm(ModelMap model) {
EditPasswordFormBean editPasswordFormBean = new EditPasswordFormBeanImpl();
model.addAttribute("editPasswordFormBean", editPasswordFormBean);
return "account/edit-password";
}
}
And here is a snippet of my velocity template:
<fieldset>
<legend>#springMessage("editPassword.editPasswordTitle")</legend>
<table border="0" cellspacing="0" cellpadding="3">
<colgroup>
<col width="150">
<col width="*">
</colgroup>
<tr>
<td colspan="2">
<br />
<strong>#springMessage("editPassword.changePassword")</strong>
</td>
</tr>
<tr>
<td align="right">#springMessage("editPassword.password")</td>
<td>
#springFormPasswordInput("editPasswordFormBean.password" "maxlength='100'")
#springShowErrors("<br>" "req")
</td>
</tr>
<tr>
<td align="right">#springMessage("editPassword.confirmPassword")</td>
<td>
#springFormPasswordInput("editPasswordFormBean.confirmPassword" "maxlength='100'")
#springShowErrors("<br>" "req")
</td>
</tr>
</table>
</fieldset>
I'm not quite sure what I should do when I catch the exception. What I currently have doesn't work. It returns to the edit-password page, but no error displays. I've read about HandleExceptionResolver, but even if I use that, I'm still not sure how to get the error to display on the view.
Any help is greatly appreciated!
Jeff, its just a guess, if you see the controller you have the RequestMapping("/edit-password.ep"), so when there is an error scenario your next view is "edit-password.ep", so it will come to this controller and it will be consdiered as a get request to the controller. But in your GET mapping method you are always creating a new EditPasswordBean and sending back to the back. If you run the server in debug mode and keep a break point in setUpForm method you will why the errors have been swallowed. Try to give specific mappings for get and post to avoid such issues. Ideally you should a Validator defined and it should be registered in your initBinder method. Check out this link http://static.springsource.org/spring/docs/current/spring-framework-reference/html/validation.html
Hope it helps.
I am creating a login page for my web application. I want to create a session object whenever
a new user logged in. I know the concept of sessions, but i didnt used that before. Can i do it with a simple class. Or, i have to move to servlet.
If i shall do it with a simple class means, how to create a session object.
This is my scenario...
The HTML CODE:
<table>
<tr>
<td>User Name: </td><td><input id="uName" class="required" type="text"
size="5" /></td>
</tr>
<tr>
<td>Password: </td><td><input id="pwd" class="required" type="text" size="5"
onclick="login()"/></td>
</tr>
</table>
The JS Code:
function login(){
var userDetails = { uName : null, pwd : null };
dwr.util.getValues(userDetails);//Yes, i am using DWR.
LoginAuthentication.doLogin(userDetails, loginResult);
}
function loginResult(nextPage){
window.location.href = nextPage;
}
The Java Code:
public class LoginAuthentication
{
public String doLogin(User user) throws SQLException, ClassNotFoundException{
String userName = user.getUserName();
boolean loginResult = verifyUser(user);//Another method that verifies user details with the DB.
if (loginResult == true){
/* Here I have to create session object,
and i want to add the current username in that object. How to do it.*/
return "MainPage.html";
}
else{
return "loginRetryPage.html";
}
}
The concept that was given to me about session is pretty simple and clear. I have to create a session object after a valid user input & add the user name to that object, Destroy the object when logout was clicked. But i didnt worked on sessions before. I mean, i dont know the syntax to create a session variable.
How shall i create a session Object here?
Any suggestions would be more appreciative!!!
Thanks in Advance!!!
In a servlet a session is obtained with the following line:
Session session = request.getSession();
And to get the request object with DWR, you do (see here):
WebContext ctx = WebContextFactory.get();
HttpServletRequest request = ctx.getHttpServletRequest();
(The HttpServletRequest contains all data about the HTTP request that has been sent by the browser to the server)
It is better to always use request.getSession(false); after successful login.