Spark insert to Hbase - hadoop

I have a pojo class of emp like below:
I am able to read streaming data and I want to insert data to Hbase
#JsonInclude(Include.NON_NULL)
public class empData implements Serializable {
private String id;
private String name;
#Override
public String toString() {
return "id=" + id + ", name="+ name ;
}
public String id() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Below is spark code:
empRecords.foreachRDD(new Function<JavaRDD<empData>, Void>() {
private static final long serialVersionUID = 1L;
#Override
public Void call(JavaRDD<empData> empDataEvent)throws Exception {
Configuration conf = HBaseConfiguration.create();
Configuration config = null;
config = HBaseConfiguration.create();
config.set("hbase.zookeeper.quorum", "**********);
HBaseAdmin.checkHBaseAvailable(config);
config.set(TableInputFormat.INPUT_TABLE, "tableName");
Job newAPIJobConfiguration1 = Job.getInstance(config);
newAPIJobConfiguration1.getConfiguration().set(TableOutputFormat.OUTPUT_TABLE, "empHbase");
newAPIJobConfiguration1.setOutputFormatClass(org.apache.hadoop.hbase.mapreduce.TableOutputFormat.class);
JavaPairRDD<ImmutableBytesWritable, Put> inesrts = empData.mapToPair(new PairFunction<Row, ImmutableBytesWritable, Put>() {
public Tuple2<ImmutableBytesWritable, Put> call(Row row) throws Exception
{
Put put = new Put(Bytes.toBytes(row.getString(0)));
put.add(Bytes.toBytes("empA"),Bytes.toBytes("id"),Bytes.toBytes(row.getString(1)));
put.add(Bytes.toBytes("empA"),Bytes.toBytes("name"),Bytes.toBytes(row.getString(2)));
return new Tuple2<ImmutableBytesWritable, Put>(new ImmutableBytesWritable(), put);
}
});
inserts.saveAsNewAPIHadoopDataset(newAPIJobConfiguration1.getConfiguration());
}
});
jssc.start();
jssc.awaitTermination();
}
The problem in the code is this step:
JavaPairRDD<ImmutableBytesWritable, Put> inesrts =empDataEvent.mapToPair(new PairFunction<Row, ImmutableBytesWritable, Put>()
How to use empDataEvent and how to insert..
How do I insert as mapToPair empDataEvent class object so that I can insert into Hbase.
Any help appreciated..

Aman,
In your code you have refer "Row", can you please elaborate where it is coming from? because there is no reference for it.
See updated code below, use class name "empData" instead of "Row" object.
JavaPairRDD<ImmutableBytesWritable, Put> inesrts = empData.mapToPair(new PairFunction<empData, ImmutableBytesWritable, Put>() {
public Tuple2<ImmutableBytesWritable, Put> call(empData row) throws Exception
{
Put put = new Put(Bytes.toBytes(row.id));
put.add(Bytes.toBytes("empA"),Bytes.toBytes("id"),Bytes.toBytes(row.id));
put.add(Bytes.toBytes("empA"),Bytes.toBytes("name"),Bytes.toBytes(row.getName));
return new Tuple2<ImmutableBytesWritable, Put>(new ImmutableBytesWritable(), put);
}
});

Related

Take the sum of the query result as separate data

Etity
#Entity
public class DateFMail {
#Id
private double balance;
public DateFMail() {
}
public DateFMail(double balance) {this.balance = balance;}
public DateFMail(DateFMail dateFMail) {
}
public double getBalance() { return balance;}
#Override
public String toString() {
return "DateFMail{" +
"balance=" + balance +
'}';
}
}
Service
public interface DateFMailService {
List<DateFMail> findAll();
}
Impl
#Service
public class DateFMailServiceImpl implements DateFMailService {
#Autowired
private DateFMailRepository mailRepository;
#Override
public List<DateFMail> findAll() {
return mailRepository.findAll();
}
}
Repository
#Repository
public interface DateFMailRepository extends JpaRepository<DateFMail, Long> {
#Query(value = "SELECT SUM(balance) \n" +
" FROM agents", nativeQuery = true)
List<DateFMail> findAll();
}
Mail Seder
#Service
public class EmailDos {
#Autowired
private JavaMailSender mailSender;
private DateFMailRepository mailRepository;
String fileDate1 = new SimpleDateFormat("dd.MM.yyyy").format(new Date());
LocalDate today = LocalDate.now();
String fileDate = (today.minusDays(1)).format(DateTimeFormatter.ofPattern("dd MMM"));
String fileDate2 = (today.minusMonths(1)).format(DateTimeFormatter.ofPattern("MMM"));
public void sendMailSum(String from, String to, String subject, String body, String fileToAttach) throws SQLException {
List<DateFMail> list = new ArrayList<>(mailRepository.findAll());
List<DateFMail> list1 = list.stream()
.map(DateFMail::new)
.collect(Collectors.toList());
System.out.println("sending email...................");
System.out.println(list1);
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
mimeMessage.setFrom(new InternetAddress(from));
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
mimeMessage.setSubject(subject);
mimeMessage.setText(body);
FileSystemResource file = new FileSystemResource(new File("C:...xlsx"));
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom("SomeAddress#gmail.com");
helper.setTo(InternetAddress.parse("SomeAddress#gmail.com"));
helper.setText("Good day!\nIn attachment payments for " + fileDate + " с 12.00-00.00" + "\nAmount for " + fileDate1 + list1);
helper.addAttachment("...xlsx", file);
mailSender.send(mimeMessage);
System.out.println("email Fab was successfully sent.....");
}
};
try {
mailSender.send(preparator);
} catch (MailException ex) {
System.err.println(ex.getMessage());
}
}
}
Controller
#Component
public class DateFMailController {
#Autowired
private DateFMailService mailService;
public void saveSum() throws IOException {
saveExcel(mailService.findAll(), "....xlsx");
}
private void saveExcel(List<DateFMail> list, String fileName) throws IOException {
Workbook workbook = new XSSFWorkbook();
CreationHelper createHelper = workbook.getCreationHelper();
Sheet sheet = workbook.createSheet("ECards");
sheet.autoSizeColumn(0);
Row header = sheet.createRow(0);
CellStyle headerStyle = workbook.createCellStyle();
headerStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex());
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
XSSFFont font = ((XSSFWorkbook) workbook).createFont();
font.setFontName("Arial");
font.setFontHeightInPoints((short) 10);
font.setBold(true);
headerStyle.setFont(font);
Cell headerCell = header.createCell(0);
headerCell.setCellValue("Sum");
headerCell.setCellStyle(headerStyle);
CellStyle style = workbook.createCellStyle();
style.setWrapText(true);
int ix_row=2;
for (DateFMail dateFMail : list) {
Row row = sheet.createRow(ix_row);
Cell cell = row.createCell(0);
cell.setCellValue(dateFMail.getBalance());
cell.setCellStyle(style);
ix_row++;
}
FileOutputStream outputStream = new FileOutputStream(fileName);
workbook.write(outputStream);
workbook.close();
}
}
Save Runer
#Component
public class SaveCardsStartupRunner implements ApplicationRunner {
#Autowired
private ECardController eCardController;
private DateFMailController controller;
// #Autowired
// private EmailDos emailDos;
String fileDate1 = new SimpleDateFormat("dd.MM.yyyy").format(new Date());
LocalDate today = LocalDate.now();
String fileDate = (today.minusDays(1)).format(DateTimeFormatter.ofPattern("dd MMM"));
String fileDate2 = (today.minusMonths(1)).format(DateTimeFormatter.ofPattern("MMM"));
#Override
public void run(ApplicationArguments args) throws Exception {
eCardController.saveCards();
controller.saveSum();
}
}
I have corrected my question. I've pasted all the code here that pertains to my question. For starters, I would like to simply output the Query result of the repository to the console. But in the form that I just posted here, I get a NullPointerException error and says that in a part of the code: controller.saveSum (); - controller = null.
Create a PaymentService class which should contain the method getTotalPayment. Inject this class in EmailSend (tip: please change this class name from EmailSend to EmailSender as class names should be noun) class. And then in PaymentService Class you should interact Data Repository class. Call this getTotalPayment method from the EmailSend class.

