Related
Issue:
I am using eloquent to pull students from a database where they have specific status and registration date values. They must also only be shown if sub-table data as specific column data as well.
The issue is that Laravel is breaking it up into multiple queries and the "with" (eager loading) tables are only getting filtered after the fact.
In other words, instead of (pseudo sql):
SELECT all students WHERE
status IN (1,4,6,7)
AND (YEAR(registration_date)<=2020 OR YEAR(registration_date) IS NULL)
AND YEAR(commencement_date)>=2020
AND (YEAR(completion_date)>=2020 OR YEAR(estimated_completion_date)>=2020)
Its pushing out 4 separate sql statements (refer to 'resulting SQL' below) where its only applying the status / registration_date filter on students, and separately the other filters down the line which causes the actual row results to be incorrect (displaying more than they should).
I would just use DB::table / DB:raw - but then on the blade end of things, I cant pull sub-child data because its no longer in a hierarchal structure.
Code:
DB::enableQueryLog();
$students = $bursary_administrator->students()->whereIn('status',[1,4,6,7])
->whereHas('bursaries', function($query) use ($request) {
$query->whereYear('registration_date','<=',$request->year)
->orWhereNull('registration_date');
})
->with(['bursaries','bursaries.enrolments','bursaries.enrolments.courses' => function($query) use ($request) {
$query->whereYear('commencement_date', '<=', $request->year)
->where(function ($query) use ($request){
$query->whereYear('completion_date', '>=', $request->year)
->whereYear('estimated_completion_date', '>=', $request->year,'or');
});
}])
->orderBy('student_name')->orderBy('student_middle_names')->orderBy('student_surname')->get();
Log::debug(DB::getQueryLog());
Resulting SQL:
local.DEBUG: array (
0 =>
array (
'query' => 'select `students`.*, `bursary_administrator_student`.`bursary_administrator_id` as `pivot_bursary_administrator_id`, `bursary_administrator_student`.`student_id` as `pivot_student_id`, `bursary_administrator_student`.`created_at` as `pivot_created_at`, `bursary_administrator_student`.`updated_at` as `pivot_updated_at` from `students` inner join `bursary_administrator_student` on `students`.`id` = `bursary_administrator_student`.`student_id` where `bursary_administrator_student`.`bursary_administrator_id` = ? and `status` in (?, ?, ?, ?) and exists (select * from `student_bursaries` where `students`.`id` = `student_bursaries`.`student_id` and (year(`registration_date`) <= ? or `registration_date` is null)) order by `student_name` asc, `student_middle_names` asc, `student_surname` asc',
'bindings' =>
array (
0 => 1,
1 => 1,
2 => 4,
3 => 6,
4 => 7,
5 => '2020',
),
'time' => 6.69,
),
1 =>
array (
'query' => 'select * from `student_bursaries` where `student_bursaries`.`student_id` in (1, 3, 14, 20, 24, 25, 29, 41, 42, 44, 49, 51, 53, 55, 56, 62, 64, 65, 72, 75, 76, 80, 81, 85, 94, 98, 100, 106, 111, 112, 133, 138, 139, 141, 156, 157, 169, 170, 180, 199, 203, 210, 213, 214, 217, 219, 221, 224, 225, 226, 227, 228, 229, 231, 232, 233, 234, 235, 237, 238, 239, 240, 242, 243, 246, 249, 251, 252, 253, 254, 255, 256, 257, 258, 260, 261, 262, 263, 265, 267, 268, 269, 270, 271, 273, 274, 275, 276, 277, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 297, 299, 300, 302, 303, 304, 305, 306, 307, 308, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 333, 334, 335, 336, 337, 338, 339, 340, 341, 343, 344, 345, 346, 347, 348, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364)',
'bindings' =>
array (
),
'time' => 2.41,
),
2 =>
array (
'query' => 'select * from `student_bursary_enrolments` where `student_bursary_enrolments`.`student_bursary_id` in (1, 3, 14, 20, 24, 25, 29, 41, 42, 44, 49, 51, 53, 55, 56, 62, 64, 65, 72, 75, 76, 80, 81, 85, 94, 98, 100, 106, 111, 112, 133, 138, 139, 141, 156, 157, 169, 170, 180, 199, 203, 210, 213, 214, 217, 219, 221, 224, 225, 226, 227, 228, 229, 231, 232, 233, 234, 235, 237, 238, 239, 240, 242, 243, 246, 249, 251, 252, 253, 254, 255, 256, 257, 258, 260, 261, 262, 263, 265, 267, 268, 269, 270, 271, 273, 274, 275, 276, 277, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 297, 299, 300, 302, 303, 304, 305, 306, 307, 308, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 333, 334, 335, 336, 337, 338, 339, 340, 341, 343, 344, 345, 346, 347, 348, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364)',
'bindings' =>
array (
),
'time' => 2.41,
),
3 =>
array (
'query' => 'select * from `student_bursary_enrolment_courses` where `student_bursary_enrolment_courses`.`student_bursary_enrolment_id` in (1, 3, 12, 18, 19, 21, 22, 27, 28, 38, 39, 40, 41, 42, 43, 48, 50, 52, 53, 55, 56, 57, 64, 65, 66, 67, 72, 75, 76, 77, 81, 82, 85, 93, 96, 98, 99, 104, 110, 111, 130, 134, 135, 136, 138, 152, 153, 154, 164, 165, 175, 180, 181, 187, 193, 194, 195, 196, 200, 201, 202, 203, 204, 205, 206, 209, 210, 211, 212, 213, 214, 215, 216, 219, 220, 221, 222, 223, 224, 225, 226, 227, 230, 231, 232, 233, 234, 235, 238, 239, 240, 241, 242, 247, 248, 252, 253, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 273, 274, 275, 276, 277, 278, 279, 280, 283, 284, 285, 286, 287, 288, 289, 290, 292, 293, 294, 295, 296, 297, 298, 299, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 331, 332, 333, 334, 335, 336, 337, 338, 339, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 371, 372, 373, 374, 375, 376, 377, 378, 379, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 409, 411, 413, 414, 415, 417, 418, 419, 424, 429, 431, 432, 433, 436, 442, 443, 445, 447, 448, 450, 452, 453, 456, 457, 466, 467, 468, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485) and year(`commencement_date`) <= ? and (year(`completion_date`) >= ? or year(`estimated_completion_date`) >= ?)',
'bindings' =>
array (
0 => '2020',
1 => '2020',
2 => '2020',
),
'time' => 2.85,
),
)
Blade / View:
<tbody>
#if ($students)
#php($row_count=0)
#foreach ($students as $student)
#php($row_count++)
<tr>
<td>{{$row_count}}</td>
<td>{{$student->student_name .' '. $student->student_middle_names .' '. $student->student_surname}}</td>
<td colspan="4">
#if ($student->bursaries)
<table class="subtable">
#foreach ($student->bursaries as $bursary)
#if ($bursary->enrolments)
#foreach ($bursary->enrolments as $enrolment)
#if ($enrolment->courses)
#foreach ($enrolment->courses as $course)
<tr>
<td>{{$enrolment->academic_institution->academic_institution .' - '. $course->course}}</td>
<td class="f114">{{__($course->current_year)}}</td>
</tr>
#endforeach
#else
<tr><td>Error: No courses</td></tr>
#endif
#endforeach
#else
<tr><td>Error: No enrolments</td></tr>
#endif
#endforeach
</table>
#else
Error: No bursaries
#endif
</td>
</tr>
#endforeach
#endif
</tbody>
This is the migration code but it gives this error
( Class 'Modules\RolePermission\Entities\InfixPermissionAssign' not found )
I have checked the names everything is right and the path is also correct appreciate your help.
I have copied this code from another project it was working there. Everything is same here too but still it doesn't work here.
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Modules\RolePermission\Entities\InfixModuleInfo;
use Modules\RolePermission\Entities\InfixModuleStudentParentInfo;
use Modules\RolePermission\Entities\InfixPermissionAssign;
class CreateInfixPermissionAssignsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('infix_permission_assigns', function (Blueprint $table) {
$table->increments('id');
$table->tinyInteger('active_status')->default(1);
$table->timestamps();
$table->integer('module_id')->nullable()->comment(' module id, module link id, module link options id');
$table->string('module_info')->nullable();
$table->integer('role_id')->nullable()->unsigned();
$table->foreign('role_id')->references('id')->on('infix_roles')->onDelete('cascade');
$table->text('saas_schools')->nullable();
$table->integer('created_by')->nullable()->default(1)->unsigned();
$table->integer('updated_by')->nullable()->default(1)->unsigned();
$table->integer('school_id')->nullable()->default(1)->unsigned();
$table->foreign('school_id')->references('id')->on('sm_schools')->onDelete('cascade');
});
// for admin
$admins = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83, 84, 85, 86, 533, 534, 535, 536, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 214, 215, 216, 217, 218, 219, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 537, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 538, 539, 540, 485, 486, 487, 488, 489, 490, 491, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570];
foreach ($admins as $key => $value) {
$permission = new Modules\RolePermission\Entities\InfixPermissionAssign();
$permission->module_id = $value;
$permission->module_info = InfixModuleInfo::find($value)->name;
$permission->role_id = 5;
$permission->save();
}
// for teacher
$teachers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83, 84, 85, 86, 533, 534, 535, 536, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 214, 215, 216, 217, 218, 219, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 537, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 277, 278, 279, 280, 281, 282, 283, 284, 285, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567];
foreach ($teachers as $key => $value) {
$permission = new InfixPermissionAssign();
$permission->module_id = $value;
$permission->module_info = InfixModuleInfo::find($value)->name;
$permission->role_id = 4;
$permission->save();
}
// for receiptionists
$receiptionists = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 65, 66, 67, 83, 84, 85, 86, 160, 161, 162, 163, 164, 188, 193, 194, 195, 376, 377, 378, 379, 380, 553, 554, 560, 564];
foreach ($receiptionists as $key => $value) {
$permission = new InfixPermissionAssign();
$permission->module_id = $value;
$permission->module_info = InfixModuleInfo::find($value)->name;
$permission->role_id = 7;
$permission->save();
}
// for librarians
$librarians = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 61, 64, 65, 66, 67, 83, 84, 85, 86, 160, 161, 162, 163, 164, 188, 193, 194, 195, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 376, 377, 378, 379, 380, 553, 554, 560, 564];
foreach ($librarians as $key => $value) {
$permission = new InfixPermissionAssign();
$permission->module_id = $value;
$permission->module_info = InfixModuleInfo::find($value)->name;
$permission->role_id = 8;
$permission->save();
}
// for drivers
$drivers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 188, 193, 194, 19, 553, 554, 560, 564];
foreach ($drivers as $key => $value) {
$permission = new InfixPermissionAssign();
$permission->module_id = $value;
$permission->module_info = InfixModuleInfo::find($value)->name;
$permission->role_id = 9;
$permission->save();
}
// for accountants
$accountants = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 65, 66, 67, 68, 69, 70, 83, 84, 85, 86, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 188, 193, 194, 195, 376, 377, 378, 379, 380, 381, 382, 383, 553, 554, 560, 564];
foreach ($accountants as $key => $value) {
$permission = new InfixPermissionAssign();
$permission->module_id = $value;
$permission->module_info = InfixModuleInfo::find($value)->name;
$permission->role_id = 6;
$permission->save();
}
// student
for ($j = 1; $j <= 55; $j++) {
$permission = new InfixPermissionAssign();
$permission->module_id = $j;
$permission->module_info = InfixModuleInfo::find($value)->name;
$permission->role_id = 2;
$permission->save();
}
$students = [554, 555, 559, 564];
foreach ($students as $key => $value) {
$permission = new InfixPermissionAssign();
$permission->module_id = $value;
$permission->module_info = InfixModuleInfo::find($value)->name;
$permission->role_id = 2;
$permission->save();
}
// parent
for ($j = 56; $j <= 96; $j++) {
$permission = new InfixPermissionAssign();
$permission->module_id = $j;
$permission->module_info = InfixModuleInfo::find($value)->name;
$permission->role_id = 3;
$permission->save();
}
$students = [554, 555, 560, 559, 564];
foreach ($students as $key => $value) {
$permission = new InfixPermissionAssign();
$permission->module_id = $value;
$permission->module_info = InfixModuleInfo::find($value)->name;
$permission->role_id = 3;
$permission->save();
}
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('infix_permission_assigns');
}
}
Have you checked the namespace and the permission of the file? Make sure the namespace and permission and owner of the file is correct. In my cases, sometimes both of those problem were the one when everything just 'seems' to be in order.
I have the below code in a bat file to wrap all the packages present in a folder where the bat file was executed.
#echo off
for /R %%f in (*.pkb) do (
wrap iname="%%~dpnxf" oname="%%~dpnf.plb"
DEL %%~dpnxf
)
Can anyone please suggest a way to unwrap all the packages present in that folder?
There are some tools that could help you.
Python: unwrap.py
Java: unwrapper-for-sql-developer
Probably, the Python script is easier to use from terminal.
Java solution is in fact a plugin presented as a *.jar, but it is quite simple to extract the essential part from it.
All you need for this task is 5 *.class files in the com.trivadis.unwrapper.util package.
Maybe decompiling them could make the picture clear.
To unwrap one package just call
String wrappedCode = ???.getPackageCode();
String sourceCode = Unwrapper.unwrap(wrappedCode);
The basic algorithm is as follows:
package com.trivadis.unwrapper.util;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.DataFormatException;
public class Unwrapper {
private static int[] charmap = new int[]{61, 101, 133, 179, 24, 219, 226, 135, 241, 82, 171, 99, 75, 181, 160, 95, 125, 104, 123, 155, 36, 194, 40, 103, 138, 222, 164, 38, 30, 3, 235, 23, 111, 52, 62, 122, 63, 210, 169, 106, 15, 233, 53, 86, 31, 177, 77, 16, 120, 217, 117, 246, 188, 65, 4, 129, 97, 6, 249, 173, 214, 213, 41, 126, 134, 158, 121, 229, 5, 186, 132, 204, 110, 39, 142, 176, 93, 168, 243, 159, 208, 162, 113, 184, 88, 221, 44, 56, 153, 76, 72, 7, 85, 228, 83, 140, 70, 182, 45, 165, 175, 50, 34, 64, 220, 80, 195, 161, 37, 139, 156, 22, 96, 92, 207, 253, 12, 152, 28, 212, 55, 109, 60, 58, 48, 232, 108, 49, 71, 245, 51, 218, 67, 200, 227, 94, 25, 148, 236, 230, 163, 149, 20, 224, 157, 100, 250, 89, 21, 197, 47, 202, 187, 11, 223, 242, 151, 191, 10, 118, 180, 73, 68, 90, 29, 240, 0, 150, 33, 128, 127, 26, 130, 57, 79, 193, 167, 215, 13, 209, 216, 255, 19, 147, 112, 238, 91, 239, 190, 9, 185, 119, 114, 231, 178, 84, 183, 42, 199, 115, 144, 102, 32, 14, 81, 237, 248, 124, 143, 46, 244, 18, 198, 43, 131, 205, 172, 203, 59, 196, 78, 192, 105, 54, 98, 2, 174, 136, 252, 170, 66, 8, 166, 69, 87, 211, 154, 189, 225, 35, 141, 146, 74, 17, 137, 116, 107, 145, 251, 254, 201, 1, 234, 27, 247, 206};
public Unwrapper() {
}
public static String unwrap(String wrapped) throws DataFormatException, IOException, NoSuchAlgorithmException {
String wrappedUnix = wrapped.replace("\r\n", "\n");
Pattern lengthPattern = Pattern.compile("([\n][0-9a-f]+[ ])([0-9a-f]+[\n])");
Matcher m = lengthPattern.matcher(wrappedUnix);
if (!m.find(0)) {
throw new RuntimeException("Could not unwrap this code. Most probably it was not wrapped with the Oracle 10g, 11g or 12c wrap utility.");
} else {
int encodedCodeLength = Integer.parseInt(m.group(2).trim(), 16);
int expectedLength = m.end() + encodedCodeLength;
if (expectedLength > wrappedUnix.length()) {
throw new RuntimeException("Wrapped code seems to be truncated. Expected length of " + expectedLength + " characters but got only " + wrappedUnix.length() + ".");
} else {
String encoded = wrappedUnix.substring(m.end(), expectedLength);
byte[] decoded = Base64Coder.decodeLines(encoded);
byte[] remapped = new byte[decoded.length];
for(int i = 0; i < decoded.length; ++i) {
int unsignedInteger = decoded[i] & 255;
remapped[i] = (byte)charmap[unsignedInteger];
}
byte[] hash = Arrays.copyOfRange(remapped, 0, 20);
byte[] zipped = Arrays.copyOfRange(remapped, 20, remapped.length);
byte[] calculatedHash = HashCalculator.getSHA1(zipped);
if (!Arrays.equals(hash, calculatedHash)) {
throw new RuntimeException("SHA-1 hash values do not match. Expected '" + HashCalculator.bytesToHex(hash) + "' but got '" + HashCalculator.bytesToHex(calculatedHash) + "'. Cannot unwrap code.");
} else {
byte[] unzipped = Unzipper.unzip(zipped);
int size;
for(size = unzipped.length; size > 0 && unzipped[size - 1] == 0; --size) {
}
return new String(unzipped, 0, size);
}
}
}
}
}
I am new to Websphere MQ (IBM z/OS) technologies. We had a requirement to implement a standalone application that uses JMS technology to connect to an MQ server (on IBM z/OS. This is maintained by a different organization for which we have only limited access) and put a message on the queue.
Here are pieces of my code below.
private void sendMessage(String queue, String msg) {
JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
JmsConnectionFactory cf = ff.createConnectionFactory();
cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, host);
cf.setIntProperty(WMQConstants.WMQ_PORT, port);
cf.setStringProperty(WMQConstants.WMQ_CHANNEL, channel);
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, queueManagerName);
cf.setStringProperty(WMQConstants.USERID, user);
cf.setStringProperty(WMQConstants.PASSWORD, password);
Connection connection = null;
Session session = null;
Destination destination = null;
MessageProducer producer = null;
connection = cf.createConnection(user, password);
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue(queue);
//((MQDestination)destination).setCCSID(37);
producer = session.createProducer(destination);
TextMessage message = session.createTextMessage();
message.setIntProperty(WMQConstants.JMS_IBM_CHARACTER_SET, 37);
//message.setIntProperty(WMQConstants.JMS_IBM_ENCODING, 785);
message.setText(msg);
// Start the connection
connection.start();
// And, send the message
producer.send(message);
}
I was successfully able to connect to the MQ server on the other end and put the messages on the remote server in ASCII format. I was able to consume the message that I have put on the queue from an AIX server.
But since the MQ is running on z/OS and the consumer is also an Mainframe application the message I put appears to be a garbage/unreadable format. After some research I figured out that messages needs to be converted to EBCDIC to be put on z/OS MQ. I expected that this will be taken care of by the IBM MQ libraries.
Please help on how can I put the messages in EBCDIC format.
You are doing this wrong:
message.setIntProperty(WMQConstants.JMS_IBM_CHARACTER_SET, 37);
You need to declare the character set that you are putting on the queue. Since that looks like Java, I'm assuming it is a UTF-16 string. Declare it as 1208, not 37.
On the other end, if they want it in EBCDIC, they will do a GET-With-Convert, declaring that they want to receive it in IBM 37/1140 and MQ will invoke Unicode Conversion Services for z/OS and make it happen.
More importantly, if your receiver is not a Java client, you need to disable the JMS header as follows:
destination = session.createQueue("queue:///" + queue + "?targetClient=1")
or by invoking the Native MQ implementation :
((MQDestination)destination).setMessageBodyStyle(WMQConstants.WMQ_MESSAGE_BODY_MQ)
See:
https://www-01.ibm.com/support/knowledgecenter/SSFKSJ_8.0.0/com.ibm.mq.dev.doc/q032120_.htm
https://www-01.ibm.com/support/knowledgecenter/SSFKSJ_8.0.0/com.ibm.mq.dev.doc/q032140_.htm?lang=en
http://www-01.ibm.com/support/knowledgecenter/SSFKSJ_7.0.1/com.ibm.mq.csqzaw.doc/jm10910_.htm
To store your message in a non-standard-encoding you will have to use BytesMessage instead of TextMessage. This might work (untested!):
byte[] messageBytes = msg.getBytes("IBM037");
BytesMessage message = session.createBytesMessage();
message.writeBytes(messageBytes);
But it would be preferable to have the given message-encoding respected at the consuming side - that's why you put it there.
If possible, use MQ's MQGMO convert option to convert into the local machine's character set. But if you want (or can't) use that mechanism, you can also implement your own character set translation to have full control. For example:
//---------------------------------------------------
//Character Translation Table for: IBM500
private static char[] EBCDIC2ASCII_IBM500 = new char[] {
0, 1, 2, 3, 156, 9, 134, 127, 151, 141, 142, 11, 12, 13, 14, 15,
16, 17, 18, 19, 157, 10, 8, 135, 24, 25, 146, 143, 28, 29, 30, 31,
128, 129, 130, 131, 132, 10, 23, 27, 136, 137, 138, 139, 140, 5, 6, 7,
144, 145, 22, 147, 148, 149, 150, 4, 152, 153, 154, 155, 20, 21, 158, 26,
32, 160, 226, 228, 224, 225, 227, 229, 231, 241, 91, 46, 60, 40, 43, 33,
38, 233, 234, 235, 232, 237, 238, 239, 236, 223, 93, 36, 42, 41, 59, 94,
45, 47, 194, 196, 192, 193, 195, 197, 199, 209, 166, 44, 37, 95, 62, 63,
248, 201, 202, 203, 200, 205, 206, 207, 204, 96, 58, 35, 64, 39, 61, 34,
216, 97, 98, 99, 100, 101, 102, 103, 104, 105, 171, 187, 240, 253, 254, 177,
176, 106, 107, 108, 109, 110, 111, 112, 113, 114, 170, 186, 230, 184, 198, 164,
181, 126, 115, 116, 117, 118, 119, 120, 121, 122, 161, 191, 208, 221, 222, 174,
162, 163, 165, 183, 169, 167, 182, 188, 189, 190, 172, 124, 175, 168, 180, 215,
123, 65, 66, 67, 68, 69, 70, 71, 72, 73, 173, 244, 246, 242, 243, 245,
125, 74, 75, 76, 77, 78, 79, 80, 81, 82, 185, 251, 252, 249, 250, 255,
92, 247, 83, 84, 85, 86, 87, 88, 89, 90, 178, 212, 214, 210, 211, 213,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 179, 219, 220, 217, 218, 159
};
private static char[] ASCII2EBCDIC_IBM500 = new char[] {
0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15,
16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31,
64, 79, 127, 123, 91, 108, 80, 125, 77, 93, 92, 78, 107, 96, 75, 97,
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 122, 94, 76, 126, 110, 111,
124, 193, 194, 195, 196, 197, 198, 199, 200, 201, 209, 210, 211, 212, 213, 214,
215, 216, 217, 226, 227, 228, 229, 230, 231, 232, 233, 74, 224, 90, 95, 109,
121, 129, 130, 131, 132, 133, 134, 135, 136, 137, 145, 146, 147, 148, 149, 150,
151, 152, 153, 162, 163, 164, 165, 166, 167, 168, 169, 192, 187, 208, 161, 7,
32, 33, 34, 35, 36, 0, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27,
48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62, 255,
65, 170, 176, 177, 159, 178, 106, 181, 189, 180, 154, 138, 186, 202, 175, 188,
144, 143, 234, 250, 190, 160, 182, 179, 157, 218, 155, 139, 183, 184, 185, 171,
100, 101, 98, 102, 99, 103, 158, 104, 116, 113, 114, 115, 120, 117, 118, 119,
172, 105, 237, 238, 235, 239, 236, 191, 128, 253, 254, 251, 252, 173, 174, 89,
68, 69, 66, 70, 67, 71, 156, 72, 84, 81, 82, 83, 88, 85, 86, 87,
140, 73, 205, 206, 203, 207, 204, 225, 112, 221, 222, 219, 220, 141, 142, 223
};
public static void main(String[] args)
{
String ebcdic = "" + (char)0xC1 + (char)0xC2 + (char)0xC3;
System.err.println("ebcdic: " + ebcdic);
String ascii = "";
for( char c: ebcdic.toCharArray() ) {
ascii += EBCDIC2ASCII_IBM500[c];
}
System.err.println("ascii: " + ascii);
ebcdic="";
for( char c: ascii.toCharArray() ) {
ebcdic += ASCII2EBCDIC_IBM500[c];
}
System.err.println("ebcdic: " + ebcdic);
}
And here's the code to create these tables:
public static void createTranslationTable(Charset charset)
{
System.out.println();
System.out.println("// ---------------------------------------------------" );
System.out.println("// Character Translation Tables for: " + charset.name() );
byte[] b = new byte[256];
for( int i=0;i<256;i++ ) b[i] = (byte)i;
String s = "";
try {
s = new String(b,charset.name());
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
int[] inverse = new int[256];
System.out.println("unsigned char EBCDIC2ASCII_" + charset.name() + "[256] = {");
for( int i=0;i<256;i++ ) {
int c = s.charAt(i); // %256;
if( c>255 ) c=i;
inverse[c] = i;
System.out.print( c + (i<255?", ":"") );
if( i%16==15 ) System.out.println();
}
System.out.println("};");
System.out.println("unsigned char ASCII2EBCDIC_" + charset.name() + "[256] = {");
for( int i=0;i<256;i++ ) {
int c = inverse[i]; // %256;
System.out.print( c + (i<255?", ":"") );
if( i%16==15 ) System.out.println();
}
System.out.println("};");
}
And you could use it like this:
createTranslationTable( Charset.forName("CP037") );
In my application I have several shapes that intersect with each other, for example, Shape A, Shape B and Shape C. A need to draw a polyline from Shape A to Shape C through Shape B, so the line lies inside all the shapes and crosses them almost at center.
What is the most efficient way to implement this? Here is the code of example: http://jsfiddle.net/dselkirk/ZMUkE/.
I need to draw a yellow line, but not manually:
var stage = new Kinetic.Stage({
container: 'container',
width: 850,
height: 750
});
var layer = new Kinetic.Layer({
x: 0,
y: 0
});
var rect = new Kinetic.Rect({
x: 100,
y: 100,
width: 80,
height: 60,
fill: '#E67E22'
});
var rect2 = new Kinetic.Rect({
x: 640,
y: 70,
width: 40,
height: 70,
fill: '#3498DB',
});
var circle = new Kinetic.Circle({
x: 600,
y: 150,
radius: 70,
fill: '#2ECC71',
});
var polyOne = new Kinetic.Polygon({
x: 80,
y: 100,
points: [73, 192, 73, 160, 340, 23, 500, 109, 499, 139, 342, 93],
fill: '#9B59B6'
});
var polyTwo = new Kinetic.Polygon({
x: 100,
y: 160,
points: [-5, 0, 75, 0, 70, 10, 70, 60, 60, 90, 61, 92, 64, 96, 66, 100, 67, 105, 67, 110, 67, 113, 66, 117, 64, 120, 63, 122, 61, 124, 58, 127, 55, 129, 53, 130, 50, 130, 20, 130, 17, 130, 15, 129, 12, 127, 9, 124, 7, 122, 6, 120, 4, 117, 3, 113, 3, 110, 3, 105, 4, 100, 6, 96, 9, 92, 10, 90, 0, 60, 0, 10],
fill: '#e74c3c'
});
var imageObj = new Image();
imageObj.onload = function () {
var yoda = new Kinetic.Image({
x: 120,
y: 120,
image: imageObj,
width: 15,
height: 18
});
// add the shape to the layer
layer.add(yoda);
stage.add(layer);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
var imageObj2 = new Image();
imageObj2.onload = function () {
var dart = new Kinetic.Image({
x: 650,
y: 80,
image: imageObj2,
width: 20,
height: 21
});
layer.add(dart);
stage.add(layer);
};
var yellowLine = new Kinetic.Line({
points: [{x:125,y:140},{x:125,y:280}, {x:425,y:150}, {x:555,y:220}, {x:655,y:100}],
stroke: 'yellow',
strokeWidth: 2,
lineJoin: 'round',
dashArray: [33, 10]
});
layer.add(polyOne);
layer.add(polyTwo);
layer.add(yellowLine);
layer.add(circle);
layer.add(rect);
layer.add(rect2);
stage.add(layer);
yellowLine.moveToTop();
For now I think the algorithm should be:
1) Find intersection points of all shapes.
2) Draw lines between these intersectiopn points. If any line point lies outside the shape - move it horizontally/vertically till it lies inside the shape.
But this algorithm seems not efficient at all.