I am using solr4.0 in jetty server. I want to query solr using solrj and expecting results to be formatted in XML. So i used HttpSolrServer (CloudSolrServer and LBHttpSolrServer does not provide support for setting parser) and i set parser to Xmlparser. Moreover i am also setting SolrQuery param wt=xml.But i am not able to get results in XML.Here is my test code
package solrjtest;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.UUID;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;
class SolrjTest
{
public static void main(String[] args) throws IOException, SolrServerException
{
SolrjTest solrj = new SolrjTest();
solrj.query("hello");
}
public void query(String q) throws IOException, SolrServerException
{
CommonsHttpSolrServer server = null;
String uuid = null;
boolean flag = true;
while (flag == true)
{
uuid = UUID.randomUUID().toString();
File f = new File("D:/SearchResult/" + uuid + ".txt");
if (!f.exists())
{
flag=false;
f.createNewFile();
}
}
try
{
server = new CommonsHttpSolrServer("http://skyfall:8983/solr/documents");
server.setParser(new XMLResponseParser());
}
catch (Exception e)
{
e.printStackTrace();
}
SolrQuery query = new SolrQuery();
query.setQuery(q);
query.setParam("wt", "xml");
FileWriter fw = new FileWriter("D:/SearchResult/" + uuid + ".txt");
try
{
QueryResponse qr = server.query(query);
SolrDocumentList sdl = qr.getResults();
XMLResponseParser r = new XMLResponseParser();
Object[] o = new Object[sdl.size()];
o = sdl.toArray();
for (int i = 0; i < o.length; i++)
{
System.out.println(o[i].toString());
fw.write(o[i].toString() + "\n");
}
fw.flush();
fw.close();
System.out.println("finished");
}
catch (SolrServerException e)
{
e.printStackTrace();
}
}
}
Any idea whats going wrong here ?
With that setup, the Solr server at the machine skyfall does send the response in XML and the CommonsHttpSolrServer wrapper does correctly parse the XML. However, that does not change the internal representation in the QueryResponse, which is just a thin wrapper around the Solr class NamedList.
You can (mis)use the XMLResponseWriter to get an XML representation of the full QueryResponse:
private String toXML(SolrParams request, QueryResponse response) {
XMLResponseWriter xmlWriter = new XMLResponseWriter();
Writer w = new StringWriter();
SolrQueryResponse sResponse = new SolrQueryResponse();
sResponse.setAllValues(response.getResponse());
try {
xmlWriter.write(w, new LocalSolrQueryRequest(null, request), sResponse);
} catch (IOException e) {
throw new RuntimeException("Unable to convert Solr response into XML", e);
}
return w.toString();
}
Related
I have tried to create a CustomQueryParser where I am making use of OpenNLP libraries as well.
My objective is if i have a query "How many defective rims are causing failure in ABC tyres in China"
I want the final query to be something like "defective rims failure tyres China"
which then would go to the Analyzer for further processing.
This is my code for QueryParserPlugin -
package com.mycompany.lucene.search;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.QParser;
import org.apache.solr.search.QParserPlugin;
import com.mycompany.lucene.search.QueryParser;
public class QueryParserPlugin extends QParserPlugin {
#Override
public QParser createParser(String qstr, SolrParams localParams,
SolrParams params, SolrQueryRequest req) {
return new QueryParser(qstr, localParams, params, req, "body_txt_str");
}
}
And the code for my QueryParser -
package com.mycompany.lucene.search;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.QParser;
import org.apache.solr.search.SyntaxError;
import opennlp.tools.postag.POSModel;
import opennlp.tools.postag.POSTaggerME;
import opennlp.tools.tokenize.Tokenizer;
import opennlp.tools.tokenize.TokenizerME;
import opennlp.tools.tokenize.TokenizerModel;
public class QueryParser extends QParser {
private String fieldName;
public QueryParser(String qstr, SolrParams localParams, SolrParams params,
SolrQueryRequest req,
String defaultFieldName) {
super(qstr, localParams, params, req);
fieldName = localParams.get("field");
if (fieldName == null) {
fieldName = params.get("df");
}
}
#Override
public Query parse() throws SyntaxError {
Analyzer analyzer = req.getSchema().getQueryAnalyzer();
InputStream tokenModelIn = null;
InputStream posModelIn = null;
try {
tokenModelIn = new FileInputStream("/Files/en-token.bin");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
TokenizerModel tokenModel = null;
try {
tokenModel = new TokenizerModel(tokenModelIn);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Tokenizer tokenizer = new TokenizerME(tokenModel);
String tokens[] = tokenizer.tokenize(qstr);
try {
posModelIn = new FileInputStream("/Files/en-pos-maxent.bin");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// loading the parts-of-speech model from stream
POSModel posModel = null;
try {
posModel = new POSModel(posModelIn);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// initializing the parts-of-speech tagger with model
POSTaggerME posTagger = new POSTaggerME(posModel);
// Tagger tagging the tokens
String tags[] = posTagger.tag(tokens);
String final_query = "";
for(int i=0;i<tokens.length;i++){
if (tags[i]=="JJ" || tags[i]=="NNS" || tags[i]=="NN") {
final_query = final_query + " " +tokens[i];
}
}
TermQuery tq= new TermQuery(new Term(fieldName,final_query));
return tq;
}
}
I then exported this as a jar and added these jars to my solrconfig.xml -
<lib dir="${solr.install.dir:../../../..}/contrib/customparser/lib"
regex=".*\.JAR" />
<lib dir="${solr.install.dir:../../../..}/contrib/analysis-extras/lib"
regex="opennlp-.*\.jar" />
But getting the below error :
Caused by:
java.lang.NoClassDefFoundError: opennlp/tools/tokenize/Tokenizer
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.apache.solr.core.SolrResourceLoader.findClass(SolrResourceLoader.java:541)
at org.apache.solr.core.SolrResourceLoader.findClass(SolrResourceLoader.java:488)
at org.apache.solr.core.SolrCore.createInstance(SolrCore.java:786)
at org.apache.solr.core.PluginBag.createPlugin(PluginBag.java:135)
at org.apache.solr.core.PluginBag.init(PluginBag.java:271)
at org.apache.solr.core.PluginBag.init(PluginBag.java:260)
at org.apache.solr.core.SolrCore.<init>(SolrCore.java:957)
... 9 more
This is my first time creating a CustomQueryParser, Could you please help me out.
Thanks
most probably your path
${solr.install.dir:../../../..}/contrib/analysis-extras/lib
doesn't contain the relevant opennlp jars or the regex is not appropriate.
that's the first thing to check.
you have to either "bundle" also the opennlp dependencies in your custom query parser jar (e.g. if you use maven to build your project, using maven-assembly-plugin, maven-shade-plugin, etc.) or make sure the opennlp specific jars in the relevant directive in your solrconfig.xml are matched.
I am trying to use OKHTTP (version 2.4.0) along retrofit (1.9.0) on google app engine (1.9.22).
Here is the how i use it:
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectTimeout(COMPOSER_MODULE_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(COMPOSER_MODULE_SOCKET_TIMEOUT, TimeUnit.SECONDS);
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setConverter(new JacksonConverter())
.setEndpoint(ENDPOINT_PATH)
.setClient(new OkClient(okHttpClient))
.build();
This throws the following error:
java.lang.NoClassDefFoundError: java.net.ProxySelector is a restricted class. Please see the Google App Engine developer's guide for more details.
at com.google.apphosting.runtime.security.shared.stub.java.net.ProxySelector.<clinit>(ProxySelector.java)
at com.squareup.okhttp.OkHttpClient.copyWithDefaults(OkHttpClient.java:614)
at com.squareup.okhttp.Call.<init>(Call.java:50)
at com.squareup.okhttp.OkHttpClient.newCall(OkHttpClient.java:595)
at retrofit.client.OkClient.execute(OkClient.java:53)
I gather from the error that "java.net.ProxySelector" is not white-listed for use on google appengine.
Question 1)
Is it possible to use OKHTTP (version 2.4.0) along retrofit (1.9.0) on google app engine (1.9.22)? i.e, is there a work around for this error
if not,
Question 2)
Are there any other way to:
(a) use async HTTP calls with google appengine (with URLFetchService, for instance) ?
(b) set connection and socket timeouts for the client used from (a) ?
The links i have come across via search:
(1) Retrofit timeout configuration for clients
(2) Google App Engine URL Fetch Java API
You can use HttpUrlConnection with Retrofit2 to use it in Google APP Engine
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.servlet.http.HttpServletResponse;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;
public class RetrofitCall implements Call {
Request request;
RetrofitCall(Request request) {
this.request = request;
}
#Override
public Request request() {
return request;
}
#Override
public Response execute() throws IOException {
URL url = request.url().url();
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setUseCaches(false);
connection.setDoOutput(true);
connection.setRequestMethod(request.method());
Headers headers = request.headers();
if (headers != null) {
for (int i = 0; i < headers.size(); i++) {
String name = headers.name(i);
connection.setRequestProperty(name, headers.get(name));
}
}
if (request.body() != null) {
BufferedSink outbuf;
outbuf = Okio.buffer(Okio.sink(connection.getOutputStream()));
request.body().writeTo(outbuf);
outbuf.close();
}
connection.connect();
final BufferedSource source = Okio.buffer(Okio.source(connection.getInputStream()));
if (connection.getResponseCode() != HttpServletResponse.SC_OK) {
throw new IOException("Fail to call " + " :: " + source.readUtf8());
}
Response response = new Response.Builder()
.code(connection.getResponseCode())
.message(connection.getResponseMessage())
.request(request)
.protocol(Protocol.HTTP_1_1)
.body(new ResponseBody() {
#Override
public MediaType contentType() {
return MediaType.parse(connection.getContentType());
}
#Override
public long contentLength() {
return connection.getContentLengthLong();
}
#Override
public BufferedSource source() {
return source;
}
})
.build();
return response;
}
#Override
public void enqueue(Callback responseCallback) {
}
#Override
public void cancel() {
}
#Override
public boolean isExecuted() {
return false;
}
#Override
public boolean isCanceled() {
return false;
}
public static class Factory implements Call.Factory {
#Override
public Call newCall(Request request) {
return new RetrofitCall(request);
}
}
}
You can use the following code snippet to run Retorifit2 with GAE limitations. It contains a lot of debugging stuffs free to remove in production and does not implement real async call.
okhttp3.Call.Factory gaeCallFactory = new okhttp3.Call.Factory() {
#Override
public okhttp3.Call newCall(final Request request) {
final URL url = request.url().url();
final String method = url.toString();
return new okhttp3.Call() {
#Override
public Request request() {
return request;
}
#Override
public Response execute() throws IOException {
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setUseCaches(false);
if (request.body() != null) {
//TODO ajust for different needs
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
BufferedSink outbuf;
ByteArrayOutputStream out = new ByteArrayOutputStream();
outbuf = Okio.buffer(Okio.sink(out));
request.body().writeTo(outbuf);
outbuf.close();
logger.info("Calling " + method + "\n" + new String(out.toByteArray()));
outbuf = Okio.buffer(Okio.sink(connection.getOutputStream()));
request.body().writeTo(outbuf);
outbuf.close();
} else {
logger.info("Calling " + method);
}
final BufferedSource source = Okio.buffer(Okio.source(connection.getInputStream()));
if (connection.getResponseCode() != HttpServletResponse.SC_OK) {
throw new IOException("Fail to call " + method + " :: " + source.readUtf8());
}
Response response = new Response.Builder()
.code(connection.getResponseCode())
.message(connection.getResponseMessage())
.request(request)
.protocol(Protocol.HTTP_1_1)
.body(new ResponseBody() {
#Override
public MediaType contentType() {
return MediaType.parse(connection.getContentType());
}
#Override
public long contentLength() {
return connection.getContentLengthLong();
}
#Override
public BufferedSource source() {
return source;
}
})
.build();
logger.info("Call response code: " + response.code() + " message: " + response.message());
return response;
}
#Override
public void enqueue(Callback responseCallback) {
try {
responseCallback.onResponse(this, execute());
} catch (IOException e) {
responseCallback.onFailure(this, e);
}
}
#Override
public void cancel() {
}
#Override
public boolean isExecuted() {
return false;
}
#Override
public boolean isCanceled() {
return false;
}
};
}
};
Retrofit retrofit = new Retrofit.Builder()
.callFactory(gaeCallFactory)
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(ENDPOINT_URI)
.build();
You need to use the Appengine URLFetchClient instead of the OkHttpClient. Like this:
import retrofit.appengine.UrlFetchClient;
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setConverter(new JacksonConverter())
.setEndpoint(ENDPOINT_PATH)
.setClient(new UrlFetchClient())
.build();
Please note this only works with Retrofit1, this will not work with Retrofit2 because it's coupled directly to OkHttp as explained by Jake Wharton here
How can I retrieve and display images from a database in a JSP page?
Let's see in steps what should happen:
JSP is basically a view technology which is supposed to generate HTML output.
To display an image in HTML, you need the HTML <img> element.
To let it locate an image, you need to specify its src attribute.
The src attribute needs to point to a valid http:// URL and thus not a local disk file system path file:// as that would never work when the server and client run at physically different machines.
The image URL needs to have the image identifier in either the request path (e.g. http://example.com/context/images/foo.png) or as request parameter (e.g. http://example.com/context/images?id=1).
In JSP/Servlet world, you can let a Servlet listen on a certain URL pattern like /images/*, so that you can just execute some Java code on specific URL's.
Images are binary data and are to be obtained as either a byte[] or InputStream from the DB, the JDBC API offers the ResultSet#getBytes() and ResultSet#getBinaryStream() for this, and JPA API offers #Lob for this.
In the Servlet you can just write this byte[] or InputStream to the OutputStream of the response the usual Java IO way.
The client side needs to be instructed that the data should be handled as an image, thus at least the Content-Type response header needs to be set as well. You can obtain the right one via ServletContext#getMimeType() based on image file extension which you can extend and/or override via <mime-mapping> in web.xml.
That should be it. It almost writes code itself. Let's start with HTML (in JSP):
<img src="${pageContext.request.contextPath}/images/foo.png">
<img src="${pageContext.request.contextPath}/images/bar.png">
<img src="${pageContext.request.contextPath}/images/baz.png">
You can if necessary also dynamically set src with EL while iterating using JSTL:
<c:forEach items="${imagenames}" var="imagename">
<img src="${pageContext.request.contextPath}/images/${imagename}">
</c:forEach>
Then define/create a servlet which listens on GET requests on URL pattern of /images/*, the below example uses plain vanilla JDBC for the job:
#WebServlet("/images/*")
public class ImageServlet extends HttpServlet {
// content=blob, name=varchar(255) UNIQUE.
private static final String SQL_FIND = "SELECT content FROM Image WHERE name = ?";
#Resource(name="jdbc/yourDB") // For Tomcat, define as <Resource> in context.xml and declare as <resource-ref> in web.xml.
private DataSource dataSource;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String imageName = request.getPathInfo().substring(1); // Returns "foo.png".
try (Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL_FIND)) {
statement.setString(1, imageName);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
byte[] content = resultSet.getBytes("content");
response.setContentType(getServletContext().getMimeType(imageName));
response.setContentLength(content.length);
response.getOutputStream().write(content);
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
}
}
} catch (SQLException e) {
throw new ServletException("Something failed at SQL/DB level.", e);
}
}
}
That's it. In case you worry about HEAD and caching headers and properly responding on those requests, use this abstract template for static resource servlet.
See also:
How should I connect to JDBC database / datasource in a servlet based application?
How to upload an image and save it in database?
Simplest way to serve static data from outside the application server in a Java web application
I suggest you address that as two problems. There are several questions and answer related to both.
How to load blob from MySQL
See for instance Retrieve image stored as blob
How to display image dynamically
See for instance Show thumbnail dynamically
I've written and configured the code in JSP using Oracle database.
Hope it will help.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpSession;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class displayfetchimage
*/
#WebServlet("/displayfetchimage")
public class displayfetchimage extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public displayfetchimage() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
Statement stmt = null;
String sql = null;
BufferedInputStream bin = null;
BufferedOutputStream bout = null;
InputStream in = null;
response.setContentType("image/jpeg");
ServletOutputStream out;
out = response.getOutputStream();
Connection conn = employee.DbConnection.getDatabaseConnection();
HttpSession session = (HttpSession) request.getSession();
String ID = session.getAttribute("userId").toString().toLowerCase();
try {
stmt = conn.createStatement();
sql = "select user_image from employee_data WHERE username='" + ID + "' and rownum<=1";
ResultSet result = stmt.executeQuery(sql);
if (result.next()) {
in = result.getBinaryStream(1);// Since my data was in first column of table.
}
bin = new BufferedInputStream(in);
bout = new BufferedOutputStream(out);
int ch = 0;
while ((ch = bin.read()) != -1) {
bout.write(ch);
}
} catch (SQLException ex) {
Logger.getLogger(displayfetchimage.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (bin != null)
bin.close();
if (in != null)
in.close();
if (bout != null)
bout.close();
if (out != null)
out.close();
if (conn != null)
conn.close();
} catch (IOException | SQLException ex) {
System.out.println("Error : " + ex.getMessage());
}
}
}
// response.getWriter().append("Served at: ").append(request.getContextPath());
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Statement stmt = null;
String sql = null;
BufferedInputStream bin = null;
BufferedOutputStream bout = null;
InputStream in = null;
response.setContentType("image/jpeg");
ServletOutputStream out;
out = response.getOutputStream();
Connection conn = employee.DbConnection.getDatabaseConnection();
HttpSession session = (HttpSession) request.getSession();
String ID = session.getAttribute("userId").toString().toLowerCase();
try {
stmt = conn.createStatement();
sql = "select user_image from employee_data WHERE username='" + ID + "' and rownum<=1";
ResultSet result = stmt.executeQuery(sql);
if (result.next()) {
in = result.getBinaryStream(1);
}
bin = new BufferedInputStream(in);
bout = new BufferedOutputStream(out);
int ch = 0;
while ((ch = bin.read()) != -1) {
bout.write(ch);
}
} catch (SQLException ex) {
Logger.getLogger(displayfetchimage.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (bin != null)
bin.close();
if (in != null)
in.close();
if (bout != null)
bout.close();
if (out != null)
out.close();
if (conn != null)
conn.close();
} catch (IOException | SQLException ex) {
System.out.println("Error : " + ex.getMessage());
}
}
}
}
Try to flush and close the output stream if it does not display.
Blob image = rs.getBlob(ImageColName);
InputStream in = image.getBinaryStream();
// Output the blob to the HttpServletResponse
response.setContentType("image/jpeg");
BufferedOutputStream o = new BufferedOutputStream(response.getOutputStream());
byte by[] = new byte[32768];
int index = in.read(by, 0, 32768);
while (index != -1) {
o.write(by, 0, index);
index = in.read(by, 0, 32768);
}
o.flush();
o.close();
I used SQL SERVER database and so the answer's code is in accordance. All you have to do is include an <img> tag in your jsp page and call a servlet from its src attribute like this
<img width="200" height="180" src="DisplayImage?ID=1">
Here 1 is unique id of image in database and ID is a variable. We receive value of this variable in servlet. In servlet code we take the binary stream input from correct column in table. That is your image is stored in which column. In my code I used third column because my images are stored as binary data in third column. After retrieving input stream data from table we read its content in an output stream so it can be written on screen. Here is it
import java.io.*;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.*;
import javax.servlet.http.*;
import model.ConnectionManager;
public class DisplayImage extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException
{
Statement stmt=null;
String sql=null;
BufferedInputStream bin=null;
BufferedOutputStream bout=null;
InputStream in =null;
response.setContentType("image/jpeg");
ServletOutputStream out;
out = response.getOutputStream();
Connection conn = ConnectionManager.getConnection();
int ID = Integer.parseInt(request.getParameter("ID"));
try {
stmt = conn.createStatement();
sql = "SELECT * FROM IMAGETABLE WHERE ID="+ID+"";
ResultSet result = stmt.executeQuery(sql);
if(result.next()){
in=result.getBinaryStream(3);//Since my data was in third column of table.
}
bin = new BufferedInputStream(in);
bout = new BufferedOutputStream(out);
int ch=0;
while((ch=bin.read())!=-1)
{
bout.write(ch);
}
} catch (SQLException ex) {
Logger.getLogger(DisplayImage.class.getName()).log(Level.SEVERE, null, ex);
}finally{
try{
if(bin!=null)bin.close();
if(in!=null)in.close();
if(bout!=null)bout.close();
if(out!=null)out.close();
if(conn!=null)conn.close();
}catch(IOException | SQLException ex){
System.out.println("Error : "+ex.getMessage());
}
}
}
}
After the execution of your jsp or html file you will see the image on screen.
You can also create custom tag for displaying image.
1) create custom tag java class and tld file.
2) write logic to display image like conversion of byte[] to string by Base64.
so it is used for every image whether you are displaying only one image or multiple images in single jsp page.
I am trying to form a query in solr for data import but could not able to do so.
I need to form the below query:
http://salsa23q-XXX-08.XXX.XXX.com:8080/solr/#/geoloc_replica1/dataimport/?command=full-import&clean=true
The code I am trying:
public class SolrJDB
{
public static String url = "http://salsa23q-XXX-08.XXX.XXX.com:8080/solr:8080/solr";
public static SolrServer localserver;
public static CloudSolrServer cloudserver;// = new CloudSolrServer("url");
public static SolrQuery que;
public static SolrInputDocument doc;
public static SolrDocumentList list;
public static QueryResponse response;
public static String serverurl = "http://salsa23q-XXX-08.XXX.XXX.com:8080/solr";
public static void main(String[] args) throws MalformedURLException, SQLException, SolrServerException {
try{
System.out.println("+++++++++++++ Starting here +++++++++++++++++++++");
//Cloud Server
String url = "salsa23q-XXX-08.XXX.XXX.com:8080/solr";
cloudserver = new CloudSolrServer(url);
SolrQuery parameters = new SolrQuery();
parameters.set("qt","/geoloc_replica1");
parameters.set("qt","//dataimport");
parameters.set("command","full-import");
System.out.println("Query to be Executed ============"+parameters.toString());
QueryResponse response = cloudserver.query(parameters);
SolrDocumentList list = response.getResults();
}
catch(SolrServerException e){
System.out.println(e.toString());
e.printStackTrace();
}
catch(Exception e){
System.out.println(e.toString());
e.printStackTrace();
}
}
}
I am getting following error:
org.apache.solr.client.solrj.SolrServerException: Error executing query
at org.apache.solr.client.solrj.request.QueryRequest.process(QueryRequest.java:98)
at org.apache.solr.client.solrj.SolrServer.query(SolrServer.java:301)
at SolrJDB.main(SolrJDB.java:37)
Caused by: java.lang.RuntimeException
at org.apache.solr.common.cloud.SolrZkClient.<init>(SolrZkClient.java:115)
at org.apache.solr.common.cloud.SolrZkClient.<init>(SolrZkClient.java:83)
at org.apache.solr.common.cloud.ZkStateReader.<init>(ZkStateReader.java:138)
at org.apache.solr.client.solrj.impl.CloudSolrServer.connect(CloudSolrServer.java:140)
at org.apache.solr.client.solrj.impl.CloudSolrServer.request(CloudSolrServer.java:165)
at org.apache.solr.client.solrj.request.QueryRequest.process(QueryRequest.java:90)
... 2 more
You are mixing up things in your code. You want to perform a request to run a DataImportHandler. But you are constructing a SolrQuery. The latter represents a search request.
What you need to run a DataImportHandler via the Java API is an UpdateRequest.
public int runDataImportHandler() throws Exception {
// fill in the parameters you want to run your import with
ModifiableSolrParams tmpParams = new ModifiableSolrParams();
tmpParams.set("command", "full-import");
tmpParams.set("clean", true);
tmpParams.set("commit", true);
tmpParams.set("optimize", true);
// create the update request
UpdateRequest tmpRequest = new UpdateRequest("/dataimport");
tmpRequest.setParams(tmpParams);
SolrServer tmpServer = getServer();
tmpRequest.process(tmpServer);
ModifiableSolrParams tmpStatusParams = new ModifiableSolrParams();
tmpStatusParams.set("command", "status");
String tmpStatus = "busy";
int tmpProcessed = 0;
do {
System.out.println("waiting for import to finish, status was " + tmpStatus);
Thread.sleep(500);
UpdateRequest tmpStatusRequest = new UpdateRequest("/dataimport");
tmpStatusRequest.setParams(tmpStatusParams);
UpdateResponse tmpStatusResponse = tmpStatusRequest.process(tmpServer);
tmpStatus = tmpStatusResponse.getResponse().get("status").toString();
Map tmpMessages = (Map) tmpStatusResponse.getResponse().get("statusMessages");
System.out.println("import status is " + tmpStatus);
if (tmpMessages.get("Total Documents Processed") != null) {
tmpProcessed = Integer.valueOf(tmpMessages.get("Total Documents Processed").toString());
}
} while ("busy".equals(tmpStatus));
System.out.println("import done");
return tmpProcessed;
}
As I can see your code the exception is related to how CloudSolrServer instance is created :-
To make instance of CloudSolrServer you need to have Solr in Cloud mode and the URL used here will be zookeeper address. CloudSolrServer creates zkStateReader which gets live nodes and collection from which it query.
Following is the exact way how you would be creating the code for dataimport:-
public static void main(String[] args) throws SolrServerException, IOException {
ModifiableSolrParams params = new ModifiableSolrParams();
params.set(UpdateParams.COLLECTION, "collection1");
params.set(CommonParams.QT, "/dataimport");
params.set("command", "full-import");
params.set("claen", true);
params.set(UpdateParams.COMMIT, true);
params.set(UpdateParams.OPTIMIZE, true);
String url = "localhost:9983"; /*Zookeeper Address*/
CloudSolrServer cloudserver = new CloudSolrServer(url, true);
cloudserver.setDefaultCollection("test");/*This is necessary in case if you are not specifying any collection name in dataimport*/
cloudserver.query(params);
}
How can I retrieve and display images from a database in a JSP page?
Let's see in steps what should happen:
JSP is basically a view technology which is supposed to generate HTML output.
To display an image in HTML, you need the HTML <img> element.
To let it locate an image, you need to specify its src attribute.
The src attribute needs to point to a valid http:// URL and thus not a local disk file system path file:// as that would never work when the server and client run at physically different machines.
The image URL needs to have the image identifier in either the request path (e.g. http://example.com/context/images/foo.png) or as request parameter (e.g. http://example.com/context/images?id=1).
In JSP/Servlet world, you can let a Servlet listen on a certain URL pattern like /images/*, so that you can just execute some Java code on specific URL's.
Images are binary data and are to be obtained as either a byte[] or InputStream from the DB, the JDBC API offers the ResultSet#getBytes() and ResultSet#getBinaryStream() for this, and JPA API offers #Lob for this.
In the Servlet you can just write this byte[] or InputStream to the OutputStream of the response the usual Java IO way.
The client side needs to be instructed that the data should be handled as an image, thus at least the Content-Type response header needs to be set as well. You can obtain the right one via ServletContext#getMimeType() based on image file extension which you can extend and/or override via <mime-mapping> in web.xml.
That should be it. It almost writes code itself. Let's start with HTML (in JSP):
<img src="${pageContext.request.contextPath}/images/foo.png">
<img src="${pageContext.request.contextPath}/images/bar.png">
<img src="${pageContext.request.contextPath}/images/baz.png">
You can if necessary also dynamically set src with EL while iterating using JSTL:
<c:forEach items="${imagenames}" var="imagename">
<img src="${pageContext.request.contextPath}/images/${imagename}">
</c:forEach>
Then define/create a servlet which listens on GET requests on URL pattern of /images/*, the below example uses plain vanilla JDBC for the job:
#WebServlet("/images/*")
public class ImageServlet extends HttpServlet {
// content=blob, name=varchar(255) UNIQUE.
private static final String SQL_FIND = "SELECT content FROM Image WHERE name = ?";
#Resource(name="jdbc/yourDB") // For Tomcat, define as <Resource> in context.xml and declare as <resource-ref> in web.xml.
private DataSource dataSource;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String imageName = request.getPathInfo().substring(1); // Returns "foo.png".
try (Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL_FIND)) {
statement.setString(1, imageName);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
byte[] content = resultSet.getBytes("content");
response.setContentType(getServletContext().getMimeType(imageName));
response.setContentLength(content.length);
response.getOutputStream().write(content);
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
}
}
} catch (SQLException e) {
throw new ServletException("Something failed at SQL/DB level.", e);
}
}
}
That's it. In case you worry about HEAD and caching headers and properly responding on those requests, use this abstract template for static resource servlet.
See also:
How should I connect to JDBC database / datasource in a servlet based application?
How to upload an image and save it in database?
Simplest way to serve static data from outside the application server in a Java web application
I suggest you address that as two problems. There are several questions and answer related to both.
How to load blob from MySQL
See for instance Retrieve image stored as blob
How to display image dynamically
See for instance Show thumbnail dynamically
I've written and configured the code in JSP using Oracle database.
Hope it will help.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpSession;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class displayfetchimage
*/
#WebServlet("/displayfetchimage")
public class displayfetchimage extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public displayfetchimage() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
Statement stmt = null;
String sql = null;
BufferedInputStream bin = null;
BufferedOutputStream bout = null;
InputStream in = null;
response.setContentType("image/jpeg");
ServletOutputStream out;
out = response.getOutputStream();
Connection conn = employee.DbConnection.getDatabaseConnection();
HttpSession session = (HttpSession) request.getSession();
String ID = session.getAttribute("userId").toString().toLowerCase();
try {
stmt = conn.createStatement();
sql = "select user_image from employee_data WHERE username='" + ID + "' and rownum<=1";
ResultSet result = stmt.executeQuery(sql);
if (result.next()) {
in = result.getBinaryStream(1);// Since my data was in first column of table.
}
bin = new BufferedInputStream(in);
bout = new BufferedOutputStream(out);
int ch = 0;
while ((ch = bin.read()) != -1) {
bout.write(ch);
}
} catch (SQLException ex) {
Logger.getLogger(displayfetchimage.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (bin != null)
bin.close();
if (in != null)
in.close();
if (bout != null)
bout.close();
if (out != null)
out.close();
if (conn != null)
conn.close();
} catch (IOException | SQLException ex) {
System.out.println("Error : " + ex.getMessage());
}
}
}
// response.getWriter().append("Served at: ").append(request.getContextPath());
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Statement stmt = null;
String sql = null;
BufferedInputStream bin = null;
BufferedOutputStream bout = null;
InputStream in = null;
response.setContentType("image/jpeg");
ServletOutputStream out;
out = response.getOutputStream();
Connection conn = employee.DbConnection.getDatabaseConnection();
HttpSession session = (HttpSession) request.getSession();
String ID = session.getAttribute("userId").toString().toLowerCase();
try {
stmt = conn.createStatement();
sql = "select user_image from employee_data WHERE username='" + ID + "' and rownum<=1";
ResultSet result = stmt.executeQuery(sql);
if (result.next()) {
in = result.getBinaryStream(1);
}
bin = new BufferedInputStream(in);
bout = new BufferedOutputStream(out);
int ch = 0;
while ((ch = bin.read()) != -1) {
bout.write(ch);
}
} catch (SQLException ex) {
Logger.getLogger(displayfetchimage.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (bin != null)
bin.close();
if (in != null)
in.close();
if (bout != null)
bout.close();
if (out != null)
out.close();
if (conn != null)
conn.close();
} catch (IOException | SQLException ex) {
System.out.println("Error : " + ex.getMessage());
}
}
}
}
Try to flush and close the output stream if it does not display.
Blob image = rs.getBlob(ImageColName);
InputStream in = image.getBinaryStream();
// Output the blob to the HttpServletResponse
response.setContentType("image/jpeg");
BufferedOutputStream o = new BufferedOutputStream(response.getOutputStream());
byte by[] = new byte[32768];
int index = in.read(by, 0, 32768);
while (index != -1) {
o.write(by, 0, index);
index = in.read(by, 0, 32768);
}
o.flush();
o.close();
I used SQL SERVER database and so the answer's code is in accordance. All you have to do is include an <img> tag in your jsp page and call a servlet from its src attribute like this
<img width="200" height="180" src="DisplayImage?ID=1">
Here 1 is unique id of image in database and ID is a variable. We receive value of this variable in servlet. In servlet code we take the binary stream input from correct column in table. That is your image is stored in which column. In my code I used third column because my images are stored as binary data in third column. After retrieving input stream data from table we read its content in an output stream so it can be written on screen. Here is it
import java.io.*;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.*;
import javax.servlet.http.*;
import model.ConnectionManager;
public class DisplayImage extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException
{
Statement stmt=null;
String sql=null;
BufferedInputStream bin=null;
BufferedOutputStream bout=null;
InputStream in =null;
response.setContentType("image/jpeg");
ServletOutputStream out;
out = response.getOutputStream();
Connection conn = ConnectionManager.getConnection();
int ID = Integer.parseInt(request.getParameter("ID"));
try {
stmt = conn.createStatement();
sql = "SELECT * FROM IMAGETABLE WHERE ID="+ID+"";
ResultSet result = stmt.executeQuery(sql);
if(result.next()){
in=result.getBinaryStream(3);//Since my data was in third column of table.
}
bin = new BufferedInputStream(in);
bout = new BufferedOutputStream(out);
int ch=0;
while((ch=bin.read())!=-1)
{
bout.write(ch);
}
} catch (SQLException ex) {
Logger.getLogger(DisplayImage.class.getName()).log(Level.SEVERE, null, ex);
}finally{
try{
if(bin!=null)bin.close();
if(in!=null)in.close();
if(bout!=null)bout.close();
if(out!=null)out.close();
if(conn!=null)conn.close();
}catch(IOException | SQLException ex){
System.out.println("Error : "+ex.getMessage());
}
}
}
}
After the execution of your jsp or html file you will see the image on screen.
You can also create custom tag for displaying image.
1) create custom tag java class and tld file.
2) write logic to display image like conversion of byte[] to string by Base64.
so it is used for every image whether you are displaying only one image or multiple images in single jsp page.