How do I insert values of elements that are part of the EmbeddedId in JPA?

I have a case where I need to execute an insert statement via createNativeQuery. I have an entity list I'm looping through in order to set the properties accordingly from another bean class, and then persist that data to the oracle database.
The problem I am facing is persisting the data that is part of the embeddedId (item, loc, weekstart, type, forecastId, insertTS). I need to persist that data for the new records to be inserted into the database. When I try to set the values from the POJO bean to my set method for the properties of my entity bean, nothing happens. Below is my code for setting the values of the properties from the POJO bean to my entity bean, along with my persistence method and the insert query being executed:
Validation class where validation occurs beforehand (missing to get the point) that includes the setting of my entity properties from the POJO bean:
List <InsertPromoData> insertPromos = new ArrayList<InsertPromoData>();
promo.forEach(record -> {
if (record.getErrorList().size() == 0) {
rowsSuccessful++;
Util.writeSuccessToFile(templateCd, successFile, record, successFields);
try {
InsertPromoData insertData = new InsertPromoData();
insertData.getId().setItem(record.getItem());
insertData.getId().setLoc(record.getLoc());
insertData.getId().setWeekStart(record.getWeek_Start_Date());
insertData.setNumberOfWeeks(record.getNumber_Of_Weeks());
insertData.getId().setType(record.getType());
insertData.getId().setForecastId(record.getForecast_ID());
insertData.setQty(record.getUnits());
insertPromos.add(insertData);
}
catch (Exception e) {
logger.error("Error with setting insertPromolist from promo list values and the error is " + e.getMessage());
}
}
else {
if (rowsFailure == 0) {
Util.writeHeaderToFile(templateCd, errorFile);
}
rowsFailure++;
Util.writeErrorToFile(templateCd, errorFile, record, record.getErrorList());
}
});
errorFile.close();
successFile.close();
OracleImpl.insertPromoData(insertPromos);
POJO bean (promo is the variable representing this list of beans in validation class above):
public class PromoBean extends ErrorListBean
{
public String Item;
public String Loc;
public String Week_Start_Date;
public String Units;
public String Forecast_ID;
public String Type;
public String Number_Of_Weeks;
public String getItem() {
return Item;
}
public void setItem(String item) {
Item = item;
}
public String getLoc() {
return Loc;
}
public void setLoc(String loc) {
Loc = loc;
}
public String getWeek_Start_Date() {
return Week_Start_Date;
}
public void setWeek_Start_Date(String week_Start_Date) {
Week_Start_Date = week_Start_Date;
}
public String getNumber_Of_Weeks() {
return Number_Of_Weeks;
}
public void setNumber_Of_Weeks(String number_Of_Weeks) {
Number_Of_Weeks = number_Of_Weeks;
}
public String getType() {
return Type;
}
public void setType(String type) {
Type = type;
}
public String getForecast_ID() {
return Forecast_ID;
}
public void setForecast_ID(String forecast_ID) {
Forecast_ID = forecast_ID;
}
public String getUnits() {
return Units;
}
public void setUnits(String units) {
Units = units;
}
}
Embeddable class representing the composite primary key of the table:
#Embeddable
public class PromoID implements Serializable {
#Column(name = "ITEM")
private String item;
#Column(name = "LOC")
private String loc;
#Column(name = "WK_START")
private String weekStart;
#Column(name = "TYPE")
private String type;
#Column(name = "FCSTID")
private String forecastId;
#Column(name = "U_TIMESTAMP")
private String insertTS;
public PromoID() {
}
public PromoID (String item, String loc, String weekStart, String type, String forecastId, String insertTS) {
this.item = item;
this.loc = loc;
this.weekStart = weekStart;
this.type = type;
this.forecastId = forecastId;
this.insertTS = insertTS;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public String getWeekStart() {
return weekStart;
}
public void setWeekStart(String weekStart) {
this.weekStart = weekStart;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getForecastId() {
return forecastId;
}
public void setForecastId(String forecastId) {
this.forecastId = forecastId;
}
public String getInsertTS() {
return insertTS;
}
public void setInsertTS(String insertTS) {
this.insertTS = insertTS;
}
//hashcode and equals methods
Persistence Bean:
#Entity
#Table(name = "U_USER_PROMO")
public class InsertPromoData {
#EmbeddedId
private PromoID id;
#Column(name="NUMBER_OF_WEEKS")
String numberOfWeeks;
#Column(name="QTY")
String qty;
#Id
#AttributeOverrides(
{
#AttributeOverride(name = "item",column = #Column(name="ITEM")),
#AttributeOverride(name = "loc", column = #Column(name="LOC")),
#AttributeOverride(name = "weekStart", column = #Column(name="WK_START")),
#AttributeOverride(name = "type", column = #Column(name="TYPE")),
#AttributeOverride(name = "forecastId", column = #Column(name="FCSTID"))
}
)
public PromoID getId() {
return id;
}
public void setId(PromoID id) {
this.id = id;
}
public String getNumberOfWeeks() {
return numberOfWeeks;
}
public void setNumberOfWeeks(String numberOfWeeks) {
this.numberOfWeeks = numberOfWeeks;
}
public String getQty() {
return qty;
}
public void setQty(String qty) {
this.qty = qty;
}
}
DAO class method to execute the update (entitymanagerfactory emf already initialized):
public static void insertPromoData(List<InsertPromoData> insertData) {
logger.debug("Execution of method insertPromoData in Dao started");
System.out.println("Size of the insertData list is " + insertData.size());
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
System.out.println("Beginning transaction for insertPromoData");
Query query = em.createNativeQuery(env.getProperty("insertPromoUploadData"));
for (InsertPromoData promoData : insertData) {
query.setParameter("item", promoData.getId().getItem());
query.setParameter("location", promoData.getId().getLoc());
query.setParameter("wkStart", promoData.getId().getWeekStart());
query.setParameter("numberOfWeeks", promoData.getNumberOfWeeks());
query.setParameter("type", promoData.getId().getType());
query.setParameter("fcstId", promoData.getId().getForecastId());
query.setParameter("quantity", promoData.getQty());
query.executeUpdate();
}
em.getTransaction().commit();
}
catch(Exception e) {
logger.error("Exception in beginning transaction");
e.printStackTrace();
}
finally {
em.clear();
em.close();
}
logger.debug("Execution of method insertPromoData in Dao ended");
}
Query in properties file:
insertPromoUploadData = INSERT INTO {h-schema}U_USER_PROMO (ITEM, LOC, WK_START, NUMBER_OF_WEEKS, TYPE, FCSTID, QTY, U_TIMESTAMP) VALUES (:item, :location, TO_DATE(:wkStart,'MM DD YYYY'), :numberOfWeeks, :type, :fcstId, :quantity, SYSDATE)
My list size from my DAO class is returning as 0 once I begin the transaction and not sure why it is empty. Is there a reason that it is empty? I'm trying to persist each of the fields to the database (including the composite key fields) via insert query. Any help appreciated.
After looking into this for hours, I finally came to the conclusion that the simplest way to executeUpdate() without running into issues due to my current #EmbeddedId/#Embeddable logic was to change it to use #IdClass for my composite PK class, and annotate the fields from the PK in my entity with #Id. This allowed my data to be persisted to the database. Another slight difference was adding the insertTS in my entity class and annotating with #Id and generating getters/setters. This was necessary for JPA to recognize all the properties being referenced that I am wanting to persist, though I am persisting insertTS using SYSDATE function from the oracle DB instead of utilizing the get/set methods and setting to the current time from the java side.
I am sure there is a way to use #EmbeddedId/#Embeddable logic and be able to persist the fields that are part of the EmbeddedId, however, this I found to be a more simplistic way of doing it without further complexity in the code.

Fetching image from MySQL database in Spring boot and thymeleaf

I am trying to create a service which fetch image of a student along with other text details of student stored in database and display it on an html page. I tried but some hash value is being returned.
My Model Class
#Entity
#Table(name = "details")
public class Student {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "name")
private String name;
#Column(name = "pic" , length = 2000)
private byte[] pic;
public Student(long id, String name, byte[] pic) {
super();
this.id = id;
this.name = name;
this.pic = pic;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public byte[] getPic() {
return pic;
}
public void setPic(byte[] pic) {
this.pic = pic;
}
#Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "];
}
}
Without Using a rest contoller will it be achieved like this?
My Controller
#Controller
public class ImgShowController {
#Autowired
EntityRepository entityRepository;
#RequestMapping("/list")
public String getAllStudents(Model model) {
List<Imge> list = (List<Imge>) entityRepository.findAll();
model.addAttribute("students", list);
return "liststudents";
}
#RequestMapping(path= {"/particularlist","/particularlist/{id}"})
public String getImage(#PathVariable("id") Long id, Model model) {
final Optional<Student> imget = entityRepository.findById(id);
Imge imge = new Imge(imget.get().getId(), imget.get().getName(), decompressBytes(imget.get().getPic()));
model.addAttribute("particularStudent", imge);
return "particularstudent";
}
}
Decompress Byte function
public static byte[] decompressBytes(byte[] data) {
Inflater inflater = new Inflater();
inflater.setInput(data);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
byte[] buffer = new byte[1024];
try {
while (!inflater.finished()) {
int count = inflater.inflate(buffer);
outputStream.write(buffer, 0, count);
}
outputStream.close();
} catch (IOException ioe) {
} catch (DataFormatException e) {
}
return outputStream.toByteArray();
}
First of all, I would suggest mentioning that you store binary object (LOB) in pic column in your entity class:
#Lob
#Column(name = "pic" , length = 2000)
private byte[] pic;
And then, it seems that Thymeleaf does not allow you to inject image directly into model, so you have 2 ways to accomplish this:
1.Adding another controller to serve you images
#GetMapping("/students/{id}/image")
public void studentImage(#PathVariable String id, HttpServletResponse response) throws IOException {
var student = entityRepository.findById(id);
var imageDecompressed = decompressBytes(student.get().getPic());
response.setContentType("image/jpeg");
InputStream is = new ByteArrayInputStream(imageDecompressed);
IOUtils(is, response.getOutputStream());
}
and then referring to it from model like this:
<img th:src="#{'students/' + #{studentId} + '/image'}">
2.Using base64
You need to encode image as base64 string:
var base64EncodedImage = Base64.getEncoder().encodeToString(imageData);
and then setting into model like this:
<img th:src="#{'data:image/jpeg;base64,'+${base64EncodedImage}}"/>
I would suggest using the first way because otherwise you would depend on image size and overall payload would be 30% larger (base64), so by using the first way you let user's browser decide how and when to load particular image

