I am streaming the audio from microphone using javascript and sending the audio stream from frontend to backend via websocket. In my websocket handle message i can see float array recieving from front end but as soon as i write the float array to a file it does contatin any audio. here is link of generated audio file.
#Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
// TODO Auto-generated method stub
byte [] bb =getByteArrayFromByteBuffer((ByteBuffer)message.getPayload());
System.out.println(Arrays.toString(bb));
FileUtils.writeByteArrayToFile(file,bb,true);
}
private static byte[] getByteArrayFromByteBuffer(ByteBuffer byteBuffer) {
byte[] bytesArray = new byte[byteBuffer.remaining()];
byteBuffer.get(bytesArray, 0, bytesArray.length);
return bytesArray;
}
below is javascript streaming code:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<button onclick="stop()">stop</button>
<script>
const AudioContext = window.AudioContext// Safari and old versions of Chrome
var context;
var source;
var bufferDetectorNode ;
jssocket= new WebSocket("ws://localhost:8080/websocket/name?user_id="+ generateRandomInteger(0, 3));
jssocket.onopen = function(e) {
console.log("[open] Connection established");
};
jssocket.onmessage = function(event) {
console.log(`[message] Data received from server: ${event.data}`);
};
jssocket.onclose = function(event) {
if (event.wasClean) {
console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
// e.g. server process killed or network down
// event.code is usually 1006 in this case
console.log('[close] Connection died');
}
};
jssocket.onerror = function(error) {
console.log(`[error] ${error.message}`);
};
try {
navigator.getUserMedia = navigator.getUserMedia
|| navigator.webkitGetUserMedia
|| navigator.mozGetUserMedia;
microphone = navigator.getUserMedia({
audio : true,
video : false
}, onMicrophoneGranted, onMicrophoneDenied);
} catch (e) {
alert(e)
}
async function onMicrophoneGranted(stream) {
console.log(stream)
context = new AudioContext();
source = context.createMediaStreamSource(stream);
await context.audioWorklet.addModule('/assets/js/buffer-detector.js');
// Create our custom node.
bufferDetectorNode= new AudioWorkletNode(context, 'buffer-detector');
bufferDetectorNode.port.onmessage = (event) => {
// Handling data from the processor.
jssocket.send(event.data)
// const byteArr = Int8Array.from(event.data)
//const original = Array.from(byteArr)
// console.log(original);
// jssocket.send( Buffer.from(byteArr, 'base64').toString('utf8'));
};
source.connect(bufferDetectorNode);
bufferDetectorNode.connect(context.destination);
//source.connect(context.destination);
}
function _base64ToArrayBuffer(base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
function onMicrophoneDenied() {
console.log('denied')
}
function stop(){
bufferDetectorNode.disconnect(context.destination)
source.disconnect(bufferDetectorNode)
}
function generateRandomInteger(min, max) {
return Math.floor(min + Math.random() * (max - min + 1))
}
</script>
</body>
</html>
AudioWorklet
class BufferProcessor extends AudioWorkletProcessor {
bufferSize = 256
_bytesWritten = 0
// 2. Create a buffer of fixed size
_buffer = new Float32Array(this.bufferSize)
initBuffer() {
this._bytesWritten = 0
}
isBufferEmpty() {
return this._bytesWritten === 0
}
isBufferFull() {
return this._bytesWritten === this.bufferSize
}
process (inputs) {
this.append(inputs[0][0])
return true;
}
append(channelData) {
if (this.isBufferFull()) {
this.flush()
}
if (!channelData) return
for (let i = 0; i < channelData.length; i++) {
this._buffer[this._bytesWritten++] = channelData[i]
}
}
flush() {
// trim the buffer if ended prematurely
this.port.postMessage(
this._bytesWritten < this.bufferSize
? this._buffer.slice(0, this._bytesWritten)
: this._buffer
)
this.initBuffer()
}
static get parameterDescriptors() {
return [{
name: 'Buffer Detector',
}]
}
constructor() {
super();
this._socket = null;
this._isRecording = true;
this.initBuffer()
}
get socket() {
return this._socket;
}
set socket(value) {
if (value instanceof WebSocket) {
this._socket = value;
}
}
get recording() {
return this._isRecording;
}
set recording(value) {
if ('boolean' === typeof value) {
this._isRecording = value;
}
}
}
registerProcessor('buffer-detector',BufferProcessor );
I'm trying to create a static cluster of two Spring Boot applications with embedded HornetQ servers. One application/server will be handling external events and generating messages to be sent to a message queue. The other application/server will be listening on the message queue and process incoming messages. Because the link between the two applications is unreliable, each will use only local/inVM clients to produce/consume messages on their respective server, and relying on the clustering functionality to forward the messages to the queue on the other server in the cluster.
I'm using the HornetQConfigurationCustomizer to customize the embedded HornetQ server, because by default it only comes with an InVMConnectorFactory.
I have created a couple of sample applications that illustrate this setup, throughout this example "ServerSend", refers to the server that will be producing messages, and "ServerReceive" refers to the server that will be consuming messages.
pom.xml for both applications contains:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hornetq</artifactId>
</dependency>
<dependency>
<groupId>org.hornetq</groupId>
<artifactId>hornetq-jms-server</artifactId>
</dependency>
DemoHornetqServerSendApplication:
#SpringBootApplication
#EnableScheduling
public class DemoHornetqServerSendApplication {
#Autowired
private JmsTemplate jmsTemplate;
private #Value("${spring.hornetq.embedded.queues}") String testQueue;
public static void main(String[] args) {
SpringApplication.run(DemoHornetqServerSendApplication.class, args);
}
#Scheduled(fixedRate = 5000)
private void sendMessage() {
String message = "Timestamp from Server: " + System.currentTimeMillis();
System.out.println("Sending message: " + message);
jmsTemplate.convertAndSend(testQueue, message);
}
#Bean
public HornetQConfigurationCustomizer hornetCustomizer() {
return new HornetQConfigurationCustomizer() {
#Override
public void customize(Configuration configuration) {
String serverSendConnectorName = "server-send-connector";
String serverReceiveConnectorName = "server-receive-connector";
Map<String, TransportConfiguration> connectorConf = configuration.getConnectorConfigurations();
Map<String, Object> params = new HashMap<String, Object>();
params.put(TransportConstants.HOST_PROP_NAME, "localhost");
params.put(TransportConstants.PORT_PROP_NAME, "5445");
TransportConfiguration tc = new TransportConfiguration(NettyConnectorFactory.class.getName(), params);
connectorConf.put(serverSendConnectorName, tc);
Set<TransportConfiguration> acceptors = configuration.getAcceptorConfigurations();
tc = new TransportConfiguration(NettyAcceptorFactory.class.getName(), params);
acceptors.add(tc);
params = new HashMap<String, Object>();
params.put(TransportConstants.HOST_PROP_NAME, "localhost");
params.put(TransportConstants.PORT_PROP_NAME, "5446");
tc = new TransportConfiguration(NettyConnectorFactory.class.getName(), params);
connectorConf.put(serverReceiveConnectorName, tc);
List<String> staticConnectors = new ArrayList<String>();
staticConnectors.add(serverReceiveConnectorName);
ClusterConnectionConfiguration conf = new ClusterConnectionConfiguration(
"my-cluster", // name
"jms", // address
serverSendConnectorName, // connector name
500, // retry interval
true, // duplicate detection
true, // forward when no consumers
1, // max hops
1000000, // confirmation window size
staticConnectors,
true // allow direct connections only
);
configuration.getClusterConfigurations().add(conf);
AddressSettings setting = new AddressSettings();
setting.setRedistributionDelay(0);
configuration.getAddressesSettings().put("#", setting);
}
};
}
}
application.properties (ServerSend):
spring.hornetq.mode=embedded
spring.hornetq.embedded.enabled=true
spring.hornetq.embedded.queues=jms.testqueue
spring.hornetq.embedded.cluster-password=password
DemoHornetqServerReceiveApplication:
#SpringBootApplication
#EnableJms
public class DemoHornetqServerReceiveApplication {
#Autowired
private JmsTemplate jmsTemplate;
private #Value("${spring.hornetq.embedded.queues}") String testQueue;
public static void main(String[] args) {
SpringApplication.run(DemoHornetqServerReceiveApplication.class, args);
}
#JmsListener(destination="${spring.hornetq.embedded.queues}")
public void receiveMessage(String message) {
System.out.println("Received message: " + message);
}
#Bean
public HornetQConfigurationCustomizer hornetCustomizer() {
return new HornetQConfigurationCustomizer() {
#Override
public void customize(Configuration configuration) {
String serverSendConnectorName = "server-send-connector";
String serverReceiveConnectorName = "server-receive-connector";
Map<String, TransportConfiguration> connectorConf = configuration.getConnectorConfigurations();
Map<String, Object> params = new HashMap<String, Object>();
params.put(TransportConstants.HOST_PROP_NAME, "localhost");
params.put(TransportConstants.PORT_PROP_NAME, "5446");
TransportConfiguration tc = new TransportConfiguration(NettyConnectorFactory.class.getName(), params);
connectorConf.put(serverReceiveConnectorName, tc);
Set<TransportConfiguration> acceptors = configuration.getAcceptorConfigurations();
tc = new TransportConfiguration(NettyAcceptorFactory.class.getName(), params);
acceptors.add(tc);
params = new HashMap<String, Object>();
params.put(TransportConstants.HOST_PROP_NAME, "localhost");
params.put(TransportConstants.PORT_PROP_NAME, "5445");
tc = new TransportConfiguration(NettyConnectorFactory.class.getName(), params);
connectorConf.put(serverSendConnectorName, tc);
List<String> staticConnectors = new ArrayList<String>();
staticConnectors.add(serverSendConnectorName);
ClusterConnectionConfiguration conf = new ClusterConnectionConfiguration(
"my-cluster", // name
"jms", // address
serverReceiveConnectorName, // connector name
500, // retry interval
true, // duplicate detection
true, // forward when no consumers
1, // max hops
1000000, // confirmation window size
staticConnectors,
true // allow direct connections only
);
configuration.getClusterConfigurations().add(conf);
AddressSettings setting = new AddressSettings();
setting.setRedistributionDelay(0);
configuration.getAddressesSettings().put("#", setting);
}
};
}
}
application.properties (ServerReceive):
spring.hornetq.mode=embedded
spring.hornetq.embedded.enabled=true
spring.hornetq.embedded.queues=jms.testqueue
spring.hornetq.embedded.cluster-password=password
After starting both applications, log output shows this:
ServerSend:
2015-04-09 11:11:58.471 INFO 7536 --- [ main] org.hornetq.core.server : HQ221000: live server is starting with configuration HornetQ Configuration (clustered=true,backup=false,sharedStore=true,journalDirectory=C:\Users\****\AppData\Local\Temp\hornetq-data/journal,bindingsDirectory=data/bindings,largeMessagesDirectory=data/largemessages,pagingDirectory=data/paging)
2015-04-09 11:11:58.501 INFO 7536 --- [ main] org.hornetq.core.server : HQ221045: libaio is not available, switching the configuration into NIO
2015-04-09 11:11:58.595 INFO 7536 --- [ main] org.hornetq.core.server : HQ221043: Adding protocol support CORE
2015-04-09 11:11:58.720 INFO 7536 --- [ main] org.hornetq.core.server : HQ221003: trying to deploy queue jms.queue.jms.testqueue
2015-04-09 11:11:59.568 INFO 7536 --- [ main] org.hornetq.core.server : HQ221020: Started Netty Acceptor version 4.0.13.Final localhost:5445
2015-04-09 11:11:59.593 INFO 7536 --- [ main] org.hornetq.core.server : HQ221007: Server is now live
2015-04-09 11:11:59.593 INFO 7536 --- [ main] org.hornetq.core.server : HQ221001: HornetQ Server version 2.4.5.FINAL (Wild Hornet, 124) [c139929d-d90f-11e4-ba2e-e58abf5d6944]
ServerReceive:
2015-04-09 11:12:04.401 INFO 4528 --- [ main] org.hornetq.core.server : HQ221000: live server is starting with configuration HornetQ Configuration (clustered=true,backup=false,sharedStore=true,journalDirectory=C:\Users\****\AppData\Local\Temp\hornetq-data/journal,bindingsDirectory=data/bindings,largeMessagesDirectory=data/largemessages,pagingDirectory=data/paging)
2015-04-09 11:12:04.410 INFO 4528 --- [ main] org.hornetq.core.server : HQ221045: libaio is not available, switching the configuration into NIO
2015-04-09 11:12:04.520 INFO 4528 --- [ main] org.hornetq.core.server : HQ221043: Adding protocol support CORE
2015-04-09 11:12:04.629 INFO 4528 --- [ main] org.hornetq.core.server : HQ221003: trying to deploy queue jms.queue.jms.testqueue
2015-04-09 11:12:05.545 INFO 4528 --- [ main] org.hornetq.core.server : HQ221020: Started Netty Acceptor version 4.0.13.Final localhost:5446
2015-04-09 11:12:05.578 INFO 4528 --- [ main] org.hornetq.core.server : HQ221007: Server is now live
2015-04-09 11:12:05.578 INFO 4528 --- [ main] org.hornetq.core.server : HQ221001: HornetQ Server version 2.4.5.FINAL (Wild Hornet, 124) [c139929d-d90f-11e4-ba2e-e58abf5d6944]
I see clustered=true in both outputs, and this would show false if I removed the cluster configuration from the HornetQConfigurationCustomizer, so it must have some effect.
Now, ServerSend shows this in the console output:
Sending message: Timestamp from Server: 1428574324910
Sending message: Timestamp from Server: 1428574329899
Sending message: Timestamp from Server: 1428574334904
However, ServerReceive shows nothing.
It appears that the messages are not forwarded from ServerSend to ServerReceive.
I did some more testing, by creating two further Spring Boot applications (ClientSend and ClientReceive), which do not have a HornetQ server embedded and instead connect to a "native" server.
pom.xml for both client applications contains:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hornetq</artifactId>
</dependency>
DemoHornetqClientSendApplication:
#SpringBootApplication
#EnableScheduling
public class DemoHornetqClientSendApplication {
#Autowired
private JmsTemplate jmsTemplate;
private #Value("${queue}") String testQueue;
public static void main(String[] args) {
SpringApplication.run(DemoHornetqClientSendApplication.class, args);
}
#Scheduled(fixedRate = 5000)
private void sendMessage() {
String message = "Timestamp from Client: " + System.currentTimeMillis();
System.out.println("Sending message: " + message);
jmsTemplate.convertAndSend(testQueue, message);
}
}
application.properties (ClientSend):
spring.hornetq.mode=native
spring.hornetq.host=localhost
spring.hornetq.port=5446
queue=jms.testqueue
DemoHornetqClientReceiveApplication:
#SpringBootApplication
#EnableJms
public class DemoHornetqClientReceiveApplication {
#Autowired
private JmsTemplate jmsTemplate;
private #Value("${queue}") String testQueue;
public static void main(String[] args) {
SpringApplication.run(DemoHornetqClientReceiveApplication.class, args);
}
#JmsListener(destination="${queue}")
public void receiveMessage(String message) {
System.out.println("Received message: " + message);
}
}
application.properties (ClientReceive):
spring.hornetq.mode=native
spring.hornetq.host=localhost
spring.hornetq.port=5445
queue=jms.testqueue
Now the console shows this:
ServerReveive:
Received message: Timestamp from Client: 1428574966630
Received message: Timestamp from Client: 1428574971600
Received message: Timestamp from Client: 1428574976595
ClientReceive:
Received message: Timestamp from Server: 1428574969436
Received message: Timestamp from Server: 1428574974438
Received message: Timestamp from Server: 1428574979446
If I have ServerSend running for a while, and then start ClientReceive, it also receives all the messages queued up to that point, so this shows that the messages don't just disappear somewhere, or get consumed from somewhere else.
For completeness sake I've also pointed ClientSend to ServerSend and ClientReceive to ServerReceive, to see if there is some issue with clustering and the InVM clients, but again there was no outout indicating that any message was received in either ClientReceive or ServerReceive.
So it appears that message delivery to/from each of the embedded brokers to directly connected external clients works fine, but no messages are forwarded between brokers in the cluster.
So, after all this, the big question, what's wrong with the setup that messages aren't forwarded within the cluster?
http://docs.jboss.org/hornetq/2.2.5.Final/user-manual/en/html/architecture.html#d0e595
"HornetQ core is designed as a set of simple POJOs so if you have an application that requires messaging functionality internally but you don't want to expose that as a HornetQ server you can directly instantiate and embed HornetQ servers in your own application."
If you are embedding it, you aren't exposing it as a server. Each of your containers has a seperate instance. It is the equivalent of starting up 2 copies of hornet and giving them the same queue name. One writes to that queue on the first instance and the other listens to the queue on the second instance.
If you want to decouple your apps in this way, you need to have a single place that is acting as a server. Probably, you want to cluster. This isn't specific to Hornet, BTW. You'll find this pattern often.
FILTER
package it.unitn.disi.webdev.claudiovigliarolo;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
#WebFilter(filterName = "AuthenticationFilter", urlPatterns = { "/*" })
public class AuthenticationFilter implements Filter {
private ServletContext context;
public void init(FilterConfig fConfig) throws ServletException {
this.context = fConfig.getServletContext();
this.context.log("AuthenticationFilter initialized");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String uri = req.getRequestURI();
HttpSession session = req.getSession(false);
boolean isLoggedIn = session != null && session.getAttribute("username") != null;
if (!isLoggedIn && !uri.endsWith("start.jsp")) {
res.sendRedirect("start.jsp");
} else {
chain.doFilter(request, response);
}
}
public void destroy() {
// close any resources here
}
}<filter-mapping><filter-name>AuthenticationFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
#WebServlet(name = "GetItems", urlPatterns = { "/GetItems" })
public class GetItems extends HttpServlet {
String dbURL = "jdbc:derby://localhost:1527/ExamDerbyDB";
String user = "WEBENGINE";
String password = "WEBENGINE";
Connection conn = null;
#Override
public void init() {
try {
Class.forName("org.apache.derby.jdbc.ClientDriver");
conn = DriverManager.getConnection(dbURL, user, password);
} catch (ClassNotFoundException | SQLException ex) {
ex.printStackTrace();
}
}
#Override
public void destroy() {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException ex) {
System.err.println("Database connection problem: can't close connection");
}
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
StringBuilder ret = new StringBuilder();
ArrayList<String> inserted = getAllItemsFromDB();
String jsonResponse = getListJson(inserted);
response.setContentType("application/json;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
out.println(jsonResponse);
}
}
private ArrayList<String> getAllItemsFromDB() throws ServletException {
ArrayList elements = new ArrayList();
PreparedStatement stm = null;
ResultSet result = null;
try {
String query = "SELECT USERNAME FROM USERS";
stm = conn.prepareStatement(query);
result = stm.executeQuery();
while(result.next()) {
String string = result.getString(1);
elements.add(string);
}
stm.close();
result.close();
} catch (SQLException ex) {
System.err.println("Database connection problem");
} finally {
try {
if(stm != null) stm.close();
if(result != null) result.close();
} catch (SQLException ex) {
System.err.println("Database connection problem: can't close statement/result");
}
return elements;
}
public String getListJson(ArrayList<String> list) {
if (list.size() == 0)
return null;
StringBuilder ret = new StringBuilder("[");
String prefix = "";
for (int i = 0; i < list.size(); i++) {
StringBuilder sb = new StringBuilder();
ret.append(prefix);
prefix = ",";
ret.append(sb.append("{\"message\":\"").append(list.get(i)).append("\"}").toString());
}
ret.append("]");
return ret.toString();
}
}
class.java
public class MessageList {
protected final LinkedList<Message> list;
public MessageList() {
this.list = new LinkedList<>();
}
public void addMessage(Message m) {
this.list.add(m);
}
public void deleteMessage(String message_id) {
for (Message a : list) {
if (a.message_id.equals(message_id)) {
list.remove(a);
}
}
}
public Message getMessage(String message_id) {
for (Message a : list) {
if (a.message_id.equals(message_id)) {
return a;
}
}
return null;
}
public void addLike(String message_id) {
for (Message a : list) {
if (a.message_id.equals(message_id)) {
a.isLiked++;
}
}
}
StringBuilder ret = new StringBuilder("[");
String prefix = "";for(
int i = 0;i<list.size();i++)
{
Message m = list.get(i);
ret.append(prefix);
prefix = ",";
ret.append(m.toJson());
}ret.append("]");
return ret.toString();
}
public String getListJson()
{
if(list.size() == 0)
{
return null;
}
StringBuilder ret = new StringBuilder("[");
String prefix = "";
for(int i=0; i<list.size(); i++) {
StringBuilder sb = new StringBuilder();
ret.append(prefix);
prefix = ",";
ret.append(sb.append("{\"message\":\"").append(list.get(i)).append("\"}").toString());
}
ret.append("]");
return ret.toString();
}
}
form
<!DOCTYPE html>
<html lang="en">
<body>
<script>
function validateForm(form) {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var error = document.getElementById("error");
error.innerHTML = "";
if (username === "" || password == "") {
form.reset();
error.innerHTML = "password / username empty";
return false;
}
return true;
}
</script>
<div class="container" style="width: 500px; float: left">
<h2 class="text-center">Welcome to the App</h2>
<form
id="registerForm"
method="POST"
onsubmit="return validateForm(this)"
action="Registration"
>
<div class="form-group">
<label for="username">Username:</label>
<input
type="text"
class="form-control"
id="username"
placeholder="Enter email"
name="username"
/>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input
type="password"
class="form-control"
id="password"
placeholder="Enter password"
name="password"
/>
</div>
<div class="form-group form-check"></div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div id="error" class="alert" role="alert"></div>
</div>
</body>
</html>
general
//servelet context
ServletContext application=getServletContext();
application.setAttribute("messages", messages);
//SESSION
HttpSession session = request.getSession();
String name = (String) request.getParameter("username");
session.setAttribute("username", name);
//random id java
String uniqueID = UUID.randomUUID().toString();
//package
it.unitn.disi.webdev.claudiovigliarolo
//project name
VIGLIAROLO_C_202314
//get contextpath
String contextPath = request.getContextPath();
System.out.println("Context Path = " + contextPath);
response.sendRedirect(contextPath + "/main.html");
//BOOTstrap
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
//redirect to other page
window.location.replace("http://stackoverflow.com");
//CONTENT type
response.setContentType("application/json;charset=UTF-8");
response.setContentType("text/html;charset=UTF-8");
//zuccherino
protected final LinkedList<Message> list;
public MessageList() {
this.list = new LinkedList<>();
}
<!DOCTYPE html>
<html lang="en">
<body>
<script>
function validateForm(form) {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var error = document.getElementById("error");
error.innerHTML = "";
if(username === "" || password == "") {
form.reset();
error.innerHTML = "password / username empty";
return false;
}
return true;
}
</script>
<div class="container " style="width:500px; float: left;">
<h2 class="text-center">Welcome to the App</h2>
<form id="registerForm" method="POST" onsubmit="return validateForm(this)" action="Registration">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" class="form-control" id="username" placeholder="Enter email" name="username">
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" class="form-control" id="password" placeholder="Enter password" name="password">
</div>
<div class="form-group form-check">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div id="error" class="alert" role="alert">
</div>
</div>
</body>
</html>
//change styles
const val = keywords.some(k=>item.message.includes(k));
const color = val ? "#FFFF00;" : "transparent;";
document.getElementById("data").innerHTML +=
"<div style=' margin-top:50px;flexdirection: row; display:flex; width:500px; background:" + color + "; justify-content: row; '>" +
item.message +
"</div>";
//setimeout
function refresh() {
// make Ajax call here, inside the callback call:
setTimeout(refresh, 5000);
// ...
}
// initial call, or just call refresh directly
setTimeout(refresh, 5000);
//template strings
`string text`
getclaudio postclaudio
<script>
function onSendData() {
var title = document.getElementById("username").value;
var description = document.getElementById("password").value;
console.log(title, description);
var http = new XMLHttpRequest();
var url = "Registration";
var params = "password=" + description + "&username=" + title;
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function () {
//Call a function when the state changes.
if (http.readyState == 4 && http.status == 200) {
console.log("res", http.responseText);
}
};
http.send(params);
}
</script>
------GET---------------
//loadData noparam
<script>
loadData();
function loadData() {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "GetProducts", true);
xhttp.responseType = "json";
xhttp.onreadystatechange = function () {
var done = 4,
ok = 200;
if (this.readyState === done && this.status === ok) {
my_JSON_object = this.response;
console.log("response", my_JSON_object);
document.getElementById("data").innerHTML = "";
my_JSON_object && my_JSON_object.forEach((item) => {
console.log("item", item.message);
document.getElementById("data").innerHTML +=
" <div class='card' style='width: 300px; margin-top:50px;'>" +
"<div class='card-body'>" +
" <h4 class='card-title'>" + item.name + "</h4>" +
"<p class='card-text'>" + item.description + "</p>" +
" <p class='card-text'>Price: " + item.price + " $</p>" +
" <a href='detail.html?name=" + item.name + "' class='card-link' >View details</a>" +
" </div> </div>";
});
}
};
xhttp.send();
}
</script>
<div id="data"></div>
//loadData withparam
<script>
function getData() {
const urlParams = new URLSearchParams(window.location.search);
const id = urlParams.get('id');
const id2 = urlParams.get('id2');
console.log(id)
var url = "GetItems";
let param1 = id;
let param2 = id2;
var params = "param1=" + param1 + "¶m2=" + param2;
var http = new XMLHttpRequest();
http.open("GET", url + "?" + params, true);
http.responseType = "json";
http.onreadystatechange = function () {
var done = 4,
ok = 200;
if (this.readyState === done && this.status === ok) {
my_JSON_object = this.response;
console.log("response", my_JSON_object);
document.getElementById("data").innerHTML = "";
my_JSON_object && my_JSON_object.forEach((item) => {
console.log("item", item.message);
document.getElementById("data").innerHTML +=
"<div style=' margin-top:50px;flexdirection: row; display:flex; width:500px; justify-content: row; '>" +
item.message +
"</div>";
});
}
};
http.send(null);
}
</script>
<div id="data"></div>
<div class="card" style="margin-top: 50px;">
<div class="card-body">Content</div>
</div>
//render multiple parameters
onclick="showData('${item.name}', '${item.price}', '${item.punteggio}', '${item.extra}' )"
JSON servelet claudio
RETURN JSON
//create simple json response
response.setContentType("application/json;charset=UTF-8");
StringBuilder ret = new StringBuilder();
ret.append("{\"ready\":\"").append("false").append("\"}");
try (PrintWriter out = response.getWriter()) {
out.println(ret.toString());
}
JSON LIST CLASS
public String toJSON() {
StringBuilder ret = new StringBuilder("[");
String prefix = "";
for(int i=0; i<list.size(); i++) {
Message m = list.get(i);
ret.append(prefix);
prefix = ",";
ret.append(m.toJson());
}
ret.append("]");
System.err.println("priting tojson"+ ret.toString());
return ret.toString();
}
JSON ITEM
public String toJson() {
StringBuilder ret = new StringBuilder();
ret.append("{\"id\":\"").append(this.id).append("\",");
ret.append("\"nome\":\"").append(this.nome).append("\",");
ret.append("\"imgName\":\"").append(this.imgName).append("\"}");
return ret.toString();
}
STRING LIST
public String wordsToJSON(ArrayList<String> list) {
System.err.println("lunghezza" + list.size());
if (list.size() == 0) {
return null;
}
StringBuilder ret = new StringBuilder("[");
String prefix = "";
for (int i = 0; i < list.size(); i++) {
StringBuilder sb = new StringBuilder();
ret.append(prefix);
prefix = ",";
ret.append(sb.append("{\"message\":\"").append(list.get(i)).append("\"}").toString());
}
ret.append("]");
System.err.println("jjj" + ret.toString());
return ret.toString();
}
}
JSON RESPONSE OK
ServletContext application=getServletContext();
MappaDiCoppie mappaDiCoppie = (MappaDiCoppie) application.getAttribute("mappaDiCoppie");
HttpSession session= request.getSession();
String username = (String) session.getAttribute("username");
StringBuilder ret = new StringBuilder();
if(mappaDiCoppie != null && username != null)
{
if(mappaDiCoppie.exists(username))
//ok
ret.append("{\"ready\":\"").append("true").append("\"}");
else
//no wait
ret.append("{\"ready\":\"").append("false").append("\"}")
try (PrintWriter out = response.getWriter()) {
out.println(ret.toString());
}
}
```
stylesheet
<link rel="stylesheet" href="./styles/styles.css">
<script type="text/javascript" src="./js/script.js"></script>
matrix html
const N = 9;
const container = document.getElementById("container");
function makeRows(rows, cols) {
container.style.setProperty('--grid-rows', rows);
container.style.setProperty('--grid-cols', cols);
for (c = 0; c < (cols); c++) {
for (r = 0; r < rows; r++) {
const myid = JSON.stringify({x: r, y: c});
let cell = document.createElement("div");
var textnode = document.createElement("span");
textnode.setAttribute("id", myid);
cell.appendChild(textnode);
cell.onclick = function (event) {
showVal(myid, r, c);
}
//cell.innerText = (c + 1);
container.appendChild(cell).className = "grid-item";
container.appendChild(cell).style = "border-color: red";
container.appendChild(cell).style = "border-width: 4px";
}
;
}
}
//styles
.myinput{
width: 50px;
margin-right: 20px;
}
#container {
display: grid;
grid-gap: .5em;
grid-template-rows: repeat(var(--grid-rows), 1fr);
grid-template-columns: repeat(var(--grid-cols), 1fr);
width: 100px;
}
.grid-item {
border: 1px solid #ddd;
text-align: center;
width: 50px;
height: 50px;
border-width: 2px;
border-color: green;
}
grid java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package utils;
import java.util.ArrayList;
import java.util.Random;
/**
*
* #author claud
*/
public class Grid {
int N;
Cell[][] matrix;
public Grid(int N) {
this.N = N;
this.matrix = new Cell[N][N];
}
private int getRandom() {
Random rn = new Random();
int range = 0 - 0 + 1;
int randomNum = rn.nextInt(N) + 0;
return randomNum;
}
public int getValue(int x, int y) {
if (x < N && y < N) {
return this.matrix[x][y].value;
} else {
return -2;
}
}
public void generate() {
System.err.println("ffffffffffffggg");
//fai il ciclo completo
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
this.matrix[i][j] = new Cell(i, j, 0);//aggiungi bombe con random altrimenti valore 0
}
}
}
public void print() {
System.err.println("printiiiiiiiiiiiing START");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.err.println(this.matrix[i][j].value);
}
}
}
}
I'm trying to write a PDF to the client dynamically using servlet/JSP and jquery. Here is what I have so far:
SERVLET
public class IndexServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static MimetypesFileTypeMap mtp = new MimetypesFileTypeMap();
public IndexServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Sysout of doGet from IndexServlet");
////INIT OF VARs
int pdfNum,
pdf;
String[] currentBatch;
String
mimeType = null,
fileID = null,
rtn = null,
docSelect = null,
docNumber = null,
docType = null,
batchName = null,
event = request.getParameter("EVENT"),
pendDir = "\\\\****\\****\\****\\****\\****\\****\\****";
///////////////////
if(event.equals("LOAD")){
System.out.println("You're now in the LOAD portion of the doGet");
PdfInit p = new PdfInit();
Batch b = p.getBatch();
currentBatch = b.pdfFiles;
batchName = b.batchName;
pdfNum = b.pdfNum;
Gson gson = new Gson();
String json = gson.toJson(b);
System.out.println(json);
response.setContentType("application/json");
response.getWriter().write(json);
}else if(event.equals("GETPDF")){
System.out.println("You're now in the GETPDF portion of the doGet");
PdfInit p = new PdfInit();
Batch b = p.getBatch();
currentBatch = b.pdfFiles;
batchName = b.batchName;
pdfNum = b.pdfNum;
pdf = Integer.parseInt(request.getParameter("id"));
String fileName = pendDir + "\\" + batchName + "\\" + currentBatch[pdf];
File file = new File(fileName);
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
ByteArrayDataSource bais = new ByteArrayDataSource(bis, mimeType);
byte [] pdfArray = bais.toByteArray();
String encoded = DatatypeConverter.printBase64Binary(pdfArray);
Gson gson = new Gson();
String json = gson.toJson(encoded);
response.setContentType("application/json");
response.getWriter().write(json);
response.getOutputStream().flush();
response.getOutputStream().close();
JSP
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO- 8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTDHTML4.01Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="/Indexer/_js/jquery-1.10.2.js"></script>
<script type="text/javascript" src="/Indexer/_js/jquery.form.js"></script>
</head>
<body>
<input type="button" value="Load Batch" id="LoadBatchBtn">
<p id="batchName"><b>Batch Name:</b> </p>
<p>Click on a document to view it.</p>
<ol id="pdfList"></ol>
<div id="pdfDiv"></div>
</body>
</html>
<script>
$(document).ready(function(){
$("#LoadBatchBtn").click(function(){
$.getJSON("IndexServlet", {"EVENT": "LOAD"}, function(data) {
$("#batchName").append(data.batchName);
for(var i = 0; i < data.pdfNum; i++ )
{
$("#pdfList").append("<li id=" + i + ">" + data.pdfFiles[i] + "</li>");
}
$("li").click(function(){
$("#pdfDiv").hide();
$.getJSON("IndexServlet", {id: this.id, "EVENT":"GETPDF"}, function(data){
var decodedData = window.atob(data);
$("#pdfDiv").html(decodedData).show();
});
});
});
});
});
</script>
Right now I am not getting anything at all on the JSP. However in the console I can see the base64 string being passed without issue. I know I most likely need to take this one step further, but I am not sure where to go from here.
EDIT
Okay now I am getting string output in the div. How can I turn this into data that the browser reads as a PDF?
I am doing a sample application for UTF-8 with Spring to support multi-language .
This is my JSP with Script ,
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%request.setCharacterEncoding("UTF-8");%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>Test</h1>
<input type="text" id="hide" />
<input type="text" id="message"/>
<button id="button">test</button>
<div id="messageDisplayArea"></div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script type="text/javascript">
var contexPath = "<%=request.getContextPath() %>";
</script>
<script>
$('#button').on('click', sendMessage);
function sendMessage() {
var intxnId = $("#hide").val();
var message = $("#message").val();
alert("send : \n intxnId : " + intxnId + "\nmessage : " + message);
$.ajax({
type: "POST",
cache: false,
url: contexPath + "/test.html",
async: true,
data: "intxnId=" + intxnId + "&message=" + encodeURIComponent(message),
//dataType: "json",
dataType: "html",
contentType: "application/x-www-form-urlencoded; charset=utf-8",
scriptCharset: "utf-8",
success: function(response) {
alert(response);
alert(response.message);
if (response !== null && response !== "" && response !== "null") {
var txt = '{"data":[' + response + ']}';
var json = eval("(" + txt + ")");
for (i = 0; i < json.data.length; i++) {
var data = json.data[i];
var name = data.name;
var message = data.message;
var time = data.time;
alert("Name : " + name + "\nMessage : " + message + "\ntime : " + time);
var createHTML = send(name, message, time);
$("#messageDisplayArea").append(createHTML);
}
;
}
},
error: function(e) {
alert('Error: ' + e);
},
});
function send(name , message , time){
var user = "<div id='user' class='fontStyle'>"+name+"</div>";
var msg = "<div id='msg' class='fontStyle'>"+message+"</div>";
var timeStamp = "<div id='time' class='fontStyle'>"+time+"</div>";
var row = "<div id='msgSet' >"+ user + msg + timeStamp +"</div>";
return row;
}
}
</script>
</body>
</html>
My Spring controller will be ,
#RequestMapping(value = "test.html", method=RequestMethod.POST , headers = "Accept=*",produces = "application/json; charset=utf-8")
public #ResponseBody String sendMessage(HttpSession session, #RequestParam String intxnId, #RequestParam String message, HttpServletRequest request, HttpServletResponse response) {
String contentType = "application/json; charset=utf-8";
response.setContentType(contentType);
try {
// request.setCharacterEncoding("utf-8");
request.setCharacterEncoding("application/json; charset=utf-8");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Send Message UTF-8 ----------------- " + message);
String json = null;
HashMap<String, String> result = new HashMap<String, String>();
result.put("name", "test");
result.put("message", message);
result.put("time", "time");
ObjectMapper map = new ObjectMapper();
if (!result.isEmpty()) {
try {
json = map.writeValueAsString(result);
System.out.println("Send Message :::::::: : " + json);
} catch (Exception e) {
e.printStackTrace();
}
}
return json;
}
My Controllers prints ,
Send Message UTF-8 ----------------- தமிழ் அரிச்சுவடி
Send Message :::::::: : {"message":"தமிழ் அரிச்சுவடி","time":"time","name":"test"}
In this my controller prints the local language . But in the JQuery success alert , I got message as ???? . I need to append the local language text in my JSP .
Hope our stack members will help me.
Following piece of code should solve your issue.
#RequestMapping(value="<your path>",produces = "application/json; charset=utf-8")
public #ResponseBody String sendMessage(#RequestParam String intxnId, #RequestParam String message) {
String json = null;
HashMap<String, String> result = new HashMap<String, String>();
result.put("name", "test");
result.put("message", message);
result.put("time", "time");
ObjectMapper map = new ObjectMapper();
if (!result.isEmpty()) {
try {
json = map.writeValueAsString(result);
System.out.println("Send Message :::::::: : " + json);
} catch (Exception e) {
e.printStackTrace();
}
}
return json;
}
This will produce UTF-8 ajax response.
Add mimeType:"application/json; charset=UTF-8" in jQuery.
I got the solution by changing the Controller as ,
#RequestMapping(value = "test.html", method=RequestMethod.POST , headers = "Accept=*",produces = "application/json; charset=utf-8")
public ResponseEntity<String> sendMessage(HttpSession session, #RequestParam String intxnId, #RequestParam String message, HttpServletRequest request, HttpServletResponse response) {
System.out.println("Send Message UTF-8 ----------------- " + message);
String json = null;
HashMap<String, String> result = new HashMap<String, String>();
result.put("name", "test");
result.put("message", message);
result.put("time", "time");
ObjectMapper map = new ObjectMapper();
if (!result.isEmpty()) {
try {
json = map.writeValueAsString(result);
System.out.println("Send Message :::::::: : " + json);
} catch (Exception e) {
e.printStackTrace();
}
}
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("Content-Type", "application/json; charset=utf-8");
return new ResponseEntity<String>(json, responseHeaders, HttpStatus.CREATED);
}