Jackson: how to put a space after a separator when I serialize a List

Which options should I use to put a space after a comma separator when I serialize a List?
What I have investigated:
I can use #JsonSerialize(contentUsing = MyCustomSerializer.class)
on the top of a List field.
Or somehow set up ObjectMapper with .writer(PrettyPrinter pp).
Neither of the options seems suitable.
The result of the serialization I have is {"inq":["2","35"]}. And I want to have: {"inq":["2", "35"]}. With a space after the comma.
Any suggestions are highly appreciated.
just extend MinimalPrettyPrinter
public class TestObjectMapper2 {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue("{\"name\":\"frank\",\"age\":20,\"inq\":[\"2\",\"35\"]}",Person.class);
System.out.println(mapper.writer(new MinimalPrettyPrinter(){
#Override
public void writeObjectEntrySeparator(JsonGenerator jg)
throws IOException
{
jg.writeRaw(',');
jg.writeRaw(' ');
}
#Override
public void writeArrayValueSeparator(JsonGenerator jg)
throws IOException
{
jg.writeRaw(',');
jg.writeRaw(' ');
}
}).writeValueAsString(person));
}
private static class Person{
#Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
private String name;
private Integer age;
private List<String> inq;
public List<String> getInq()
{
return inq;
}
public void setInq(List<String> inq)
{
this.inq = inq;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
}
output: {"name":"frank", "age":20, "inq":["2", "35"]}

Accessing Subclass properties in a JavaFX TableView ObservableArrayList

I am trying to access getter properties in a subclass with a TableView in JavaFX. I have the following class:
public class PersonType implements Serializable {
private static final long serialVersionUID = 1L;
Person person;
short count;
public PersonType() {
}
public PersonType(Person person, short count) {
super();
this.person = person;
this.count = count;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public short getCount() {
return count;
}
public void setCount(short count) {
this.count = count;
}
Person is like this:
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
String firstName;
String lastName;
public Person() {
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
Okay - lastly we have the following:
#FXML
private TableColumn tcFirstName;
#FXML
private TableColumn tcLastName;
#FXML
private TableView tblPersonTypes;
ArrayList<PersonType> pType = new ArrayList<PersonType>();
//Can assume that pType here has say 5 entries, the point of this
//is I'm trying to get to the firstName, lastName properties of the
//PersonType in the TableView below like the following:
tcFirstName.setCellValueFactory(new PropertyValueFactory<String,String>("firstName"));
tcLastName.setCellValueFactory(new PropertyValueFactory<String,String>("lastName"));
//Populate Table with Card Records
ObservableList<PersonType> data = FXCollections.observableArrayList(pType);
tblPersonTypes.setItems(data);
And I'm unsure how with a list of PersonTypes I can tell the table columns that I want the firstName and lastName properties of the Person object contained within. I know I could create a new object, and have the "count" from PersonTypes, then the other properties of "firstName", "lastName" etc without having an object property of Person. Any help would be greatly appreciated.
-- EDIT --
Another way I thought to do this was using CellFactories - where I would pass in to the CellValueFactories the Person object, then set the CellFactory to return a String value (firstName for the first name column, etc). And it would look like this:
tcFirstName.setCellValueFactory(new PropertyValueFactory<Person,String>("person"));
tcFirstName.setCellFactory(new Callback<TableColumn<Person,String>,TableCell<Person,String>>(){
#Override
public TableCell<Person,String> call(TableColumn<Person,String> param) {
TableCell<Person,String> cell = new TableCell<Person,String>(){
#Override
public void updateItem(String item, boolean empty) {
if(item!=null){
setGraphic(new Label(item.getFirstName()));
}
}
};
return cell;
}
});
Try this:
tcFirstName.setCellValueFactory(new Callback<CellDataFeatures<PersonType, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<PersonType, String> p) {
// p.getValue() returns the PersonType instance for a particular TableView row
if (p.getValue() != null && p.getValue().getPerson() != null) {
return new SimpleStringProperty(p.getValue().getPerson().getFirstName());
} else {
return new SimpleStringProperty("<No TC firstname>");
}
}
});
}

Resources